Java NIO

 

 

Capacity

A buffer's capacity is the number of elements it contains. The capacity of a buffer is never negative and never changes. 

 

Limit

A buffer's limit is the index of the first element that should not be read or written. A buffer's limit is never negative and is never greater than its capacity. 

limit 变量限制了当前buffer中可操作的容量大小。 向buffer写入数据时limit =capacity (除非使用limit(n)限制了limit大小),表明可写入的容量为limit ;调用flip()时Limit=Position,表面当前buffer可读取的容量是limit。 

 

Position 

A buffer's position is the index of the next element to be read or written. A buffer's position is never negative and is never greater than its limit. 

在从通道读取时,您将所读取的数据放到底层的数组中。 position 变量跟踪已经写了多少数据。更准确地说,它指定了下一个字节将放到数组的哪一个元素中。因此,如果您从通道中读三个字节到缓冲区中,那么缓冲区的 position 将会设置为3,指向数组中第四个元素。

同样,在写入通道时,您是从缓冲区中获取数据。 position 值跟踪从缓冲区中获取了多少数据。更准确地说,它指定下一个字节来自数组的哪一个元素。因此如果从缓冲区写了5个字节到通道中,那么缓冲区的 position 将被设置为5,指向数组的第六个元素。

 

Mark

A buffer's mark is the index to which its position will be reset when the reset method is invoked. The mark is not always defined, but when it is defined it is never negative and is never greater than the position.

标记读写的位置

 

0 <= mark <= position <= limit <= capacity 

remaining= limit - position 

 

默认值:

mark =-1 (未定义)

position =0

limit = capacity = n

 

重要方法:

flip()  由写buffer模式 改为从buffer读出模式

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

 clear() 重新回到写buffer模式

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

 

 

 mark() 标记当前读或写得位置

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

 

reset() 回到标记的位置

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

 

discarkMark() 清除标记

    final void discardMark() {                          // package-private
        mark = -1;
    }

 

 rewind() 位置归0,清除标记, 从头开始读或写

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

 

 

以下对比两种不同IO copy文件的方式:

	@Test
	public void copyByIO() throws Exception{
		FileInputStream fin = new FileInputStream("E:\\TechTools\\windows\\DEEP_GHOST_WIN7_SP1_X64_V2016_01.iso");
		FileOutputStream fout = new FileOutputStream("D:\\Data\\Log\\future\\DEEP_GHOST_WIN7_SP1_X64_V2016_01.iso");
		byte[] buffer = new byte[1024*1024];
		while(fin.read(buffer, 0, 1024*1024)!=-1){
			fout.write(buffer);
		}
		fin.close();
		fout.close();
	}


	@Test
	public void copyByNIO() throws Exception{
		FileInputStream fin = new FileInputStream("E:\\TechTools\\windows\\DEEP_GHOST_WIN7_SP1_X64_V2016_01.iso");
		FileOutputStream fout = new FileOutputStream("D:\\Data\\Log\\future\\DEEP_GHOST_WIN7_SP1_X64_V2016_01.iso");
		try {
			FileChannel chin = fin.getChannel();
			FileChannel chout = fout.getChannel();
			ByteBuffer buffer =ByteBuffer.allocate(1024*1024);
			int flag = 0;
			while(flag!=-1){
				buffer.flip();
				chout.write(buffer);
				
				buffer.clear();
				flag = chin.read(buffer);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			fin.close();
			fout.close();
		}
	}

  测试结果: NIO比IO略快。

 

Direct Buffer

与ByteBuffer.allocate(1024*1024)相似的另一个方法是ByteBuffer.allocateDirect(1024*1024)。它直接在OS内核分配内存,不占用JVM空间,就好比是“内核缓冲区”的内容直接写入了Channel,减少了数据拷贝,因此速度更快。著名的Netty就是使用DirectBuffer。

 

 

MappedByteBuffer 

将文件的全部或部分直接映射到内存,可以实现对文件的快速随机读取,对MappedByteBuffer的修改操作也可以直接反应到文件

	@Test
	public void testMappedByteBuffer() throws Exception{
		RandomAccessFile file = new RandomAccessFile("D:\\Data\\Log\\future\\1.txt", "rw");
		FileChannel chin = file.getChannel();
		MappedByteBuffer buffer = chin.map(MapMode.READ_WRITE, 0, chin.size());
		buffer.put(0, (byte)1);
		file.close();
	}
 

 

 

 

参考:

https://www.ibm.com/developerworks/cn/education/java/j-nio/index.html

<Direct buffer 与Heap Buffer的区别>http://blog.youkuaiyun.com/shibushiyouwenti/article/details/7396016

 

03-15
### Java NIO 教程与文档 Java NIO 是一种基于缓冲区和通道的 I/O 处理方式,相较于传统的 Java IO 更高效且适合处理大规模数据传输。以下是关于 Java NIO 的一些核心概念及其学习资源。 #### 1. **核心组件** Java NIO 主要由以下几个部分组成: - **Buffer**: 数据容器,用于存储不同类型的原始数据[^4]。 - **Channel**: 类似于流的概念,但支持双向读写操作。 - **Selector**: 支持多路复用机制,允许单线程管理多个 Channel。 这些组件共同构成了高效的非阻塞 I/O 模型,适用于网络编程和文件操作场景。 #### 2. **官方文档** Oracle 官方文档提供了详尽的 Java NIONIO.2 API 描述以及使用示例。可以通过访问 Oracle 官网并搜索 "Java SE documentation" 来获取最新的官方文档[^3]。 #### 3. **教程推荐** Baeldung 网站上的教程涵盖了 Java NIO 的基本原理及高级应用案例。例如,“Five ways to maximize Java NIO and NIO.2” 提供了五个重要的功能介绍,包括变更通知器(Change Notifiers),这使得监听事件变得更加简单。 #### 4. **实际应用场景** 通过结合实例代码可以更好地理解如何利用 Java NIO 实现高性能的数据传输。例如,在文件写入方面有多种实现方法,既可以直接采用标准库中的 `Files` 工具类,也可以借助更底层的 Buffer 和 Channel 结构完成复杂任务[^1]。 ```java import java.nio.file.*; import java.io.IOException; public class FileWriteExample { public static void main(String[] args) throws IOException { Path path = Paths.get("example.txt"); String content = "This is a test."; // 使用 Files.write 方法快速写入字符串到文件 Files.write(path, content.getBytes()); } } ``` 上述代码展示了如何利用 `Files.write()` 函数向指定路径下的文件写入一段文本内容。 --- ####
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值