Java檔案讀寫IO/NIO及效能比較總結
阿新 • • 發佈:2019-02-05
幹Java這麼久,一直在做WEB相關的專案,一些基礎類差不多都已經忘記。經常想得撿起,但總是因為一些原因,不能如願。
其實不是沒有時間,只是有些時候疲於總結,今得空,下定決心將丟掉的都給撿起來。
檔案讀寫是一個在專案中經常遇到的工作,有些時候是因為維護,有些時候是新功能開發。我們的任務總是很重,工作節奏很快,快到我們不能停下腳步去總結。
檔案讀寫有以下幾種常用的方法
1、位元組讀寫(InputStream/OutputStream)
2、字元讀取(FileReader/FileWriter)
3、行讀取(BufferedReader/BufferedWriter)
程式碼(以讀取為例):
[java]- import java.io.BufferedReader;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileReader;
- import java.io.IOException;
- import java.io.InputStream;
- /**
- * <b>檔案讀取類</b><br />
- * 1、按位元組讀取檔案內容<br />
- * 2、按字元讀取檔案內容<br />
- * 3、按行讀取檔案內容<br />
- * @author qin_xijuan
- *
- */
- publicclass FileOperate {
- privatestaticfinal String FILE_PATH = "d:/work/the List of Beautiful Music.txt";
- /**
- * 以位元組為單位讀取檔案內容
- * @param filePath:需要讀取的檔案路徑
- */
- publicstaticvoid readFileByByte(String filePath) {
- File file = new File(filePath);
- // InputStream:此抽象類是表示位元組輸入流的所有類的超類。
- InputStream ins = null ;
- try{
- // FileInputStream:從檔案系統中的某個檔案中獲得輸入位元組。
- ins = new FileInputStream(file);
- int temp ;
- // read():從輸入流中讀取資料的下一個位元組。
- while((temp = ins.read())!=-1){
- System.out.write(temp);
- }
- }catch(Exception e){
- e.getStackTrace();
- }finally{
- if (ins != null){
- try{
- ins.close();
- }catch(IOException e){
- e.getStackTrace();
- }
- }
- }
- }
- /**
- * 以字元為單位讀取檔案內容
- * @param filePath
- */
- publicstaticvoid readFileByCharacter(String filePath){
- File file = new File(filePath);
- // FileReader:用來讀取字元檔案的便捷類。
- FileReader reader = null;
- try{
- reader = new FileReader(file);
- int temp ;
- while((temp = reader.read()) != -1){
- if (((char) temp) != '\r') {
- System.out.print((char) temp);
- }
- }
- }catch(IOException e){
- e.getStackTrace();
- }finally{
- if (reader != null){
- try {
- reader.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
- /**
- * 以行為單位讀取檔案內容
- * @param filePath
- */
- publicstaticvoid readFileByLine(String filePath){
- File file = new File(filePath);
- // BufferedReader:從字元輸入流中讀取文字,緩衝各個字元,從而實現字元、陣列和行的高效讀取。
- BufferedReader buf = null;
- try{
- // FileReader:用來讀取字元檔案的便捷類。
- buf = new BufferedReader(new FileReader(file));
- // buf = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
- String temp = null ;
- while ((temp = buf.readLine()) != null ){
- System.out.println(temp);
- }
- }catch(Exception e){
- e.getStackTrace();
- }finally{
- if(buf != null){
- try{
- buf.close();
- } catch (IOException e) {
- e.getStackTrace();
- }
- }
- }
- }
- publicstaticvoid main(String args[]) {
- readFileByByte(FILE_PATH);
- readFileByCharacter(FILE_PATH);
- readFileByLine(FILE_PATH);
- }
- }
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
/**
* <b>檔案讀取類</b><br />
* 1、按位元組讀取檔案內容<br />
* 2、按字元讀取檔案內容<br />
* 3、按行讀取檔案內容<br />
* @author qin_xijuan
*
*/
public class FileOperate {
private static final String FILE_PATH = "d:/work/the List of Beautiful Music.txt";
/**
* 以位元組為單位讀取檔案內容
* @param filePath:需要讀取的檔案路徑
*/
public static void readFileByByte(String filePath) {
File file = new File(filePath);
// InputStream:此抽象類是表示位元組輸入流的所有類的超類。
InputStream ins = null ;
try{
// FileInputStream:從檔案系統中的某個檔案中獲得輸入位元組。
ins = new FileInputStream(file);
int temp ;
// read():從輸入流中讀取資料的下一個位元組。
while((temp = ins.read())!=-1){
System.out.write(temp);
}
}catch(Exception e){
e.getStackTrace();
}finally{
if (ins != null){
try{
ins.close();
}catch(IOException e){
e.getStackTrace();
}
}
}
}
/**
* 以字元為單位讀取檔案內容
* @param filePath
*/
public static void readFileByCharacter(String filePath){
File file = new File(filePath);
// FileReader:用來讀取字元檔案的便捷類。
FileReader reader = null;
try{
reader = new FileReader(file);
int temp ;
while((temp = reader.read()) != -1){
if (((char) temp) != '\r') {
System.out.print((char) temp);
}
}
}catch(IOException e){
e.getStackTrace();
}finally{
if (reader != null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 以行為單位讀取檔案內容
* @param filePath
*/
public static void readFileByLine(String filePath){
File file = new File(filePath);
// BufferedReader:從字元輸入流中讀取文字,緩衝各個字元,從而實現字元、陣列和行的高效讀取。
BufferedReader buf = null;
try{
// FileReader:用來讀取字元檔案的便捷類。
buf = new BufferedReader(new FileReader(file));
// buf = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
String temp = null ;
while ((temp = buf.readLine()) != null ){
System.out.println(temp);
}
}catch(Exception e){
e.getStackTrace();
}finally{
if(buf != null){
try{
buf.close();
} catch (IOException e) {
e.getStackTrace();
}
}
}
}
public static void main(String args[]) {
readFileByByte(FILE_PATH);
readFileByCharacter(FILE_PATH);
readFileByLine(FILE_PATH);
}
}
// ----------------------------------------------------------------- 分割線 -----------------------------------------------------------------------------
再經過兩位同行的提點下,我對之前寫的檔案做了點修改,並通過讀寫一個1.2M的文字檔案來測試各方法的效能。從多次測試結果來看,行讀寫卻是是Java.nio更有效率。
經過修改之後的程式碼如下:
[java] view plaincopyprint?- package com.waddell.basic;
- 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.InputStream;
- import java.io.OutputStream;
- import java.nio.ByteBuffer;
- import java.nio.channels.FileChannel;
- /**
- * <b>檔案讀取類</b><br />
- * 1、按位元組讀取檔案內容<br />
- * 2、按字元讀取檔案內容<br />
- * 3、按行讀取檔案內容<br />
- *
- * @author qin_xijuan
- *
- */
- publicclass FileOperate {
- privatestaticfinal String FILE_PATH = "d:/work/jipinwodi.txt";
- /**
- * 以位元組為單位讀寫檔案內容
- *
- * @param filePath
- * :需要讀取的檔案路徑
- */
- publicstaticvoid readFileByByte(String filePath) {
- File file = new File(filePath);
- // InputStream:此抽象類是表示位元組輸入流的所有類的超類。
- InputStream ins = null;
- OutputStream outs = null;
- try {
- // FileInputStream:從檔案系統中的某個檔案中獲得輸入位元組。
- ins = new FileInputStream(file);
- outs = new FileOutputStream("d:/work/readFileByByte.txt");
- int temp;
- // read():從輸入流中讀取資料的下一個位元組。
- while ((temp = ins.read()) != -1) {
- outs.write(temp);
- }
- } catch (Exception e) {
- e.getStackTrace();
- } finally {
- if (ins != null && outs != null) {
- try {
- outs.close();
- ins.close();
- } catch (IOException e) {
- e.getStackTrace();
- }
- }
- }
- }
- /**
- * 以字元為單位讀寫檔案內容
- *
- * @param filePath
- */
- publicstaticvoid readFileByCharacter(String filePath) {
- File file = new File(filePath);
- // FileReader:用來讀取字元檔案的便捷類。
- FileReader reader = null;
- FileWriter writer = null;
- try {
- reader = new FileReader(file);
- writer = new FileWriter("d:/work/readFileByCharacter.txt");
- int temp;
- while ((temp = reader.read()) != -1) {
- writer.write((char)temp);
- }
- } catch (IOException e) {
- e.getStackTrace();
- } finally {
- if (reader != null && writer != null) {
- try {
- reader.close();
- writer.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
- /**
- * 以行為單位讀寫檔案內容
- *
- * @param filePath
- */
- publicstaticvoid readFileByLine(String filePath) {
- File file = new File(filePath);
- // BufferedReader:從字元輸入流中讀取文字,緩衝各個字元,從而實現字元、陣列和行的高效讀取。
- BufferedReader bufReader = null;
- BufferedWriter bufWriter = null;
- try {
- // FileReader:用來讀取字元檔案的便捷類。
- bufReader = new BufferedReader(new FileReader(file));
- bufWriter = new BufferedWriter(new FileWriter("d:/work/readFileByLine.txt"));
- // buf = new BufferedReader(new InputStreamReader(new
- // FileInputStream(file)));
- String temp = null;
- while ((temp = bufReader.readLine()) != null) {
- bufWriter.write(temp+"\n");
- }
- } catch (Exception e) {
- e.getStackTrace();
- } finally {
- if (bufReader != null && bufWriter != null) {
- try {
- bufReader.close();
- bufWriter.close();
- } catch (IOException e) {
- e.getStackTrace();
- }
- }
- }
- }
- /**
- * 使用Java.nio ByteBuffer位元組將一個檔案輸出至另一檔案
- *
- * @param filePath
- */
- publicstaticvoid readFileByBybeBuffer(String filePath) {
- FileInputStream in = null;
- FileOutputStream out = null;
- try {
- // 獲取原始檔和目標檔案的輸入輸出流
- in = new FileInputStream(filePath);
- out = new FileOutputStream("d:/work/readFileByBybeBuffer.txt");
- // 獲取輸入輸出通道
- FileChannel fcIn = in.getChannel();
- FileChannel fcOut = out.getChannel();
- ByteBuffer buffer = ByteBuffer.allocate(1024);
- while (true) {
- // clear方法重設緩衝區,使它可以接受讀入的資料
- buffer.clear();
- // 從輸入通道中將資料讀到緩衝區
- int r = fcIn.read(buffer);
- if (r == -1) {
- break;
- }
- // flip方法讓緩衝區可以將新讀入的資料寫入另一個通道
- buffer.flip();
- fcOut.write(buffer);
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (in != null && out != null) {
- try {
- in.close();
- out.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
- publicstaticlong getTime(){
- return System.currentTimeMillis();
- }
- publicstaticvoid main(String args[]) {
- long time1 = getTime() ;
- // readFileByByte(FILE_PATH);// 8734,8281,8000,7781,8047
- // readFileByCharacter(FILE_PATH);// 734, 437, 437, 438, 422
- // readFileByLine(FILE_PATH);// 110, 94, 94, 110, 93
- readFileByBybeBuffer(FILE_PATH);// 125, 78, 62, 78, 62
- long time2 = getTime() ;
- System.out.println(time2-time1);
- }
- }
package com.waddell.basic;
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.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
* <b>檔案讀取類</b><br />
* 1、按位元組讀取檔案內容<br />
* 2、按字元讀取檔案內容<br />
* 3、按行讀取檔案內容<br />
*
* @author qin_xijuan
*
*/
public class FileOperate {
private static final String FILE_PATH = "d:/work/jipinwodi.txt";
/**
* 以位元組為單位讀寫檔案內容
*
* @param filePath
* :需要讀取的檔案路徑
*/
public static void readFileByByte(String filePath) {
File file = new File(filePath);
// InputStream:此抽象類是表示位元組輸入流的所有類的超類。
InputStream ins = null;
OutputStream outs = null;
try {
// FileInputStream:從檔案系統中的某個檔案中獲得輸入位元組。
ins = new FileInputStream(file);
outs = new FileOutputStream("d:/work/readFileByByte.txt");
int temp;
// read():從輸入流中讀取資料的下一個位元組。
while ((temp = ins.read()) != -1) {
outs.write(temp);
}
} catch (Exception e) {
e.getStackTrace();
} finally {
if (ins != null && outs != null) {
try {
outs.close();
ins.close();
} catch (IOException e) {
e.getStackTrace();
}
}
}
}
/**
* 以字元為單位讀寫檔案內容
*
* @param filePath
*/
public static void readFileByCharacter(String filePath) {
File file = new File(filePath);
// FileReader:用來讀取字元檔案的便捷類。
FileReader reader = null;
FileWriter writer = null;
try {
reader = new FileReader(file);
writer = new FileWriter("d:/work/readFileByCharacter.txt");
int temp;
while ((temp = reader.read()) != -1) {
writer.write((char)temp);
}
} catch (IOException e) {
e.getStackTrace();
} finally {
if (reader != null && writer != null) {
try {
reader.close();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 以行為單位讀寫檔案內容
*
* @param filePath
*/
public static void readFileByLine(String filePath) {
File file = new File(filePath);
// BufferedReader:從字元輸入流中讀取文字,緩衝各個字元,從而實現字元、陣列和行的高效讀取。
BufferedReader bufReader = null;
BufferedWriter bufWriter = null;
try {
// FileReader:用來讀取字元檔案的便捷類。
bufReader = new BufferedReader(new FileReader(file));
bufWriter = new BufferedWriter(new FileWriter("d:/work/readFileByLine.txt"));
// buf = new BufferedReader(new InputStreamReader(new
// FileInputStream(file)));
String temp = null;
while ((temp = bufReader.readLine()) != null) {
bufWriter.write(temp+"\n");
}
} catch (Exception e) {
e.getStackTrace();
} finally {
if (bufReader != null && bufWriter != null) {
try {
bufReader.close();
bufWriter.close();
} catch (IOException e) {
e.getStackTrace();
}
}
}
}
/**
* 使用Java.nio ByteBuffer位元組將一個檔案輸出至另一檔案
*
* @param filePath
*/
public static void readFileByBybeBuffer(String filePath) {
FileInputStream in = null;
FileOutputStream out = null;
try {
// 獲取原始檔和目標檔案的輸入輸出流
in = new FileInputStream(filePath);
out = new FileOutputStream("d:/work/readFileByBybeBuffer.txt");
// 獲取輸入輸出通道
FileChannel fcIn = in.getChannel();
FileChannel fcOut = out.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (true) {
// clear方法重設緩衝區,使它可以接受讀入的資料
buffer.clear();
// 從輸入通道中將資料讀到緩衝區
int r = fcIn.read(buffer);
if (r == -1) {
break;
}
// flip方法讓緩衝區可以將新讀入的資料寫入另一個通道
buffer.flip();
fcOut.write(buffer);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (in != null && out != null) {
try {
in.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static long getTime(){
return System.currentTimeMillis();
}
public static void main(String args[]) {
long time1 = getTime() ;
// readFileByByte(FILE_PATH);// 8734,8281,8000,7781,8047
// readFileByCharacter(FILE_PATH);// 734, 437, 437, 438, 422
// readFileByLine(FILE_PATH);// 110, 94, 94, 110, 93
readFileByBybeBuffer(FILE_PATH);// 125, 78, 62, 78, 62
long time2 = getTime() ;
System.out.println(time2-time1);
}
}
在main方法中,呼叫各方法之後,有五組資料,分辨是我5次讀寫檔案測試出來的時間(毫秒)。
付我個人測試:
[java] view plaincopyprint?- publicstaticvoid main(String args[]) {
- long time1 = getTime() ;
- // readFileByByte(FILE_PATH); //2338,2286
- // readFileByCharacter(FILE_PATH);//160,162,158
- // readFileByLine(FILE_PATH); //46,51,57
- // readFileByBybeBuffer(FILE_PATH);//19,18,17
- // readFileByBybeBuffer(FILE_PATH);//2048: 11,13
- // readFileByBybeBuffer(FILE_PATH);//1024*100 100k,711k: 6,6
- // readFileByBybeBuffer(FILE_PATH);//1024*100 100k,1422k: 7
- // readFileByBybeBuffer(FILE_PATH);//1024*100 100k,9951k: 49,48
- // readFileByBybeBuffer(FILE_PATH);//1024*1000 1M,711k: 7,7
- // readFileByBybeBuffer(FILE_PATH);//1024*1000 1M,1422k: 7,8
- // readFileByBybeBuffer(FILE_PATH);//1024*1000 1M,9951k: 48,49
- // readFileByBybeBuffer(FILE_PATH);//1024*10000 10M,711k: 21,13,17
- // readFileByBybeBuffer(FILE_PATH);//1024*10000 10M,1422k: 16,17,14,15
- // readFileByBybeBuffer(FILE_PATH);//1024*10000 10M,9951k:64,60
- long time2 = getTime() ;
- System.out.println(time2-time1);
- }
public static void main(String args[]) {
long time1 = getTime() ;
// readFileByByte(FILE_PATH); //2338,2286
// readFileByCharacter(FILE_PATH);//160,162,158
// readFileByLine(FILE_PATH); //46,51,57
// readFileByBybeBuffer(FILE_PATH);//19,18,17
// readFileByBybeBuffer(FILE_PATH);//2048: 11,13
// readFileByBybeBuffer(FILE_PATH);//1024*100 100k,711k: 6,6
// readFileByBybeBuffer(FILE_PATH);//1024*100 100k,1422k: 7
// readFileByBybeBuffer(FILE_PATH);//1024*100 100k,9951k: 49,48
// readFileByBybeBuffer(FILE_PATH);//1024*1000 1M,711k: 7,7
// readFileByBybeBuffer(FILE_PATH);//1024*1000 1M,1422k: 7,8
// readFileByBybeBuffer(FILE_PATH);//1024*1000 1M,9951k: 48,49
// readFileByBybeBuffer(FILE_PATH);//1024*10000 10M,711k: 21,13,17
// readFileByBybeBuffer(FILE_PATH);//1024*10000 10M,1422k: 16,17,14,15
// readFileByBybeBuffer(FILE_PATH);//1024*10000 10M,9951k:64,60
long time2 = getTime() ;
System.out.println(time2-time1);
}
轉自:http://www.cnblogs.com/waddell/archive/2013/01/24/2874104.html