FileChannel

概述

1、用于读取,写入,映射和操作文件的通道

2、只能在阻塞模式下工作,所以无法搭配 Selector 使用

 

获取 FileChannel 对象

1、返回与该 FileInputStream 相关的唯一 FileChannel 对象

public FileChannel getChannel() {
    synchronized (this) {
        if (channel == null) {
            channel = FileChannelImpl.open(fd, path, true, false, this);
        }
        return channel;
    }
}

(1)通过 FileInputStream 获取的 Channel 只能读

(2)返回 Channel 的初始 position,将等于到目前为止从文件中读取的字节数

(3)从该 FileOutputStream 读取字节将增加 Channel 的 position

(4)改变 Channel 的 position,无论是显式设置,还是通过读取,都将改变该 FileOutputStream 的文件 position

2、返回与此 FileOutputStream 相关联的唯一 FileChannel 对象

public FileChannel getChannel() {
    synchronized (this) {
        if (channel == null) {
            channel = FileChannelImpl.open(fd, path, false, true, append, this);
        }
        return channel;
    }
}

(1)通过 FileOutputStream 获取的 Channel 只能写

(2)返回 Channel 的初始 position,将等于写入文件的字节数,除非该 FileOutputStream 是 append 模式,在这种情况下,position 将等于文件的大小

(3)将字节写入此 FileOutputStream 将相应地增加 Channel 的 position

(4)显式设置,或通过写入,以更改 Channel 的 position 将会改变这个 FileOutputStream 的文件 position

3、创建随机访问文件流,以从中指定名称的文件读取,并可选择写入文件。 创建一个新的FileDescriptor对象来表示与该文件的连接

public RandomAccessFile(String name, String mode) throws FileNotFoundException {
    this(name != null ? new File(name) : null, mode);
}
public RandomAccessFile(File file, String mode) throws FileNotFoundException {
    String name = (file != null ? file.getPath() : null);
    int imode = -1;
    if (mode.equals("r"))
        imode = O_RDONLY;
    else if (mode.startsWith("rw")) {
        imode = O_RDWR;
        rw = true;
        if (mode.length() > 2) {
            if (mode.equals("rws"))
                imode |= O_SYNC;
            else if (mode.equals("rwd"))
                imode |= O_DSYNC;
            else
                imode = -1;
        }
    }
    if (imode < 0)
        throw new IllegalArgumentException("Illegal mode \"" + mode
                                           + "\" must be one of "
                                           + "\"r\", \"rw\", \"rws\","
                                           + " or \"rwd\"");
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkRead(name);
        if (rw) {
            security.checkWrite(name);
        }
    }
    if (name == null) {
        throw new NullPointerException();
    }
    if (file.isInvalid()) {
        throw new FileNotFoundException("Invalid file path");
    }
    fd = new FileDescriptor();
    fd.attach(this);
    path = name;
    open(name, imode);
}

(1)r:只读模式,调用结果对象的任何写入方法,都会导致抛出一个 IOException

(2)rw:读写模式,如果该 File 不存在,那么将尝试创建它

(3)rws:读写模式,同时要求对文件内容或元数据的每一次更新,都要同步写入底层存储设备

(4)rwd:读写模式,并且要求对文件内容的每一次更新,都同步写入底层存储设备

(5)rws、rwd 类似 FileChannel 的 force(),分别对应传入 true、false,但它们总是适用于每个 I / O 操作,因此通常更有效

(6)如果文件驻留在本地存储设备上,则当该类的方法的调用返回时,将保证通过该调用对文件所做的所有更改都将被写入该设备,这确保系统崩溃时不会丢失关键信息,如果文件不在本地设备上,则不会提供此类保证

(7)rwd 可用于减少执行 I / O 操作数,只需要更新要写入存储的文件内容

(8)rws 需要更新要写入的文件内容及其元数据,这通常需要至少一个低级 I / O 操作

 

将字节序列从给定缓冲区写入此通道

public abstract int write(ByteBuffer src) throws IOException;

1、字节从该通道的当前文件 position 开始写入,除非通道处于 append 模式,在这种情况下,position 首先提前到文件的末尾

2、如果需要,文件扩容以容纳写入的字节,然后文件位置用实际写入的字节数更新

3、否则,此方法的行为与 WritableByteChannel 接口的规定完全相同

4、src:要检索字节的缓冲区

5、返回写入的字节数,可能为 0

6、不限制 Buffer 写入 FileChannel 的数据量

 

将字节序列从此通道读取到给定的缓冲区中

public abstract int read(ByteBuffer dst) throws IOException;

1、从该通道的当前文件 position 开始读取字节,然后以实际读取的字节数更新文件 position

2、否则,此方法的行为与 ReadableByteChannel 中的规定完全相同

3、dst:要传输字节的缓冲区

4、返回读取的字节数,可能为 0,如果通道已达到流出端, 则为 -1

 

关闭

public void close() throws IOException

1、使用 try-catch-resource 语法糖

2、如果 Stream / RandomAccessFile 具有相关联的信道,则该信道也被关闭

 

返回此 FileChannel 的文件 position

public abstract long position() throws IOException;

1、该 FileChannel 的文件 position,是从文件开始到当前 position 的非负整数

 

设置 FileChannel 的文件 position

public abstract FileChannel position(long newPosition) throws IOException;

1、将 position 设置为大于文件当前大小的值是合法的,但不会更改文件的大小

2、尝试在该 position 读取字节,将立即返回 -1(文件结束标志)

3、尝试在该 position 写入字节,将导致文件扩容以适应新的字节,导致文件空洞,不指定上一个文件结尾和新写入的字节之间的任何字节的值

4、newPosition:一个非负整数,从文件开始计数字节数

 

返回此 FileChannel 关联文件的当前大小

public abstract long size() throws IOException;

1、该 FileChannel 关联文件的当前大小,以字节为单位

 

将此 FileChannel 的文件截断为给定大小

public abstract FileChannel truncate(long size) throws IOException;

1、如果给定的大小小于文件的当前大小,则文件将被截断,丢弃超出文件新末尾的所有字节

2、如果给定的大小大于或等于文件的当前大小,则该文件不会被修改

3、size:新的大小,非负字节数

 

强制将此 FileChannel 文件的任何更新,写入包含该  FileChannel 的存储设备

public abstract void force(boolean metaData) throws IOException

1、如果此  FileChannel 的文件驻留在本地存储设备上,那么当该方法返回时,将保证自创建该通道以来创建的该文件所做的所有更改,或自上次调用该方法以来,都将写入该设备,确保系统崩溃时不会丢失关键信息,如果文件不在本地设备上,则不会提供此类保证

2、metaData 限制此方法执行所需 I / O 操作数,false 表示只写入文件的内容的更新,true 表示必须写入文件的内容和元数据的更新,这通常需要至少一个 I / O操作,该参数实际上是否具有任何效果取决于底层操作系统,因此不指定

3、调用此方法可能会导致 I / O 操作发生,即使通道为只读模式,例如,某些操作系统将最后访问时间作为文件的元数据的一部分进行维护,并且每次读取文件时都会更新此时间,这是否实际上是系统依赖的,因此是不指定的

4、这个方法只保证强制改变这个通道的文件,这些改变是通过这个类中定义的方法进行的,它可能会强制修改通过调用 map 方法获得的映射的字节缓冲区的内容,调用映射的字节缓冲区的强制方法将强制写入对缓冲区内容的修改

5、metaData:true 强制更改文件的内容和要写入存储的元数据,false 只需要强制更改内容

 

集中写:从给定的缓冲区向该通道写入一系列字节

public final long write(ByteBuffer[] srcs) throws IOException

1、字节从该通道的当前文件位置开始写入,除非通道处于 append 模式,在这种情况下,position 首先提前到文件的末尾

2、如果需要,文件扩容以容纳写入的字节,然后文件位置用实际写入的字节数更新,否则,此方法的行为与 GatheringByteChannel 接口中的规定完全相同

3、srcs:要检索字节的缓冲区

4、返回写入的字节数,可能为 0

 

分散读:从该通道读取到给定缓冲区的字节序列

public final long read(ByteBuffer[] dsts) throws IOException

1、从该通道的当前文件位置开始读取字节,然后以实际读取的字节数更新文件位置,否则,此方法的行为与 ScatteringByteChannel 接口中的规定完全相同

2、dsts:要传输字节的缓冲区

3、返回读取的字节数,可能为 0,如果通道已达到流出末尾, 则为 -1

 

从给定的可读字节通道,将字节传输到该通道的文件中

public abstract long transferFrom(ReadableByteChannel src,
                                  long position,
                                  long count)
                           throws IOException

1、尝试从 src 读取 count 个字节,并将其写入此通道的文件,从给定 position 开始

2、此方法的调用可能会传送或不传送所有请求的字节,是否这样做取决于渠道的性质和状态

3、如果 src 剩余少于 count 个字节,或者 src 为非阻塞,并且其输入缓冲区中立即可用的字节少于 8841760419806 字节,则将少于所请求的字节数

4、此方法不会修改此 FileChannel 的 position

5、如果给定的位置大于文件的当前大小,则不会传输任何字节

6、如果 src 具有 position,则从该 position 开始读取字节,然后将该位置递增读取的字节数

7、该方法比从 src 读取并写入此通道的简单循环可能更有效,许多操作系统可以将字节直接从 src 传输到文件系统高速缓存中,而无需实际复制它们

8、src:源频道

9、position:传输开始的文件中的位置,必须是非负的

10、count:要传输的最大字节数,必须是非负的

11、返回实际传输的字节数,可能为 0

 

将该通道文件的字节传输到给定的可写字节通道

public abstract long transferTo(long position,
                                long count,
                                WritableByteChannel target)
                         throws IOException

1、尝试从该通道文件中的给定 position 开始,读取最多 count 个字节,并将其写入目标通道

2、此方法的调用可能会传送或不传送所有请求的字节,是否这样做取决于渠道的性质和状态

3、如果该通道的文件包含少于 count 个字节,从给定的 position 开始,或者如果目标通道是非阻塞的,并且在其输出缓冲区中有少于 count 个字节的空闲, 那么传输的字节数将少于所请求的字节数

4、此方法不会修改此通道的位置

5、如果给定的位置大于文件的当前大小,则不会传输任何字节

6、如果目标通道具有位置,则从该位置开始写入字节,然后将该位置递增写入的字节数

7、该方法比从该通道读取并写入目标通道的简单循环更有效,许多操作系统可以将字节直接从文件系统缓存传输到目标通道,而无需实际复制它们

8、position:传输开始的文件中的位置,必须是非负的

9、count:要传输的最大字节数,必须是非负的

10、target:目标通道

11、返回实际传输的字节数,可能为 0

12、FileChannelImpl 的 transferTo 一次只能传输 2147483647L(2GiB - 1byte)

int var8 = (int)Math.min(var3, 2147483647L);
posted @   半条咸鱼  阅读(155)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示