`
zachary.guo
  • 浏览: 488010 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

NIO - FileChannel

    博客分类:
  • NIO
 
阅读更多
        对于文件 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)决定。
  • 大小: 41.2 KB
分享到:
评论

相关推荐

    Java NIO实战开发多人聊天室

    05-Java NIO-Channel-FileChannel详解(一).mp4 06-Java NIO-Channel-FileChannel详解(二).mp4 08-Java NIO-Channel-ServerSocketChannel.mp4 09-Java NIO-Channel-SocketChannel.mp4 10-Java NIO-Channel-...

    JAVA-NIO-DEMO

    Java NIO(New IO)是Java 1.4版本引入的一个新模块,它提供了一种不同于传统IO(基于字节流和字符流)的I/O操作方式。传统的IO模型是阻塞式的,而NIO的核心特点是非阻塞,这使得在处理大量并发I/O请求时更为高效。...

    java网络编程NIO视频教程

    Java NIO-异步FileChannel-CompletionHandler读数据 - **主要内容**:演示如何使用CompletionHandler处理异步读取的数据。 - **学习目标**:学会使用CompletionHandler进行异步数据处理。 通过以上内容的学习,...

    Java-NIO-系列教程

    ### Java NIO 系列教程知识点详解 #### 一、Java NIO 概述 Java NIO (New IO) 是 Java SE 1.4 版本引入的一种新的输入/输出方式,它提供了一种替代传统的 Java IO 包的方式。Java NIO 主要包括三个核心组成部分:*...

    bio-nio-aio.zip

    压缩包中的`demo3.txt`展示了如何使用NIO的`FileChannel`进行文件读写,而`demo4read.txt`和`demo4write.txt`则演示了如何利用`SocketChannel`进行网络通信。 三、反应器模式(Reactor) Reactor是Java NIO的一种...

    【IT十八掌徐培成】Java基础第27天-02.NIO-ServerSocketChannel-SocketChannel.zip

    通道是数据进出的路径,如FileChannel、SocketChannel、ServerSocketChannel等。它们提供了读写数据的方法,并且可以与Selector配合工作,实现高效的并发I/O操作。 7. **选择器模式(Selector Pattern)**: 通过...

    muyinchen#woker#07 Java的NIO之FileChannel1

    7.1 打开一个FileChannel 7.2 从FileChannel通道中读取数据 7.3 向FileChannel中写入数据: 7.4 关闭FileCha

    nio-study:尼奥研究

    例如,FileChannel用于文件操作,SocketChannel用于网络通信。 2. **缓冲区(Buffers)**:缓冲区是NIO中数据操作的主要对象,所有类型的Java原始类型都有对应的Buffer类,如ByteBuffer、CharBuffer等。数据在进行I...

    nio-demo:NIO编辑演示

    在NIO中,`java.nio`包提供了`FileChannel`类,它允许我们高效地在文件之间传输数据。与BIO中的`InputStream`和`OutputStream`不同,`FileChannel`可以进行内存映射文件操作,提高了大文件读写的效率。通过`...

    nio-2015:NIO 2015 第二轮——我的解决方案

    2. **Java NIO API**:学习如何使用java.nio包下的类和接口,如FileChannel、ByteBuffer、SelectionKey等,创建高效的I/O系统。 3. **C++异步I/O**:如果在C++中实现了NIO概念,那么会涉及到异步编程模型,如事件...

    java.util源码-Java.util-NIO-Source-code:基本输入和输出,包括带有NIO源代码的java.util读取文件

    例如,`java.nio.channels.FileChannel`类,它允许我们以非阻塞方式读写文件,提高了I/O性能。通过查看源码,我们可以学习到如何使用`transferTo()`和`transferFrom()`方法进行文件间的高效数据传输,或者如何使用`...

    NIO学习-Java源代码分享(含netty)

    常见的Channel类有FileChannel、SocketChannel、ServerSocketChannel等。 2. **Buffer**:Buffer是NIO中的数据容器,用于临时存储数据。Buffer有固定大小,当数据读取或写入时,会改变Buffer的状态,例如position...

    nio-开源

    4. **文件通道(FileChannel)**:允许直接在文件和缓冲区之间传输数据,减少了数据拷贝。 5. **管道(Pipe)**:提供进程间的双向数据流,不同于基于套接字的网络通信,管道主要用于同一JVM内的线程间通信。 6. **...

    nio压力测试

    在测试中,我们需要关注不同类型的通道(如FileChannel、SocketChannel)和缓冲区(ByteBuffer)的性能特性。 2. **选择器(Selectors)**:选择器允许单个线程监控多个通道的事件,如读写就绪。测试中会评估选择器...

    【IT十八掌徐培成】Java基础第26天-06.FileChannel-RandomAccessFile-CopyFile.zip

    首先,`FileChannel`是`java.nio.channels`包中的一个接口,它提供了低级的、高性能的文件操作。`FileChannel`的主要特性包括读写文件、映射内存到文件、锁定文件区域等。通过`FileInputStream`, `FileOutputStream`...

    无涯教程(LearnFk)-Java-Nio教程离线版.pdf

    Java NIO提供了多种类型的通道实现,例如FileChannel、SocketChannel、ServerSocketChannel和DatagramChannel。FileChannel用于文件的读写操作,而SocketChannel和ServerSocketChannel用于TCP网络通信,...

    java nio教程pdf

    Java NIO(New IO,也称为Non-Blocking IO)是一种基于通道(Channel)和缓冲区(Buffer)的I/O操作方法,用于替代标准Java IO API。Java NIO提供了与标准IO不同的I/O工作方式,它是面向缓冲区、基于通道的I/O操作,...

    JAVA-NIO程序设计完整实例

    **JAVA-NIO程序设计完整实例** Java NIO(New IO)是Java 1.4引入的一个新特性,它为Java提供了非阻塞I/O操作的能力,使得Java在处理I/O时更加高效。NIO与传统的BIO(Blocking I/O)模型相比,其核心在于它允许程序...

Global site tag (gtag.js) - Google Analytics