1. 程式人生 > >Java 之 檔案讀寫及效能比較總結

Java 之 檔案讀寫及效能比較總結

Java 之 檔案讀寫及效能比較總結

2014年05月12日 17:56:49

閱讀數:21765



幹Java這麼久,一直在做WEB相關的專案,一些基礎類差不多都已經忘記。經常想得撿起,但總是因為一些原因,不能如願。

其實不是沒有時間,只是有些時候疲於總結,今得空,下定決心將丟掉的都給撿起來。

檔案讀寫是一個在專案中經常遇到的工作,有些時候是因為維護,有些時候是新功能開發。我們的任務總是很重,工作節奏很快,快到我們不能停下腳步去總結。

檔案讀寫有以下幾種常用的方法

1、位元組讀寫(InputStream/OutputStream)

2、字元讀取(FileReader/FileWriter)

3、行讀取(BufferedReader/BufferedWriter)

程式碼(以讀取為例):

 
  1. import java.io.BufferedReader;

  2. import java.io.File;

  3. import java.io.FileInputStream;

  4. import java.io.FileReader;

  5. import java.io.IOException;

  6. import java.io.InputStream;

  7. /**

  8. * <b>檔案讀取類</b><br />

  9. * 1、按位元組讀取檔案內容<br />

  10. * 2、按字元讀取檔案內容<br />

  11. * 3、按行讀取檔案內容<br />

  12. * @author qin_xijuan

  13. *

  14. */

  15. public class FileOperate {

  16.  
  17. private static final String FILE_PATH = "d:/work/the List of Beautiful Music.txt";

  18.  
  19. /**

  20. * 以位元組為單位讀取檔案內容

  21. * @param filePath:需要讀取的檔案路徑

  22. */

  23. public static void readFileByByte(String filePath) {

  24. File file = new File(filePath);

  25. // InputStream:此抽象類是表示位元組輸入流的所有類的超類。

  26. InputStream ins = null ;

  27. try{

  28. // FileInputStream:從檔案系統中的某個檔案中獲得輸入位元組。

  29. ins = new FileInputStream(file);

  30. int temp ;

  31. // read():從輸入流中讀取資料的下一個位元組。

  32. while((temp = ins.read())!=-1){

  33. System.out.write(temp);

  34. }

  35. }catch(Exception e){

  36. e.getStackTrace();

  37. }finally{

  38. if (ins != null){

  39. try{

  40. ins.close();

  41. }catch(IOException e){

  42. e.getStackTrace();

  43. }

  44. }

  45. }

  46. }

  47.  
  48. /**

  49. * 以字元為單位讀取檔案內容

  50. * @param filePath

  51. */

  52. public static void readFileByCharacter(String filePath){

  53. File file = new File(filePath);

  54. // FileReader:用來讀取字元檔案的便捷類。

  55. FileReader reader = null;

  56. try{

  57. reader = new FileReader(file);

  58. int temp ;

  59. while((temp = reader.read()) != -1){

  60. if (((char) temp) != '\r') {

  61. System.out.print((char) temp);

  62. }

  63. }

  64. }catch(IOException e){

  65. e.getStackTrace();

  66. }finally{

  67. if (reader != null){

  68. try {

  69. reader.close();

  70. } catch (IOException e) {

  71. e.printStackTrace();

  72. }

  73. }

  74. }

  75. }

  76.  
  77. /**

  78. * 以行為單位讀取檔案內容

  79. * @param filePath

  80. */

  81. public static void readFileByLine(String filePath){

  82. File file = new File(filePath);

  83. // BufferedReader:從字元輸入流中讀取文字,緩衝各個字元,從而實現字元、陣列和行的高效讀取。

  84. BufferedReader buf = null;

  85. try{

  86. // FileReader:用來讀取字元檔案的便捷類。

  87. buf = new BufferedReader(new FileReader(file));

  88. // buf = new BufferedReader(new InputStreamReader(new FileInputStream(file)));

  89. String temp = null ;

  90. while ((temp = buf.readLine()) != null ){

  91. System.out.println(temp);

  92. }

  93. }catch(Exception e){

  94. e.getStackTrace();

  95. }finally{

  96. if(buf != null){

  97. try{

  98. buf.close();

  99. } catch (IOException e) {

  100. e.getStackTrace();

  101. }

  102. }

  103. }

  104. }

  105.  
  106. public static void main(String args[]) {

  107. readFileByByte(FILE_PATH);

  108. readFileByCharacter(FILE_PATH);

  109. readFileByLine(FILE_PATH);

  110. }

  111. }

// ----------------------------------------------------------------- 分割線 -----------------------------------------------------------------------------

 

再經過兩位同行的提點下,我對之前寫的檔案做了點修改,並通過讀寫一個1.2M的文字檔案來測試各方法的效能。從多次測試結果來看,行讀寫卻是是Java.nio更有效率。

經過修改之後的程式碼如下:

 
  1. package com.waddell.basic;

  2.  
  3. import java.io.BufferedReader;

  4. import java.io.BufferedWriter;

  5. import java.io.File;

  6. import java.io.FileInputStream;

  7. import java.io.FileOutputStream;

  8. import java.io.FileReader;

  9. import java.io.FileWriter;

  10. import java.io.IOException;

  11. import java.io.InputStream;

  12. import java.io.OutputStream;

  13. import java.nio.ByteBuffer;

  14. import java.nio.channels.FileChannel;

  15.  
  16. /**

  17. * <b>檔案讀取類</b><br />

  18. * 1、按位元組讀取檔案內容<br />

  19. * 2、按字元讀取檔案內容<br />

  20. * 3、按行讀取檔案內容<br />

  21. *

  22. * @author qin_xijuan

  23. *

  24. */

  25. public class FileOperate {

  26.  
  27. private static final String FILE_PATH = "d:/work/jipinwodi.txt";

  28.  
  29. /**

  30. * 以位元組為單位讀寫檔案內容

  31. *

  32. * @param filePath

  33. * :需要讀取的檔案路徑

  34. */

  35. public static void readFileByByte(String filePath) {

  36. File file = new File(filePath);

  37. // InputStream:此抽象類是表示位元組輸入流的所有類的超類。

  38. InputStream ins = null;

  39. OutputStream outs = null;

  40. try {

  41. // FileInputStream:從檔案系統中的某個檔案中獲得輸入位元組。

  42. ins = new FileInputStream(file);

  43. outs = new FileOutputStream("d:/work/readFileByByte.txt");

  44. int temp;

  45. // read():從輸入流中讀取資料的下一個位元組。

  46. while ((temp = ins.read()) != -1) {

  47. outs.write(temp);

  48. }

  49. } catch (Exception e) {

  50. e.getStackTrace();

  51. } finally {

  52. if (ins != null && outs != null) {

  53. try {

  54. outs.close();

  55. ins.close();

  56. } catch (IOException e) {

  57. e.getStackTrace();

  58. }

  59. }

  60. }

  61. }

  62.  
  63. /**

  64. * 以字元為單位讀寫檔案內容

  65. *

  66. * @param filePath

  67. */

  68. public static void readFileByCharacter(String filePath) {

  69. File file = new File(filePath);

  70. // FileReader:用來讀取字元檔案的便捷類。

  71. FileReader reader = null;

  72. FileWriter writer = null;

  73. try {

  74. reader = new FileReader(file);

  75. writer = new FileWriter("d:/work/readFileByCharacter.txt");

  76. int temp;

  77. while ((temp = reader.read()) != -1) {

  78. writer.write((char)temp);

  79. }

  80. } catch (IOException e) {

  81. e.getStackTrace();

  82. } finally {

  83. if (reader != null && writer != null) {

  84. try {

  85. reader.close();

  86. writer.close();

  87. } catch (IOException e) {

  88. e.printStackTrace();

  89. }

  90. }

  91. }

  92. }

  93.  
  94. /**

  95. * 以行為單位讀寫檔案內容

  96. *

  97. * @param filePath

  98. */

  99. public static void readFileByLine(String filePath) {

  100. File file = new File(filePath);

  101. // BufferedReader:從字元輸入流中讀取文字,緩衝各個字元,從而實現字元、陣列和行的高效讀取。

  102. BufferedReader bufReader = null;

  103. BufferedWriter bufWriter = null;

  104. try {

  105. // FileReader:用來讀取字元檔案的便捷類。

  106. bufReader = new BufferedReader(new FileReader(file));

  107. bufWriter = new BufferedWriter(new FileWriter("d:/work/readFileByLine.txt"));

  108. // buf = new BufferedReader(new InputStreamReader(new

  109. // FileInputStream(file)));

  110. String temp = null;

  111. while ((temp = bufReader.readLine()) != null) {

  112. bufWriter.write(temp+"\n");

  113. }

  114. } catch (Exception e) {

  115. e.getStackTrace();

  116. } finally {

  117. if (bufReader != null && bufWriter != null) {

  118. try {

  119. bufReader.close();

  120. bufWriter.close();

  121. } catch (IOException e) {

  122. e.getStackTrace();

  123. }

  124. }

  125. }

  126. }

  127.  
  128. /**

  129. * 使用Java.nio ByteBuffer位元組將一個檔案輸出至另一檔案

  130. *

  131. * @param filePath

  132. */

  133. public static void readFileByBybeBuffer(String filePath) {

  134. FileInputStream in = null;

  135. FileOutputStream out = null;

  136. try {

  137. // 獲取原始檔和目標檔案的輸入輸出流

  138. in = new FileInputStream(filePath);

  139. out = new FileOutputStream("d:/work/readFileByBybeBuffer.txt");

  140. // 獲取輸入輸出通道

  141. FileChannel fcIn = in.getChannel();

  142. FileChannel fcOut = out.getChannel();

  143. ByteBuffer buffer = ByteBuffer.allocate(1024);

  144. while (true) {

  145. // clear方法重設緩衝區,使它可以接受讀入的資料

  146. buffer.clear();

  147. // 從輸入通道中將資料讀到緩衝區

  148. int r = fcIn.read(buffer);

  149. if (r == -1) {

  150. break;

  151. }

  152. // flip方法讓緩衝區可以將新讀入的資料寫入另一個通道

  153. buffer.flip();

  154. fcOut.write(buffer);

  155. }

  156.  
  157. } catch (Exception e) {

  158. e.printStackTrace();

  159. } finally {

  160. if (in != null && out != null) {

  161. try {

  162. in.close();

  163. out.close();

  164. } catch (IOException e) {

  165. e.printStackTrace();

  166. }

  167. }

  168. }

  169. }

  170.  
  171. public static long getTime(){

  172. return System.currentTimeMillis();

  173. }

  174.  
  175. public static void main(String args[]) {

  176. long time1 = getTime() ;

  177. // readFileByByte(FILE_PATH);// 8734,8281,8000,7781,8047

  178. // readFileByCharacter(FILE_PATH);// 734, 437, 437, 438, 422

  179. // readFileByLine(FILE_PATH);// 110, 94, 94, 110, 93

  180. readFileByBybeBuffer(FILE_PATH);// 125, 78, 62, 78, 62

  181. long time2 = getTime() ;

  182. System.out.println(time2-time1);

  183. }

  184. }

 

在main方法中,呼叫各方法之後,有五組資料,分辨是我5次讀寫檔案測試出來的時間(毫秒)。

關於Java.nio 請參考:http://www.iteye.com/topic/834447

付我個人測試:

 

 
  1. public static void main(String args[]) {

  2. long time1 = getTime() ;

  3. // readFileByByte(FILE_PATH); //2338,2286

  4. // readFileByCharacter(FILE_PATH);//160,162,158

  5. // readFileByLine(FILE_PATH); //46,51,57

  6. // readFileByBybeBuffer(FILE_PATH);//19,18,17

  7. // readFileByBybeBuffer(FILE_PATH);//2048: 11,13

  8. // readFileByBybeBuffer(FILE_PATH);//1024*100 100k,711k: 6,6

  9. // readFileByBybeBuffer(FILE_PATH);//1024*100 100k,1422k: 7

  10. // readFileByBybeBuffer(FILE_PATH);//1024*100 100k,9951k: 49,48

  11. // readFileByBybeBuffer(FILE_PATH);//1024*1000 1M,711k: 7,7

  12. // readFileByBybeBuffer(FILE_PATH);//1024*1000 1M,1422k: 7,8

  13. // readFileByBybeBuffer(FILE_PATH);//1024*1000 1M,9951k: 48,49

  14. // readFileByBybeBuffer(FILE_PATH);//1024*10000 10M,711k: 21,13,17

  15. // readFileByBybeBuffer(FILE_PATH);//1024*10000 10M,1422k: 16,17,14,15

  16. // readFileByBybeBuffer(FILE_PATH);//1024*10000 10M,9951k:64,60

  17.  
  18. long time2 = getTime() ;

  19. System.out.println(time2-time1);

  20. }



轉自:http://www.cnblogs.com/waddell/archive/2013/01/24/2874104.html