Java NIO 学习笔记(四)----文件通道和网络通道

目录:
Java NIO 学习笔记(一)----概述,Channel/Buffer
Java NIO 学习笔记(二)----聚集和分散,通道到通道
Java NIO 学习笔记(三)----Selector
Java NIO 学习笔记(四)----文件通道和网络通道

FileChannel 文件通道

FileChannel 是连接到文件的通道,可以从文件中读取数据,并将数据写入文件,可以替代使用标准 IO 读写文件的操作。

注意 FileChannel 无法设置为非阻塞模式。 它始终以阻塞模式运行。

打开 FileChannel

在使用 FileChannel 之前必须先将其打开。 无法直接打开 FileChannel ,必须通过 InputStream,OutputStream 或 RandomAccessFile 获取 FileChannel 。 以下是通过 RandomAccessFile 打开 FileChannel 的方法:

RandomAccessFile aFile = new RandomAccessFile("D:\\test\\input.txt", "rw"); FileChannel inChannel = aFile.getChannel(); 从 FileChannel 读写数据

这是通过调用 read()/write() 方法之一完成的,读和写都是针对一个 ByteBuufer 对象的。
这是一个例子:

// 这里省略 2 个 Channel 的定义... ByteBuffer buffer = ByteBuffer.allocate(48); buffer.clear(); // 清除缓冲区,准备写入数据 int bytesRead = inChannel.read(buffer); // 将 inChannel 的数据读入缓冲区 buffer.flip(); // 反转缓冲区,就是把指针放到开头,并设置 limit 标记结尾 while(buffer.hasRemaining()) { // 只要缓冲区还有数据 outChannel.write(buffer); // 就将缓冲区数据写入通道 }

分配缓冲区后,调用 FileChannel 对象的 read() 方法将 FileChannel 中的数据读入 Buffer ,返回的 int 代表读取的字节数。 如果返回 -1,则到达文件结尾。

使用 write() 方法将数据写入 FileChannel ,该方法同样将 Buffer 作为参数,注意在 while 循环中调用 write() 方法。 这是因为无法保证 write() 方法写入 FileChannel 的字节数。 因此,我们重复调用 write() 方法,直到 Buffer 中没有要写入通道的字节。

关闭 FileChannel

使用 FileChannel 后,必须将其关闭:

channel.close(); FileChannel Position 指定操作位置

可以调用 position() 方法获取 FileChannel 对象的当前位置,调用 position(long pos) 方法来设置 FileChannel 的位置,这样就可以在特定位置开始读取或写入 FileChannel 。
一个例子:

// 获取当前位置 long pos = channel.position(); // 指定通道的位置,0 <= position <= limit channel.position(pos +123);

如果位置设置在文件结束后面:

读取操作将得到 -1 ---- 文件结束标记。

写入操作,文件将扩大到指定位置并写入数据。 这可能导致“文件漏洞”,磁盘上的物理文件数据中存在间隙。(比如开始顺序写入123后,此时 position=3,手动指定 position = 6,写入4,那此时磁盘物理文件应该是['1', '2', '3', '~', '~', '~', '4'],中间有3个位置是空的)

获取 FileChannel 的大小信息

FileChannel 对象的 size() 方法返回通道所连接文件的文件大小。 这是一个简单的例子:

long fileSize = channel.size(); FileChannel Truncate(截断)

可以通过调用 FileChannel 对象的 truncate() 方法截断文件。 截断文件时,会以给定长度将其剪切掉,即指定长度后面部分被删除。 这是一个例子,将文件长度截断为 1024 字节:

channel.truncate(1024); 将 FileChannel 数据强制保存到磁盘

FileChannel 对象的 void force(boolean metaData) 方法强制将所有未写入磁盘的数据从通道刷新到磁盘。 出于性能原因,操作系统可能会将数据缓存在内存中,因此在调用 force() 方法之前,无法保证写入通道的数据实际写入磁盘。
boolean 参数指定是否应该刷新文件元数据(权限信息等)到磁盘。

channel.force(true); channel.force(flase); SocketChannel 套接字通道

SocketChannel 是连接到 TCP 网络套接字的通道,相当于 Java 网络编程的套接字。可以通过两种方式创建:

打开 SocketChannel 并连接到 Internet 上的某个服务器,即向服务器发出连接。

当传入连接到达 ServerSocketChannel 时,创建 SocketChannel ,即接收客户端发来的连接。

打开和关闭 SocketChannel

以下是打开SocketChannel的方法:

SocketChannel socketChannel = SocketChannel.open(); socketChannel.connect(new InetSocketAddress("http://baidu.com", 80)); socketChannel.close();

InetSocketAddress 是 SocketAddress 类的子类,为(IP地址+端口号)类型,也就是端口地址类型,可以使用静态方法 createUnresolved(String host, int port) 获取对象,另外也能由构造函数 InetSocketAddress(InetAddress addr, int port) 创建,其中 InetAddress 对象可省略,也可用字符串代替。

通过 SocketChannel 读写数据 // 这里省略 2 个 Channel 的定义... ByteBuffer buffer = ByteBuffer.allocate(48); buffer.clear(); // 清除缓冲区,准备写入数据 int bytesRead = socketChannel.read(buffer); // 将 socketChannel 的数据读入缓冲区 buffer.flip(); // 反转缓冲区,就是把指针放到开头,并设置 limit 标记结尾 while(buffer.hasRemaining()) { // 只要缓冲区还有数据 channel.write(buffer);// 就将缓冲区数据写入通道 }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpwwgs.html