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,目的是将有数据部分的字节,由缓冲写入到通道中。通常用在读与写之间。


读写文件代码

[html]  view plain  copy
  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. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值