程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 三種訪問文件的方式,三種訪問文件方式

三種訪問文件的方式,三種訪問文件方式

編輯:JAVA綜合教程

三種訪問文件的方式,三種訪問文件方式


標准IO,帶緩沖的標准IO,內存映射等在Java中的實現:

  1 package com.mesopotamia.test;
  2 
  3 import java.io.BufferedReader;
  4 import java.io.ByteArrayInputStream;
  5 import java.io.File;
  6 import java.io.FileNotFoundException;
  7 import java.io.FileReader;
  8 import java.io.IOException;
  9 import java.io.RandomAccessFile;
 10 import java.nio.ByteBuffer;
 11 import java.nio.MappedByteBuffer;
 12 import java.nio.channels.FileChannel;
 13 import java.util.Scanner;
 14 
 15 import org.apache.log4j.Logger;
 16 /*
 17  * 原文學習請加微信訂閱號:it_pupil
 18  * **/
 19 public class FileRead {
 20     private static Logger logger = Logger.getLogger(FileRead.class); 
 21     public static void main(String args[]) throws FileNotFoundException{
 22         String path = "C:" + File.separator + "test" + File.separator + "Alice.txt";  
 23         readFile3(path);
 24     }
 25     
 26     public static void readFile(String path) throws FileNotFoundException {
 27         long start = System.currentTimeMillis();//開始時間
 28         int bufSize = 1024;//1K緩沖區
 29         File fin = new File(path); 
 30         /*
 31          * 通道就是為操作文件而建立的一個連接。(讀寫文件、內存映射等)
 32          * 此處的getChannel()可以獲取通道;
 33          * 用FileChannel.open(filename)也可以創建一個通道。
 34          * "r"表示只讀。
 35          * 
 36          * RandomAccessFile是獨立與I/O流家族的類,其父類是Object。
 37          * 該類因為有個指針可以挪動,所以,可以從任意位置開始讀取文件數據。
 38          * **/
 39         FileChannel fcin = new RandomAccessFile(fin, "r").getChannel();
 40         //給字節緩沖區分配大小
 41         ByteBuffer rBuffer = ByteBuffer.allocate(bufSize);                        
 42         String enterStr = "\n";
 43         try {
 44             byte[] bs = new byte[bufSize];
 45             String tempString = null;
 46             while (fcin.read(rBuffer) != -1) {//每次讀1k到緩沖區
 47                 int rSize = rBuffer.position();//記錄緩沖區當前位置
 48                 rBuffer.rewind();//位置歸零,標記取消,方便下次循環重新讀入緩沖區。
 49                 rBuffer.get(bs);//將緩沖區數據讀到字節數組中
 50                 rBuffer.clear();//清除緩沖
 51                 /*
 52                  * 用默認編碼將指定字節數組的數據構造成一個字符串
 53                  * bs:指定的字節數組,0:數組起始位置;rSize:數組結束位置
 54                  * */
 55                 tempString = new String(bs, 0, rSize);
 56                 int fromIndex = 0;//每次讀的開始位置
 57                 int endIndex = 0;//每次讀的結束位置
 58                 //按行讀String數據
 59                 while ((endIndex = tempString.indexOf(enterStr, fromIndex)) != -1) {
 60                     String line = tempString.substring(fromIndex, endIndex);//轉換一行            
 61                     System.out.print(line);                     
 62                     fromIndex = endIndex + 1;
 63                 }
 64             }
 65             long end = System.currentTimeMillis();//結束時間
 66             System.out.println("傳統IO讀取數據,指定緩沖區大小,總共耗時:"+(end - start)+"ms");
 67 
 68         } catch (IOException e) {
 69             e.printStackTrace();
 70         }
 71     }
 72     
 73     public static void readFile1(String path) { 
 74         long start = System.currentTimeMillis();//開始時間
 75         File file = new File(path);  
 76         if (file.isFile()) {  
 77             /*使用Reader家族,表示我要讀字符數據了,
 78              *使用該家族中的BufferedReader,表示我要建立緩沖區讀字符數據了。
 79              * */
 80             BufferedReader bufferedReader = null;  
 81             FileReader fileReader = null;  
 82             try {  
 83                 fileReader = new FileReader(file); 
 84                 //嵌套使用,裝飾者模式,老生常談。裝飾者模式的使用,可以讀前面小磚寫的《從熏肉大餅到裝飾者模式》
 85                 bufferedReader = new BufferedReader(fileReader);  
 86                 String line = bufferedReader.readLine();  
 87                 //一行一行讀
 88                 while (line != null) { //按行讀數據
 89                     System.out.println(line);  
 90                     line = bufferedReader.readLine();  
 91                 }  
 92             } catch (FileNotFoundException e) {  
 93                 e.printStackTrace();  
 94             } catch (IOException e) {  
 95                 e.printStackTrace();  
 96             } finally {  
 97                 //最後一定要關閉
 98                 try {  
 99                     fileReader.close();  
100                     bufferedReader.close();  
101                 } catch (IOException e) {  
102                     e.printStackTrace();  
103                 }  
104                 long end = System.currentTimeMillis();//結束時間
105                 System.out.println("傳統IO讀取數據,不指定緩沖區大小,總共耗時:"+(end - start)+"ms");
106             }  
107   
108         }  
109     } 
110     
111     public static void readFile3(String path) {
112         long start = System.currentTimeMillis();//開始時間
113         long fileLength = 0;  
114         final int BUFFER_SIZE = 0x300000;// 3M的緩沖  
115             File file = new File(path);  
116             fileLength = file.length();  
117             try {  
118                 /*使用FileChannel.map方法直接把整個fileLength大小的文件映射到內存中**/
119                 MappedByteBuffer inputBuffer = new RandomAccessFile(file, "r").getChannel()
120                     .map(FileChannel.MapMode.READ_ONLY, 0, fileLength);// 讀取大文件  
121                 byte[] dst = new byte[BUFFER_SIZE];// 每次讀出3M的內容
122                 //每3M做一個循環,分段將inputBuffer的數據取出。
123                 for (int offset = 0; offset < fileLength; offset += BUFFER_SIZE) {
124                     //防止最後一段不夠3M
125                     if (fileLength - offset >= BUFFER_SIZE) {
126                         //一個字節一個字節的取出來放到byte[]數組中。
127                         for (int i = 0; i < BUFFER_SIZE; i++)  
128                             dst[i] = inputBuffer.get(offset + i);  
129                     } else {  
130                         for (int i = 0; i < fileLength - offset; i++)  
131                             dst[i] = inputBuffer.get(offset + i);  
132                     }  
133                     // 將得到的3M內容給Scanner,這裡的XXX是指Scanner解析的分隔符。
134                     Scanner scan = new Scanner(new ByteArrayInputStream(dst)).useDelimiter("XXX");  
135                     //hasNext()所參照的token就是上面的XXX
136                     while (scan.hasNext()) {  
137                         // 這裡為對讀取文本解析的方法  
138                         System.out.print(scan.next() + "XXX");  
139                     }  
140                     scan.close();  
141                 }  
142                 System.out.println();
143                 long end = System.currentTimeMillis();//結束時間
144                 System.out.println("NIO 內存映射讀大文件,總共耗時:"+(end - start)+"ms");
145             } catch (Exception e) {  
146                 e.printStackTrace();  
147             }  
148     } 
149 }

內容來自:《磁盤IO的工作機制》,發布自微信訂閱號:it_pupil

《磁盤IO的工作機制》主要內容:

  內核空間與用戶空間(以及數據在二者之間的轉換);

  標准訪問文件的方式(要同時經過內核空間、用戶空間的雙重拷貝)(局部性原理);

  帶緩沖訪問文件的方式;

  直接IO(避開內核緩沖區,適合在應用程序中管理緩存的系統,比如:數據庫管理系統);

  內存映射(磁盤文件與用戶空間的直接映射,減少拷貝數據的次數,適合大文件的讀寫。);

  阻塞與非阻塞,同步與異步的區分(非阻塞同步、非阻塞異步的介紹);

訂閱號二維碼:

  

  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved