Java-IO 字節流的使用和效率比較
打算做一個系列,前面講了基本的字符流的用法,這篇博客介紹一下字節流的基本用法:
一、基本使用:
基本字節流:
FileInputStream FileOutputStream
BufferedInputStream BufferedOutputStream
註意點,字節流和字符流的使用方式基本類似,有一點區別是使用字節流來讀寫文件是不需要使用flush函數的,原因:
1、字符流需要使用到flush函數將寫在緩沖區的字符沖到文件,因為字符流=編碼字典+字節流,事實上字符流讀取的還是字節,但是讀完一個字節之後它會根據字符集去查找相應的字符;
2、字節流直接操作的就是字節,所以它進行寫入的時候直接就寫入到文件中了,不需要再進行flush;
3、FileInputStream FileOutputStream是由繼承flush方法的,但是這個方法什麽也沒有做。在FileOutputStream中flush源碼是這樣子的:
public void flush() throws IOException { }
之所以還需要這個函數是子類可能是需要用到的。
下面是基本使演示用代碼:
兩個全局變量分別是:
1、LINE_SEPARATE:當前系統環境的換行符;
2、ROOT_DIR:當前項目的運行目錄(我們創建的文件如果沒有特殊指定就是在這個目錄下);
private final static String LINE_SEPARATE = System.getProperty("line.separator"); private final static String ROOT_DIR=System.getProperty("user.dir"); public static void main(String[] args) throws IOException { System.out.println(ROOT_DIR); try (OutputStream out = new FileOutputStream("in.txt")) { out.write("湖畔".getBytes()); out.write(LINE_SEPARATE.getBytes()); out.write("123456".getBytes()); out.write(LINE_SEPARATE.getBytes()); } try (InputStream in = new FileInputStream("in.txt")) { byte[] contentArray = new byte[512]; int length = in.read(contentArray); try (OutputStream out = new FileOutputStream("newIn.txt")) { out.write(contentArray, 0, length); System.out.println(new String(contentArray, 0, length)); } } }
註意;我上面寫入的內容很短,讀一次512比特的數組肯定都能夠全部讀取出來,所以就不使用while循環了。
下面是輸出結果:
E:\EXE\eke.test.first 湖畔 123456
二、使用帶有緩沖區的BufferedInputStream和BufferedOutputStream並使用不同的方法復制一個文件比較效率:
(這些方法的比較是看傳智播客視頻後寫的)
直接上代碼:
public static void main(String[] args) throws IOException {
long copy_2_start_time = System.currentTimeMillis();
copy_2();
long copy_2_end_time = System.currentTimeMillis();
System.out.println("copy_2 運行耗時:" + (copy_2_end_time - copy_2_start_time) + " 毫秒");
long copy_1_start_time = System.currentTimeMillis();
copy_1();
long copy_1_end_time = System.currentTimeMillis();
System.out.println("copy_1 運行耗時:" + (copy_1_end_time - copy_1_start_time) + " 毫秒");
long copy_0_start_time = System.currentTimeMillis();
copy_0();
long copy_0_end_time = System.currentTimeMillis();
System.out.println("copy_0 運行耗時:" + (copy_0_end_time - copy_0_start_time) + " 毫秒");
}
private static void copy_1() throws IOException {
try (FileInputStream in = new FileInputStream("環保小視頻.mp4")) {
try (BufferedInputStream bufin = new BufferedInputStream(in, 102400)) {
int content;
try (FileOutputStream out = new FileOutputStream("copy_1.mp4")) {
try (BufferedOutputStream bufout = new BufferedOutputStream(out, 102400)) {
while ((content = in.read()) != -1) {
bufout.write(content);
}
}
}
}
}
}
private static void copy_0() throws IOException {
try (FileInputStream in = new FileInputStream("環保小視頻.mp4")) {
try (FileOutputStream out = new FileOutputStream("copy_0.mp4")) {
byte[] contentArray = new byte[102400];
int length = 0;
while ((length = in.read(contentArray)) != -1) {
out.write(contentArray, 0, length);
}
}
}
}
private static void copy_2() throws IOException {
try (FileInputStream in = new FileInputStream("環保小視頻.mp4")) {
try (FileOutputStream out = new FileOutputStream("copy_2.mp4")) {
int ch;
while ((ch = in.read()) != -1) {
out.write(ch);
}
}
}
}
輸出結果:
Connected to the target VM, address: ‘127.0.0.1:53146‘, transport: ‘socket‘ copy_2 運行耗時:69494 毫秒 copy_1 運行耗時:9119 毫秒 copy_0 運行耗時:9 毫秒 Disconnected from the target VM, address: ‘127.0.0.1:53146‘, transport: ‘socket‘
分析:
copy_2方法是使用FileOutputStream和FileInputStream,一個自己一個字節的讀;速度慢的想死;
copy_1方法使用了帶緩沖區的BufferedInputStream 和BufferedOutputStream,速度有了很大的提高,但是還是慢的一匹;
copy_0方法是使用了自己創建的緩沖區,每次讀取102400個字節,竟然只需要9毫秒。
其中copy_1和copy_0的區別是在讀取和寫入的時候都是從各自的緩沖區取,但是copy_1沒有使用數組,一次還是只讀取一個字節,所以速度上被copy_0給拋下了。
Java-IO 字節流的使用和效率比較