Java NIO用法

1.NIO

在Java的标准I/O中,提供了基于流的I/O实现,即InputStreamOutputStream。NIO是New I/O的是简称,基于块(Block),以块为基本单位处理数据。其中最主要的两个概念是缓冲(Buffer)和通道(Channel)。

NIO实现文件的拷贝,读取Channel中的数据,写入Buffer中,再从Buffer中读取。

public void copyFile(String fileInput, String fileOutput) {
    try {
        FileInputStream input = new FileInputStream(fileInput);
        FileOutputStream output = new FileOutputStream(fileOutput);

        FileChannel inputChannel = input.getChannel();
        FileChannel outputChannel = output.getChannel();

        ByteBuffer buffer = ByteBuffer.allocate(1024);			
        while(inputChannel.read(buffer) != -1) {
            buffer.flip();				
            outputChannel.write(buffer);				
            buffer.clear();
        }

        input.close();
        output.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

2.缓冲Buffer

Buffer有三个重要参数

  • 位置(position),从position开始读写
  • 容量(capacity),缓冲区的总容量上限。
  • 限制(limit),缓冲区数据上限。

Buffer创建

Buffer通过allocate(int)wrap()方法创建,初始化后,position0,而capacitylimit都为最大

ByteBuffer buffer = ByteBuffer.allocate(15);
BufferTool.printBuffer(buffer);

byte[] byteArray = new byte[10];
buffer = ByteBuffer.wrap(byteArray);
BufferTool.printBuffer(buffer);

输出

position = 0, capacity = 15, limit = 15
position = 0, capacity = 10, limit = 10

BufferTool.java文件

public static void printBuffer(Buffer buffer) {
    System.out.println("position = " + buffer.position()
            + ", capacity = " + buffer.capacity()
            + ", limit = " + buffer.limit());
}

Buffer读写

  • get(),返回当前position上的数据,并将position向后移一位。
  • get(byte[] dst),读取当前数据到dst中,并移动position位置。
  • get(int index),读取指定索引上的数据,不改变position位置。
  • put(byte),当前位置写入给定数据,position向后移一位。
  • put(byte[] src),写入给定数据,并移动position位置。
  • put(int index, byte b),指定索引写入给定数据,不改变position位置。

在下面示例中,我们首先调用put()方法添加,然后调用flip()进行读写转换,最后使用get()方法读取数据。

ByteBuffer buffer = ByteBuffer.allocate(15);
buffer.put((byte)0);
buffer.put((byte)1);

byte[] src = new byte[] {2, 3, 4};
buffer.put(src);
BufferTool.printBuffer(buffer);

buffer.flip();
System.out.println("after flip");
BufferTool.printBuffer(buffer);

System.out.println("get = " + buffer.get());
BufferTool.printBuffer(buffer);

byte[] dst = new byte[2];
buffer.get(dst);
System.out.println(dst[0] + ":" + dst[1]);
BufferTool.printBuffer(buffer);

输出

position = 5, capacity = 15, limit = 15
after flip
position = 0, capacity = 15, limit = 5
get = 0
position = 1, capacity = 15, limit = 5
1:2
position = 3, capacity = 15, limit = 5

修改Buffer状态

  • rewind(),将position清空。
  • clear(),也将position清空,同时将limit设置为capacity的大小。
  • flip(),实现读写转换,同时设置limitposition
  • mark(),用来记录当前位置。
  • reset(),用来恢复到mark所在的位置。

具体实现

public final Buffer rewind() {
    position = 0;
    mark = -1;
    return this;
}

public final Buffer clear() {
    position = 0;
    limit = capacity;
    mark = -1;
    return this;
}

public final Buffer flip() {
    limit = position;
    position = 0;
    mark = -1;
    return this;
}

public final Buffer mark() {
    mark = position;
    return this;
}

public final Buffer reset() {
    int m = mark;
    if (m < 0)
        throw new InvalidMarkException();
    position = m;
    return this;
}

3. ByteBuffer

  • duplicate(),以缓冲区为基础,生成一个完全一样的新缓冲区。新缓冲区与原缓冲区共享相同的内存数据,又独立维护各自的positionlimitmask

  • slice(),在现有的缓冲区中,创建新的子缓冲区,子缓冲区与父缓冲区共享内存数据。

    ByteBuffer buffer = ByteBuffer.allocate(15);
    for (int index = 0; index < 10; index++) {
        buffer.put((byte) index);
    }
    buffer.flip();
    BufferTool.printByteBuffer(buffer);
    
    ByteBuffer duplicateBuffer = buffer.duplicate();
    duplicateBuffer.put(0, (byte) 10);
    BufferTool.printByteBuffer(buffer);		
    
    buffer.position(3);
    buffer.limit(6);
    ByteBuffer sliceBuffer = buffer.slice();
    BufferTool.printByteBuffer(sliceBuffer);
    
    sliceBuffer.put(0, (byte) 30);
    buffer.limit(10);
    BufferTool.printByteBuffer(buffer);
    

    输出

    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    [10, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    [3, 4, 5]
    [10, 1, 2, 30, 4, 5, 6, 7, 8, 9]
    

    BufferTool.java文件

    public static void printByteBuffer(ByteBuffer buffer) {
        System.out.print("[");
        for (int index = 0; index < buffer.limit(); index++) {
            if (index != 0) {
                System.out.print(", ");	
            }
            System.out.print(buffer.get(index));
        }		
        System.out.println("]");
    }
    
  • asReadOnlyBuffer(),生成只读缓存区,可以保证数据不被修改。

  • allocateDirect(int capacity),直接访问物理内存。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值