Java NIO学习教程(四)

本文详细介绍了Java NIO中的FileChannel和SocketChannel的使用方法,包括读写操作、非阻塞模式、位置设置及文件截断等高级特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文地址: link.

8.Java NIO FileChannel

Java NIO FileChannel是连接文件的通道。使用文件通道,你可以从文件中读取数据,并将数据写入文件。 Java NIO FileChannel类是NIO替代标准Java IO API来实现读取文件。

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

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

RandomAccessFile aFile = new RandomAccessFile("data.txt", "rw");
FileChannel      inChannel = aFile.getChannel();

从FileChannel读取数据
要从FileChannel读取数据,可以调用其中的**read( )**方法。这是一个例子:

ByteBuffer buf = ByteBuffer.allocate(48);

int bytesRead = inChannel.read(buf);

首先分配缓冲区。从FileChannel读取的数据被读入Buffer。

其次,调用FileChannel.read( )方法。此方法将FileChannel中的数据读入 Buffer。read( )方法返回的int值得出缓冲区中有多少字节。如果返回-1,则到达文件结尾。

将数据写入FileChannel
使用FileChannel.write( )方法将数据写入FileChannel,该方法将Buffer作为参数。这是一个例子:

String newData = "New String to write to file..." + System.currentTimeMillis();

ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());

buf.flip();

while(buf.hasRemaining()) {
    channel.write(buf);
}

注意如何在while循环中调用FileChannel.write( )方法。无法保证write( )方法写入FileChannel的字节数。因此我们重复write( )调用,直到Buffer中没有其他字节要写入。

关闭FileChannel
当你完成使用时,你必须关闭FileChannel。这是如何做到的:

channel.close();   

FileChannel Position
在读取或写入FileChannel时,你可以在特定位置执行此操作。你可以通过调用position( )方法获取FileChannel对象的当前位置。

你还可以通过调用position(long pos)方法来设置FileChannel的位置。

这是两个例子:

long pos = channel.position();

channel.position(pos +123);

如果你在文件结束后设置位置,并尝试从通道读取,你将得到-1——文件结束标记。

如果在文件结束后设置位置并写入通道,则文件将扩展以适合位置并写入数据。这可能导致“文件漏洞”,其中磁盘上的物理文件在写入数据中存在间隙。

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

long fileSize = channel.size();    

FileChannel 截断
你可以通过调用FileChannel.truncate( )方法截断文件。截断文件时,会以给定长度将其剪切掉。这是一个例子:

channel.truncate(1024);

此示例以1024字节的长度截断文件。

FileChannel Force
FileChannel.force( )方法将所有未写入的数据从通道刷新到磁盘。出于性能原因,操作系统可能会将数据缓存在内存中,因此在调用该force( )方法之前,无法保证写入通道的数据实际写入磁盘。

force( )方法采用布尔值作为参数,告知是否应该刷新文件元数据(权限等)。

这是一个刷新数据和元数据的示例:

channel.force(true);

9.Java NIO SocketChannel

Java NIO SocketChannel是连接到TCP网络套接字的通道。它是Java NIO相当于Java Networking的套接字。有两种方法可以创建SocketChannel:

  • 打开SocketChannel并连接到Internet上的某个服务器。
  • 当传入连接到达ServerSocketChannel时,可以创建SocketChannel。

打开SocketChannel
以下是打开的方式SocketChannel方式:

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

关闭SocketChannel
在使用后通过调用SocketChannel.close( )方法关闭SocketChannel。这是如何做到的:

socketChannel.close();    

从SocketChannel读取
要从SocketChannel读取数据可以调用其中的read( )方法。这是一个例子:

ByteBuffer buf = ByteBuffer.allocate(48);

int bytesRead = socketChannel.read(buf);

首先分配缓冲区。从中SocketChannel读取的数据被读入Buffer。

其次,调用SocketChannel.read( )方法。此方法将数据从SocketChannel读入Buffer。read( )方法返回的int值得到缓冲区中有多少字节。如果返回-1,则到达流末尾(连接已关闭)。

写入SocketChannel
使用SocketChannel.write( )方法将数据写入SocketChannel,该方法将Buffer作为参数。这是一个例子:

String newData = "New String to write to file..." + System.currentTimeMillis();

ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());

buf.flip();

while(buf.hasRemaining()) {
    channel.write(buf);
}

注意如何在while循环中调用SocketChannel.write( )方法。无法保证write( )方法写入SocketChannel的字节数。因此我们重复write( )调用,直到Buffer中没有其他字节要写入。

非阻塞模式
你可以将SocketChannel设置为非阻塞模式。执行此操作时,可以在异步模式下调用connect( ),read( )和write( )。

connect( )
如果SocketChannel处于非阻塞模式,并且你调用connect( ),则该方法可能会在建立连接之前返回。要确定是否已建立连接,可以调用finishConnect()方法,如下所示:

socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress("http://jenkov.com", 80));

while(! socketChannel.finishConnect() ){
    //wait, or do something else...    
}

write( )
在非阻塞模式下,write( )方法可能在没有写入任何内容的情况下返回。因此,需要在循环中调用write( )方法。但是,由于这已经在之前的编写示例中完成,因此不需要在此处做任何不同的操作。

read( )
在非阻塞模式下,read( )方法可能在没有读取任何数据的情况下返回。因此,需要注意返回的int,它告诉读取了多少字节。

带Selector的非阻塞模式
使用Selector时,SocketChannel的非阻塞模式效果更好。通过使用选择器注册一个或多个SocketChannel,可以向选择器询问准备好读取,写入等的通道。如何在SocketChannel中使用Selector,将在本教程的后续文章中详细介绍。

【上篇】Java NIO学习教程(三)==>点击

【下篇】Java NIO学习教程(五)==>点击

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值