标准IO,带缓冲的标准IO,内存映射等在Java中的实现:

三种访问文件的方式_import

  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                     //防止最后一段不够3M125                     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就是上面的XXX136                     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 }

三种访问文件的方式_import