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

 

读写文件代码

import java.io.File;  
import java.io.FileInputStream;  
import java.io.FileNotFoundException;  
import java.io.FileOutputStream;  
import java.io.IOException;  
import java.nio.ByteBuffer;  
import java.nio.channels.FileChannel;  
import java.nio.charset.Charset;  
  
public class TestJavaNIO {  
  
    static void readNIO() {  
        String pathname = "C:\\Users\\adew\\Desktop\\jd-gui.cfg";  
        FileInputStream fin = null;  
        try {  
            fin = new FileInputStream(new File(pathname));  
            FileChannel channel = fin.getChannel();  
  
            int capacity = 100;// 字节  
            ByteBuffer bf = ByteBuffer.allocate(capacity);  
            System.out.println("限制是:" + bf.limit() + "容量是:" + bf.capacity()  
                    + "位置是:" + bf.position());  
            int length = -1;  
  
            while ((length = channel.read(bf)) != -1) {  
  
                /*  
                 * 注意,读取后,将位置置为0,将limit置为容量, 以备下次读入到字节缓冲中,从0开始存储  
                 */  
                bf.clear();  
                byte[] bytes = bf.array();  
                System.out.write(bytes, 0, length);  
                System.out.println();  
  
                System.out.println("限制是:" + bf.limit() + "容量是:" + bf.capacity()  
                        + "位置是:" + bf.position());  
  
            }  
  
            channel.close();  
  
        } catch (FileNotFoundException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            if (fin != null) {  
                try {  
                    fin.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
    }  
  
    static void writeNIO() {  
        String filename = "out.txt";  
        FileOutputStream fos = null;  
        try {  
  
            fos = new FileOutputStream(new File(filename));  
            FileChannel channel = fos.getChannel();  
            ByteBuffer src = Charset.forName("utf8").encode("你好你好你好你好你好");  
            // 字节缓冲的容量和limit会随着数据长度变化,不是固定不变的  
            System.out.println("初始化容量和limit:" + src.capacity() + ","  
                    + src.limit());  
            int length = 0;  
  
            while ((length = channel.write(src)) != 0) {  
                /*  
                 * 注意,这里不需要clear,将缓冲中的数据写入到通道中后 第二次接着上一次的顺序往下读  
                 */  
                System.out.println("写入长度:" + length);  
            }  
  
        } catch (FileNotFoundException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            if (fos != null) {  
                try {  
                    fos.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
    }  
  
    static void testReadAndWriteNIO() {  
        String pathname = "C:\\Users\\adew\\Desktop\\test.txt";  
        FileInputStream fin = null;  
          
        String filename = "test-out.txt";  
        FileOutputStream fos = null;  
        try {  
            fin = new FileInputStream(new File(pathname));  
            FileChannel channel = fin.getChannel();  
  
            int capacity = 100;// 字节  
            ByteBuffer bf = ByteBuffer.allocate(capacity);  
            System.out.println("限制是:" + bf.limit() + "容量是:" + bf.capacity()+ "位置是:" + bf.position());  
            int length = -1;  
  
            fos = new FileOutputStream(new File(filename));  
            FileChannel outchannel = fos.getChannel();  
              
              
            while ((length = channel.read(bf)) != -1) {  
                  
                //将当前位置置为limit,然后设置当前位置为0,也就是从0到limit这块,都写入到同道中  
                bf.flip();  
                  
                int outlength =0;  
                while((outlength=outchannel.write(bf)) != 0){  
                    System.out.println("读,"+length+"写,"+outlength);  
                }  
                  
                //将当前位置置为0,然后设置limit为容量,也就是从0到limit(容量)这块,  
                //都可以利用,通道读取的数据存储到  
                //0到limit这块  
                bf.clear();  
                  
            }  
        } catch (FileNotFoundException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            if (fin != null) {  
                try {  
                    fin.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
            if (fos != null) {  
                try {  
                    fos.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
    }  
  
    @SuppressWarnings("resource")  
    public static void main(String[] args) {  
        testReadAndWriteNIO();  
    }  
  
}  

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java NIO(New Input/Output)是Java 1.4版本引入的一组用于快速、高效地处理输入输出操作的API。Java NIO提供了ByteBuffer类来支持基于通道(Channel)的输入输出操作。 在Java NIO中,可以使用ByteBuffer读取文件,而每个ByteBuffer中的元素大小是以字节为单位的。由于题目中要求用2个字节来读取文件,我们可以利用ByteBuffer的两个字节缓冲区来实现。 首先,我们需要创建一个ByteBuffer对象,并设置它的容量为2个字节,代码如下: ```java ByteBuffer buffer = ByteBuffer.allocate(2); ``` 然后,我们需要获取一个文件通道(FileChannel)对象,代码如下: ```java FileInputStream fis = new FileInputStream("文件路径"); FileChannel channel = fis.getChannel(); ``` 接下来,我们可以使用ByteBuffer的read方法从通道中读取字节,代码如下: ```java int bytesRead = channel.read(buffer); ``` 需要注意的是,读取操作可能不一定能够读取到2个字节,所以我们需要通过`bytesRead`变量来判断实际读取到的字节数。 最后,我们可以通过ByteBuffer的get方法获取读取到的字节数据,并进行相应的处理,代码如下: ```java buffer.flip(); if (buffer.hasRemaining()) { byte[] bytes = new byte[buffer.remaining()]; buffer.get(bytes); // 进行相关操作,比如将字节转换为字符串 } ``` 注意,在读取完成后,我们需要调用ByteBuffer的flip方法来进行反转操作,以准备读取已经写入的字节数据。然后,我们可以通过ByteBuffer的hasRemaining方法来判断是否还有剩余字节未读取,如果有,我们可以通过remaining方法获取剩余字节数,并将它们读取到一个字节数组中。 总的来说,通过Java NIO中的ByteBuffer类,我们可以方便、快速地以2个字节为单位读取文件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值