X Tutup
#08.Java NIO FileChannel *FileChannel*是一个用于连接文件的通道类。使用*FileChannel*你可以读取文件的数据或往文件里写入数据。使用*FileChannel*可以代替标准的Java IO API中对文件的操作。 *FileChannel*不能设置为非阻塞模式,它总是以阻塞模式运行。 ##打开FileChannel(Opening a FileChannel) 当需要使用*FileChannel*时,你需要首先打开一个*FileChannel*,但你不能直接打开。你必须要通过*InputStream*,*OutputStream*或*RandomAccessFile*来获得一个*FileChannel*实例。如下面这个例子: ```Java RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw"); FileChannel inChannel = aFile.getChannel(); ``` ##从FileChannel中读取数据(Reading Data from a FileChannel) 从*FileChannel*中读取数据,可以调用多个重载的`read()`方法。 ```Java ByteBuffer buf = ByteBuffer.allocate(48); int bytesRead = inChannel.read(buf); ``` 当**缓冲区(Buffer)**分配之后,数据从*FileChannel*中读取到缓冲区。 当`FileChannel.read()`被调用后,这个方法会从*FileChannel*中读取数据到缓冲区。`read()`方法会返回一个int值,这个值代表了写入缓冲区的字节数。如果返回值是-1,则没有数据被读取。 ##往FileChannel中写入数据(Writing Data to a FileChannel) 往*FileChannel*中写数据用的是`FileChannel.write()`方法,这个方法也会带有个Buffer类型参数。 ```Java 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); } ``` 注意这里的`FileChannel.write()`方法是在while循环里面进行的。我们并不知道有多少数据要写入到*FileChannel*中,因此我们需要重复地调用`write()`方法直到缓冲区中没有数据可写。 ##关闭FileChannel(Closing a FileChannel) 当使用完FileChannel后,必须要关闭它: ```Java channel.close(); ``` ##FileChannel Position 当从*FileChannel*读取数据往其中写人数据时,我们需要要指定特定的位置。你可以通过调用`position()`方法来获得*FileChannel*当前的位置。 你也可以通过`position(long pos)`方法来设置*FileChannel*的位置。 ```Java long pos channel.position(); channel.position(pos +123); ``` 如果你将*position*设置到文件的末尾之后,当你再对*FileChannel*进行读取时,将会返回-1,表明读取到了文件末尾。 如果你将*position*设置到文件的末尾之后,让你往*FileChannel*写入数据时,文件就会自动拓展到`position`所指定的位置并写入数据。这会导致**文件空洞(File Hole)**。 ##FileChannel Size `FileChannel.size()`方法会返回通道所连接的文件的大小。 ```Java long fileSize = channel.size(); ``` ##FileChannel Truncate 你可以通过`FileChannel.truncate()`方法对通道所关联的文件进行截取: ```Java channel.truncate(1024); ``` ##FileChannel Force `FileChannel.force()`方法会将所有通道中的数据刷新到磁盘中。操作系统会处于性能考虑将数据缓存到内存中,所以你不能保证写入到通道中的数据会立刻同步到磁盘,因此你可以通过`force()`方法将通道中的数据刷新到物理磁盘。 `FileChannel.forece()`方法带有一个布尔类型的参数,这个参数用于指定文件的**元数据(meta data)**是否也需要刷新到物理磁盘。 ```Java channel.force(true); ```
X Tutup