生動講解使用不同方式操作File檔案的方法之間的差異
下面展示了兩種java檔案操作的方式, 第一種是通過流來實現對檔案的複製 第二種是通過reader的方式來實現的 第三種是通過buffer來實現的 而且每一個方法之後都附有了對應的方法的使用btye[]/char[]的方法,讀者可以自行的測試它們的執行時間來比較它們的效能的優劣
package com.dada.handlefile;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Date;
public class CopyFile {
public static void main(String[] args) throws Exception {
CopyFile cf = new CopyFile();
File source = new File("source.JPG");
File dest = new File("dest.JPG");
File dest1 = new File("dest1.JPG");
// cf.check(source);
// // 測試第一種方法執行的時間
// File dest1 = new File("temp1.jpg");
// cf.check(dest1);
// Date m1Begin = new Date();
// cf.createFileByStream(source, dest1);
// Date m1End = new Date();
// long t1 = (m1End.getTime() - m1Begin.getTime());
//
// // 測試第二種方法執行的時間
// File dest2 = new File("temp2.jpg");
// cf.check(dest2);
// Date m2Begin = new Date();
// cf.createFileByReader(source, dest2);
// Date m2End = new Date();
// long t2 = (m2End.getTime() - m2Begin.getTime());
//
// // 第三種方法執行的時間
// File dest3 = new File("temp3.jpg");
// cf.check(dest3);
// Date m3Begin = new Date();
// cf.createFileByBuffer(source, dest3);
// Date m3End = new Date();
// long t3 = (m3End.getTime() - m3Begin.getTime());
//
// // 第一和第二種方法之間時間只差
// long difM1ToM2 = t1 - t2;
// // 倍數
// double multipleM1ToM2 = t1 / t2 * 1.0;
//
// long difM2ToM3 = t2 - t3;
// double multipleM2ToM3 = t2 / t3 * 1.0;
//
// long difM1ToM3 = t1 - t3;
// double multipleM1ToM3 = t1 / t3 * 1.0;
//
// System.out.println("第一個方法執行時間: " + t1 + "\t第一和第二個方法執行的時間差: "
// + difM1ToM2 + "\t倍數差: " + multipleM1ToM2);
// System.out.println("第二個方法執行時間: " + t2 + "\t第二和第三個方法執行的時間差: "
// + difM2ToM3 + "\t倍數差: " + multipleM2ToM3);
// System.out.println("第三個方法執行時間: " + t3 + "\t第一和第三個方法執行的時間差: "
// + difM1ToM3 + "\t倍數差: " + multipleM1ToM3);
}
/**
* 檢測指定檔案是否存在,不存在就建立
*
* @param f
*/
public void check(File f) {
if (!f.exists()) {
try {
f.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 通過stream來複制檔案
* @param source
* @param dest
* @throws Exception
*/
public void createFileByStream(File source, File dest) throws Exception {
FileInputStream in = new FileInputStream(source);
FileOutputStream out = new FileOutputStream(dest);
int read = in.read();
while (read != -1) {
out.write(read);
read = in.read();
}
out.close();
in.close();
}
public void createFileByStreamWithByte(File source, File dest) throws Exception {
FileInputStream in = new FileInputStream(source);
FileOutputStream out = new FileOutputStream(dest);
byte[] buf = new byte[1024];
while (in.read(buf) != -1) {
out.write(buf);
}
out.close();
in.close();
}
/**
* 使用reader來複制檔案
* @param source
* @param dest
* @throws Exception
*/
public void createFileByReader(File source, File dest) throws Exception {
FileReader fr = new FileReader(source);
FileWriter fw = new FileWriter(dest);
int read = fr.read();
while (read != -1) {
fw.write(read);
read = fr.read();
}
fw.close();
fr.close();
}
public void createFileByReaderWithChar(File source, File dest) throws Exception {
FileReader fr = new FileReader(source);
FileWriter fw = new FileWriter(dest);
char[] buf = new char[2048];
while (fr.read(buf) != -1) {
fw.write(buf);
}
fw.close();
fr.close();
}
/**
* 通過buffer來複制檔案
* @param source
* @param dest
* @throws Exception
*/
public void createFileByBuffer(File source, File dest) throws Exception {
// 封裝stream
FileInputStream in = new FileInputStream(source);
// 把stream封裝成為reader
InputStreamReader isr = new InputStreamReader(in);
// 把reader封裝成為buffer
BufferedReader br = new BufferedReader(isr);
FileOutputStream out = new FileOutputStream(dest);
OutputStreamWriter osw = new OutputStreamWriter(out);
BufferedWriter bw = new BufferedWriter(osw);
int read = br.read();
while (read != -1) {
bw.write(read);
read = br.read();
}
bw.close();
osw.close();
out.close();
br.close();
isr.close();
in.close();
}
public void createFileByBufferWithChar(File source, File dest) throws Exception {
// 封裝stream
FileInputStream in = new FileInputStream(source);
// 把stream封裝成為reader
InputStreamReader isr = new InputStreamReader(in);
// 把reader封裝成為buffer
BufferedReader br = new BufferedReader(isr);
FileOutputStream out = new FileOutputStream(dest);
OutputStreamWriter osw = new OutputStreamWriter(out);
BufferedWriter bw = new BufferedWriter(osw);
char[] buf = new char[2048];
while (br.read(buf) != -1) {
bw.write(buf);
}
bw.close();
osw.close();
out.close();
br.close();
isr.close();
in.close();
}
}
執行結果:
第一個方法執行時間: 7019 第一和第二個方法執行的時間差: 6894 倍數差: 56.0
第二個方法執行時間: 125 第二和第三個方法執行的時間差: 79 倍數差: 2.0
第三個方法執行時間: 46 第一和第三個方法執行的時間差: 6973 倍數差: 152.0
可見差異是非常之大的,相差超過150倍這個,
為什麼呢?我覺得就好像是這樣的:
我們可以打個比喻:
我們把檔案的複製可以看成是在兩個地方之間搬運東西,
有三種運輸工具:
摩托車(對應inputStream/outputStream),
三馬車(對應InputStreamReader/outtStreamReader),
大卡車(對應BufferedReader/BufferedWriter),
它們之間的關係式摩托車可以單獨的運送,送到指定地點之後
回來再次重複原來的動作,也可以把它上面的傳送帶(inputStream
可以封裝進入inputStreamReader裡面),同理三馬車也可以單獨
的運送,也可以把它的傳送帶(inputStreamReader可以封裝進入
BufferedReader裡面)連線到卡車上,但是因為卡車太高了,所以土
無法直接的裝進卡車,所以如果要使用卡車運送土的話,就需要摩托
車和三馬車提供傳送帶,把土送進卡車裡(對應stream的兩個封裝
過程)。
這是讀取過程,寫入的過程也是一樣的。需要把土從卡車上面通過
傳送帶一級一級的傳輸到地面。
那麼直接使用摩托車,三馬車和三個一起使用的效率差在哪裡了?
其實這中間取資料和讀資料的速度應該是沒有太大差異的,差異就在
於它們取的頻率差異很大,第一種方法是stream是位元組它們的容量很
小,所以它們每一次只能夠傳輸幾個位元組,而以此類推越往上一次傳輸
的容量越大,這樣的話,往返的次數就少了,花費在"路"上面的時間就少
了,同樣是運送100立方米的土,卡車要一次一個小時就夠了,而三馬車
要10次每一次要3個小時,而摩托車要100次每一次6個小時,這時間差
異就很明顯了.
另外在讀寫檔案的時候最好使用各個物件的read()方法,因為這個方法
是以位元組的方式讀取的,不論是什麼格式的檔案都不會出錯,但是如果
你使用buffer的readLine()方法,或者是它的read(byte[] b);方法,結果都
可能會出現問題,比如用readLine()方法讀取文字檔案,在你再次的寫出
去的時候,它裡面的所有的換行都會被去掉的.
如果是用它來讀取其他格式檔案,比如jpg檔案結果基本上都是錯誤的,
所以說在複製的時候直接就呼叫它的read()方法,既簡單效率又高,還不
會出錯的。
相關文章
- Git比對檔案之間的差異Git
- 前端BootstrapTable元件不同使用方法的效率各有差異前端bootAPT元件
- js中split,splice,slice方法之間的差異。JS
- IDEA如何對比不同分支某個檔案的差異Idea
- Python3之檔案操作filePython
- Bootstrap和Tailwind CSS之間的差異?bootAICSS
- 工作流和BPM之間的差異
- SQL Server 2017 各版本之間的差異SQLServer
- 示例解讀 Python 2 和 Python 3 之間的主要差異Python
- Java : File 檔案類操作Java
- Python中操作時間之strptime()方法的使用Python
- 能動性:知識分子和企業家之間的差異
- C# File.Exists 判斷系統檔案,警惕32位和64位的差異C#
- 使用Visual Studio進行檔案差異比較
- PostgreSQL在不同的表空間移動資料檔案SQL
- 美顏sdk為什麼有多種不同的價格?版本之間有哪些差異?
- [Windows批處理]比對Git兩個分支之間的差異,把有改動的檔案複製到指定目錄WindowsGit
- base64轉file檔案的兩種方式
- 圖解:美國不同族裔間的貧富差圖解
- python file 檔案操作筆記Python筆記
- Python 4 種不同的存取檔案騷操作Python
- module.exports、exports 、export default之間的差異區別及與require、import的使用ExportUIImport
- 差異檔案(diff)和補丁檔案(patch)簡介
- [譯] 測試原生,Flutter 和 React Native 移動開發之間的效能差異FlutterReact Native移動開發
- 像操作Room一樣操作SharedPreferences和File檔案OOM
- python對檔案的操作方法Python
- 類的方法,函式,同一個package不同.py檔案,不同package不同.py檔案————呼叫問題函式Package
- Spark和Hadoop之間的主要技術差異和選擇SparkHadoop
- 對於 JavaScript 中迴圈之間的技術差異概述JavaScript
- CentOS/RHEL 7:Chrony vs NTP(ntpd和chronyd之間的差異)CentOS
- 優雅的操作檔案:java.nio.file 庫介紹Java
- 主機和Docker容器之間的檔案互傳方法Docker
- 【JAVA :File類的用法(一)】File類的構造方法-File類建立檔案與資料夾Java構造方法
- [AlwaysOn] AlwaysOn可用性組的可用性模式之間的差異模式
- 怎樣解決程式語言之間的差異性問題?
- 6. 檢測兩臺機器上檔案的差異
- webpack打包之後的檔案過大的解決方法Web
- php檔案操作之提取檔案/目錄的名稱PHP
- Python檔案操作:finally子句的使用Python