Java NIO Channel之FileChannel [ 转载 ]
Java NIO Channel之FileChannel [ 转载 ]
@author zachary.guo
对于文件 I/O,最强大之处在于异步 I/O(asynchronous I/O),它允许一个进程可以从操作系统请求一个或多个 I/O 操作而不必等待这些操作的完成。发起请求的进程之后会收到它请求的 I/O 操作已完成的通知。异步 I/O 是一种高级性能,当前的很多操作系统都还不具备。因此,文件通道在多数情况下来说总是阻塞式的,因此不能被置于非阻塞模式。
FileChannel 对象不能直接创建。一个 FileChannel 实例只能通过在一个打开的 File 对象(RandomAccessFile、FileInputStream 或 FileOutputStream)上调用 getChannel() 方法获取。调用 getChannel() 方法会返回一个连接到相同文件的 FileChannel 对象且该 FileChannel 对象具有与 File 对象相同的访问权限,然后你就可以使用通道对象来利用强大的 FileChannel API了:
- package java.nio.channels;
- public abstract class FileChannel extends AbstractChannel implements ByteChannel, GatheringByteChannel, ScatteringByteChannel {
- // This is a partial API listing
- // All methods listed here can throw java.io.IOException
- public abstract int read(ByteBuffer dst, long position);
- public abstract int write(ByteBuffer src, long position);
- public abstract long size();
- // 返回当前文件的 position 值。返回值是一个长整型(long),表示文件中的当前字节位置。
- public abstract long position();
- // 将通道的 position 设置为指定值。负值,将异常伺候;值可以超过文件尾,这会导致文件空洞。
- public abstract void position(long newPosition);
- public abstract void truncate(long size);
- public abstract void force(boolean metaData);
- public final FileLock lock();
- public abstract FileLock lock(long position, long size, boolean shared);
- public final FileLock tryLock();
- public abstract FileLock tryLock(long position, long size, boolean shared);
- public abstract MappedByteBuffer map(MapMode mode, long position, long size);
- public abstract long transferTo(long position, long count, WritableByteChannel target);
- public abstract long transferFrom(ReadableByteChannel src, long position, long count);
- public static class MapMode {
- public static final MapMode READ_ONLY;
- public static final MapMode READ_WRITE;
- public static final MapMode PRIVATE;
- }
- }
同大多数通道一样,只要有可能,FileChannel 都会尝试使用本地 I/O 服务。FileChannel 类本身是抽象的,你从 getChannel() 方法获取的实际对象是一个具体子类(subclass)的一个实例(instance),该子类可能使用本地代码来实现以上 API 方法中的一些或全部。
FileChannel 对象是线程安全(thread-safe)的。多个进程可以在同一个实例上并发调用方法而不会引起任何问题,不过并非所有的操作都是多线程的(multithreaded)。影响通道位置或者影响文件大小的操作都是单线程的(single-threaded)。如果有一个线程已经在执行会影响通道位置或文件大小的操作,那么其他尝试进行此类操作之一的线程必须等待。并发行为也会受到底层的操作系统或文件系统影响。
◇ 访问文件
每个 FileChannel 对象都同一个文件描述符(file descriptor)有一对一的关系,所以上面列出的 API 方法与在你最喜欢的 POSIX(可移植操作系统接口)兼容的操作系统上的常用文件 I/O 系统调用紧密对应也就不足为怪了。
本质上讲,RandomAccessFile 类提供的是同样的抽象内容。在通道出现之前,底层的文件操作都是通过 RandomAccessFile 类的方法来实现的。FileChannel 模拟同样的 I/O 服务,因此它的 API 自然也是很相似的。

File I/O API 比较
同底层的文件描述符一样,每个 FileChannel 都有一个叫 “file position”的概念。这个 position 值决定文件中哪一处的数据接下来将被读或者写。因此,FileChannel 位置(position)是从底层的文件描述符获得的,该 position 同时被作为通道引用获取来源的文件对象共享。这也就意味着一个对象对该 position 的更新可以被另一个对象看到:
- RandomAccessFile randomAccessFile = new RandomAccessFile ("filename", "r");
- // Set the file position
- randomAccessFile.seek (1000);
- // Create a channel from the file
- FileChannel fileChannel = randomAccessFile.getChannel( );
- // This will print "1000"
- System.out.println ("file pos: " + fileChannel.position( ));
- // Change the position using the RandomAccessFile object
- randomAccessFile.seek (500);
- // This will print "500"
- System.out.println ("file pos: " + fileChannel.position( ));
- // Change the position using the FileChannel object
- fileChannel.position (200);
- // This will print "200"
- System.out.println ("file pos: " + randomAccessFile.getFilePointer( ));
尝试在文件末尾之外的 position 进行一个绝对 read() 操作,size() 方法会返回一个 end-of-file。在超出文件大小的 position 上做一个绝对 write() 会导致文件增加以容纳正在被写入的新字节。文件中位于之前 end-of-file 位置和新添加的字节起始位置之间区域的字节的值不是由 FileChannel 类指定,而是在大多数情况下反映底层文件系统的语义。不过,大部分情况下,这些空洞会被填 0。
当需要减少一个文件的 size 时,truncate() 方法会砍掉您所指定的新 size 值之外的所有数据。如果当前 size 大于新 size,超出新 size 的所有字节都会被悄悄地丢弃。如果提供的新 size 值大于或等于当前的文件 size 值,该文件不会被修改。这两种情况下,truncate() 都会产生副作用:文件的 position 会被设置为所提供的新 size 值。
上面列出的最后一个 API 是 force()。该方法告诉通道强制将全部待定的修改都应用到磁盘的文件上。所有的现代文件系统都会缓存数据和延迟磁盘文件更新以提高性能。调用 force() 方法要求文件的所有待定修改立即同步到磁盘。
◇ 文件空洞
文件位移量可以大于文件的当前长度,在这种情况下,对该文件的下一次写将延长该文件,并在文件中构成一个空洞,这一点是允许的。位于文件中但没有写过的字节都被设为 0。
如果 offset 比文件的当前长度更大,下一个写操作就会把文件“撑大(extend)”。这就是所谓的在文件里创造“空洞(hole)”。没有被实际写入文件的所有字节由重复的 0 表示。空洞是否占用硬盘空间由文件系统(file system)决定。
Java NIO Channel之FileChannel [ 转载 ]的更多相关文章
- Java NIO Channel和Buffer
Java NIO Channel和Buffer @author ixenos Channel和Buffer的关系 1.NIO速度的提高来自于所使用的结构更接近于OS执行I/O的方式:通道和缓冲器: 2 ...
- Java NIO Channel通道
原文链接:http://tutorials.jenkov.com/java-nio/channels.html Java NIO Channel通道和流非常相似,主要有以下几点区别: 通道可以读也可以 ...
- (三:NIO系列) Java NIO Channel
出处: Java NIO Channel 1.1. Java NIO Channel的特点 和老的OIO相比,通道和NIO流(非阻塞IO)主要有以下几点区别: (1)OIO流一般来说是单向的(只能读或 ...
- [翻译] java NIO Channel
原文地址:http://tutorials.jenkov.com/java-nio/channels.html JAVA NIO channels和流的概念很像,下面是他们的一些区别: 你可以对cha ...
- Java NIO Channel to Channel Transfers通道传输接口
原文链接:http://tutorials.jenkov.com/java-nio/channel-to-channel-transfers.html 在Java NIO中如果一个channel是Fi ...
- Java NIO Channel to Channel Transfers
In Java NIO you can transfer data directly from one channel to another, if one of the channels is a ...
- JAVA NIO 内存映射(转载)
原文地址:http://blog.csdn.net/fcbayernmunchen/article/details/8635427 Java类库中的NIO包相对于IO 包来说有一个新功能是内存 ...
- Java NIO 文件通道 FileChannel 用法
FileChannel 提供了一种通过通道来访问文件的方式,它可以通过带参数 position(int) 方法定位到文件的任意位置开始进行操作,还能够将文件映射到直接内存,提高大文件的访问效率.本文将 ...
- Java NIO Channel 使用
Java NIO 中的 Channel 分类: FileChannel SocketChannel ServerSocketChannel DatagramChannel channel 分类 Fil ...
随机推荐
- weblogic配置修改java代码后不需要重启热部署方式
我用的是weblogic8.x 在项目的WEB-INFO中创建weblogic.xml --------以下内容复制到weblogic.xml中------------ <!DOCTYPE we ...
- WPF实现打印功能
WPF实现打印功能 在WPF 中可以通过PrintDialog 类方便的实现应用程序打印功能,本文将使用一个简单实例进行演示.首先在VS中编辑一个图形(如下图所示). 将需要打印的内容放入同一个< ...
- 4605 Magic Ball Game
先离线记录所有询问,然后用dfs在线记录当前节点的所有父亲结点,父亲结点分为两类,一个从左边过来,一个从右边过来,分别开一个数组. 数据需要离散化,刚开始用lower_bound写,一直wa..,用二 ...
- 线程内唯一对象HttpContext
在asp.net中,HttpContext是主线程内唯一对象.在web应用中开启多线程,在另外一个线程中是无法访问HttpContext. 如果需要在另外一个线程中使用HttpContext.Curr ...
- php的数组与字符串的转换函数整理
1.将一个字符串转化为数组 str_split()用于将一个字符串转化为数组 语法: str_split(string,length) //string是必须的,是要分割的字符串: //length是 ...
- 从ICassFactory为CLSID为{17BCA6E8-A950-497E-B2F9-AF6AA475916F}的COM组件创建实例失败,原因是出现以下错误:c001f011.(Microsoft.Server.manageDTS
从ICassFactory为CLSID为{17BCA6E8-A950-497E-B2F9-AF6AA475916F}的COM组件创建实例失败,原因是出现以下错误:c001f011.(Microsoft ...
- ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第五章:排序、分页和路由
本章的重点是对产品信息增加排序和分页的功能,以及使用ASP.NET Routing特性添加更加友好的URL支持. 注意:如果你想按照本章的代码编写示例,你必须完成第四章或者直接从www.apress. ...
- Sql Server 自定义函数(原创)
---------------------------------------------------------------------------------------------- 传入字符串 ...
- Linux编程之UDP SOCKET全攻略
这篇文章将对linux下udp socket编程重要知识点进行总结,无论是开发人员应知应会的,还是说udp socket的一些偏僻知识点,本文都会讲到.尽可能做到,读了一篇文章之后,大家对udp so ...
- NET仿微信Oauth2.0
这个文章先说一说Oauth2.0的原理,再到应用场景,最后才是代码实现,这样才学会最终的思想,并在应用场景使用,所谓实践出真理. 1,Oauth2.0的原理 OAuth是一个关于授权(authoriz ...