Java NIO 读取文件、写入文件、读取写入混合

前言

Java NIO(new/inputstream outputstream)使用通道、缓冲来操作流,所以要深刻理解这些概念,尤其是,缓冲中的数据结构(当前位置(position)、限制(limit)、容量(capacity)),这些知识点要通过写程序慢慢体会。

 

NIO vs  传统IO

NIO是面向缓冲、通道的;传统IO面向流

通道是双向的既可以写、也可以读;传统IO只能是单向的

NIO可以设置为异步;传统IO只能是阻塞,同步的

 

 

缓冲区结构图

NIO是面向缓冲区的,缓冲区可以理解为一块内存,有大小。缓冲区有位置、界限、容量几个概念。

 

capacity:容量,缓冲区的大小

limit:限制,表示最大的可读写的数量

position:当前位置,每当读写,当前位置都会加一

 

flip和clear方法,内部就操作这三个变量。

 

 

缓冲区常用方法

clear:将当前位置设置为0,限制设置为容量,目的是尽最大可能让字节,由通道读取到缓冲中

flip:当前位置置为限制,然后将当前位置置为0,目的是将有数据部分的字节,由缓冲写入到通道中。通常用在读与写之间。

 

读写文件代码

  1 import java.io.File;  
  2 import java.io.FileInputStream;  
  3 import java.io.FileNotFoundException;  
  4 import java.io.FileOutputStream;  
  5 import java.io.IOException;  
  6 import java.nio.ByteBuffer;  
  7 import java.nio.channels.FileChannel;  
  8 import java.nio.charset.Charset;  
  9   
 10 public class TestJavaNIO {  
 11   
 12     static void readNIO() {  
 13         String pathname = "C:\\Users\\adew\\Desktop\\jd-gui.cfg";  
 14         FileInputStream fin = null;  
 15         try {  
 16             fin = new FileInputStream(new File(pathname));  
 17             FileChannel channel = fin.getChannel();  
 18   
 19             int capacity = 100;// 字节  
 20             ByteBuffer bf = ByteBuffer.allocate(capacity);  
 21             System.out.println("限制是:" + bf.limit() + "容量是:" + bf.capacity()  
 22                     + "位置是:" + bf.position());  
 23             int length = -1;  
 24   
 25             while ((length = channel.read(bf)) != -1) {  
 26   
 27                 /*  
 28                  * 注意,读取后,将位置置为0,将limit置为容量, 以备下次读入到字节缓冲中,从0开始存储  
 29                  */  
 30                 bf.clear();  
 31                 byte[] bytes = bf.array();  
 32                 System.out.write(bytes, 0, length);  
 33                 System.out.println();  
 34   
 35                 System.out.println("限制是:" + bf.limit() + "容量是:" + bf.capacity()  
 36                         + "位置是:" + bf.position());  
 37   
 38             }  
 39   
 40             channel.close();  
 41   
 42         } catch (FileNotFoundException e) {  
 43             e.printStackTrace();  
 44         } catch (IOException e) {  
 45             e.printStackTrace();  
 46         } finally {  
 47             if (fin != null) {  
 48                 try {  
 49                     fin.close();  
 50                 } catch (IOException e) {  
 51                     e.printStackTrace();  
 52                 }  
 53             }  
 54         }  
 55     }  
 56   
 57     static void writeNIO() {  
 58         String filename = "out.txt";  
 59         FileOutputStream fos = null;  
 60         try {  
 61   
 62             fos = new FileOutputStream(new File(filename));  
 63             FileChannel channel = fos.getChannel();  
 64             ByteBuffer src = Charset.forName("utf8").encode("你好你好你好你好你好");  
 65             // 字节缓冲的容量和limit会随着数据长度变化,不是固定不变的  
 66             System.out.println("初始化容量和limit:" + src.capacity() + ","  
 67                     + src.limit());  
 68             int length = 0;  
 69   
 70             while ((length = channel.write(src)) != 0) {  
 71                 /*  
 72                  * 注意,这里不需要clear,将缓冲中的数据写入到通道中后 第二次接着上一次的顺序往下读  
 73                  */  
 74                 System.out.println("写入长度:" + length);  
 75             }  
 76   
 77         } catch (FileNotFoundException e) {  
 78             e.printStackTrace();  
 79         } catch (IOException e) {  
 80             e.printStackTrace();  
 81         } finally {  
 82             if (fos != null) {  
 83                 try {  
 84                     fos.close();  
 85                 } catch (IOException e) {  
 86                     e.printStackTrace();  
 87                 }  
 88             }  
 89         }  
 90     }  
 91   
 92     static void testReadAndWriteNIO() {  
 93         String pathname = "C:\\Users\\adew\\Desktop\\test.txt";  
 94         FileInputStream fin = null;  
 95           
 96         String filename = "test-out.txt";  
 97         FileOutputStream fos = null;  
 98         try {  
 99             fin = new FileInputStream(new File(pathname));  
100             FileChannel channel = fin.getChannel();  
101   
102             int capacity = 100;// 字节  
103             ByteBuffer bf = ByteBuffer.allocate(capacity);  
104             System.out.println("限制是:" + bf.limit() + "容量是:" + bf.capacity()+ "位置是:" + bf.position());  
105             int length = -1;  
106   
107             fos = new FileOutputStream(new File(filename));  
108             FileChannel outchannel = fos.getChannel();  
109               
110               
111             while ((length = channel.read(bf)) != -1) {  
112                   
113                 //将当前位置置为limit,然后设置当前位置为0,也就是从0到limit这块,都写入到同道中  
114                 bf.flip();  
115                   
116                 int outlength =0;  
117                 while((outlength=outchannel.write(bf)) != 0){  
118                     System.out.println("读,"+length+"写,"+outlength);  
119                 }  
120                   
121                 //将当前位置置为0,然后设置limit为容量,也就是从0到limit(容量)这块,  
122                 //都可以利用,通道读取的数据存储到  
123                 //0到limit这块  
124                 bf.clear();  
125                   
126             }  
127         } catch (FileNotFoundException e) {  
128             e.printStackTrace();  
129         } catch (IOException e) {  
130             e.printStackTrace();  
131         } finally {  
132             if (fin != null) {  
133                 try {  
134                     fin.close();  
135                 } catch (IOException e) {  
136                     e.printStackTrace();  
137                 }  
138             }  
139             if (fos != null) {  
140                 try {  
141                     fos.close();  
142                 } catch (IOException e) {  
143                     e.printStackTrace();  
144                 }  
145             }  
146         }  
147     }  
148   
149     @SuppressWarnings("resource")  
150     public static void main(String[] args) {  
151         testReadAndWriteNIO();  
152     }  
153   
154 }  

猜你喜欢

转载自www.cnblogs.com/cxxjohnson/p/9082567.html
今日推荐