Java FileChannel虚拟类

总结

  1. FileChannel虚拟类是用于读取、写入、映射和操作文件的通道
  2. FileChannel文件通道是连接到文件的SeekableByteChannel可查找通道。 它在其文件中有一个当前位置position,可以修改当前位置position在任意位置读取(读取越界会报错)和写入数据(写入越界会增加文件长度),当写入的字节超过其当前大小时,文件的大小会增加, 当调用truncate方法时,文件大小减小。文件还可能具有一些相关元数据,如访问权限、内容类型和上次修改时间,此类不定义元数据访问的方法
  3. 多个并发线程可以安全地使用文件通道。在同一时间只有一个线程能够进行通道的位置或文件大小更改操作,其他线程如果一样调用这些操作会阻塞
  4. 文件通道是通过调用此类定义的open方法之一创建的。还可以通过调用现有的java.io.FileInputStream#getChannel、java.io.FileOutputStream#getChannel或
    java.io.RandomAccessFile#getChannel对象的getChannel方法,从该对象获取文件通道,它返回连接到指定文件的文件通道。
  5. 如果文件通道是从现有流或RandomAccessFile获得的,那么文件通道的状态与getChannel方法返回通道的对象的状态密切相关。 无论是显式更改通道位置,还是通过读取或写入字节更改通道位置, 都将更改原始对象的文件位置,反之亦然。 通过文件通道更改文件长度将更改通过原始对象看到的长度,反之亦然。通过写入字节更改文件内容将更改原始对象看到的内容,反之亦然

FileChannel虚拟类方法

创建通道方法

方法名作用
static FileChannel open(Path path, Set<? extends OpenOption> options, FileAttribute<?>… attrs)打开或创建文件,返回访问该文件的文件通道。 path是要打开或创建的文件路径和文件名,options打开文件选项,attrs是文件属性数组,FileAttribute文件属性里面只有两个成员变量,一个属性名,一个属性值
static FileChannel open(Path path, OpenOption… options)打开或创建文件,返回访问该文件的文件通道。调用上面一个方法,只不过传入文件属性数组时,传递的是一个空数组

打开文件选项

选项名意义
StandardOpenOption.READ打开文件以进行读取
StandardOpenOption.WRITE打开文件以进行写入
StandardOpenOption.APPEND如果文件是为WRITE访问而打开的,那么字节将写入文件的末尾而不是开头,是附加选项,必须和WRITE一起使用
StandardOpenOption.TRUNCATE_EXISTING,如果文件已经存在,并且已打开以进行WRITE访问,则其长度将被截断为0(即清空文件), 如果文件仅为READ访问而打开,则会忽略此选项,是附加选项,必须和WRITE一起使用
StandardOpenOption.CREATE如果文件不存在,则创建新文件,如果还设置了CREATE_NEW选项,则忽略此选项
StandardOpenOption.CREATE_NEW创建新文件,如果文件已存在,则创建失败
StandardOpenOption.DELETE_ON_CLOSE关闭通道时删除文件,如果存在此选项,则实现将尽最大努力在通过适当的close方法关闭时删除该文件,如果未调用close方法,则会在Java虚拟机终止时尽最大努力删除该文件
StandardOpenOption.SPARSE创建稀疏文件,当与CREATE_NEW选项一起使用时,该选项会提示新文件将是稀疏的, 当文件系统不支持创建稀疏文件时,将忽略该选项。稀疏文件就是在文件中留有很多空余空间,留备将来插入数据使用。如果这些空余空间被ASCII码的NULL字符占据,并且这些空间相当大,那么这个文件就被称为稀疏文件,而且由于那些无用的0字节被用一定的算法压缩起来,所以声明一个很大的稀疏文件,其实占用的空间也很小
StandardOpenOption.SYNC要求对文件内容或元数据的每次更新都同步写入基础存储设备
StandardOpenOption.DSYNC要求对文件内容的每次更新都同步写入基础存储设备

读取方法

方法名作用
abstract int read(ByteBuffer dst)从该通道将字节序列读入给定的缓冲区,即将数据从文件中读取到内存缓冲区,返回的int是从文件中读取的字节数
abstract long read(ByteBuffer[] dsts, int offset, int length)从该通道将字节序列读入给定的缓冲区,这是给定一个缓冲区数组dsts,这里的offset和length不是针对文件的,而是针对dsts缓冲区数组的,offset指从缓冲区数组dsts的下标开始,填充length个缓冲区。读取文件的是位置是当前位置,和offset以及length无关。返回的long是从文件中读取的字节数
final long read(ByteBuffer[] dsts)从该通道将字节序列读入给定的缓冲区,调用的是上一个方法,只是传递的offset是0,length是缓冲区数组dsts的长度,即读取文件数据从第一个缓冲区开始填充直到把缓冲区数组所有缓冲区填满,或文件先到结尾
abstract int read(ByteBuffer dst, long position)从给定的文件位置开始,将字节序列从此通道读入给定的缓冲区,给定了文件中要读取的位置,读取文件写入缓冲区dst,写入的位置是根据缓冲区里面的位置决定的
abstract long transferFrom(ReadableByteChannel src, long position, long count)将字节从给定的可读字节通道传输到此通道的文件中,src是可以读取的字节通道,position仍然是当前通道里的位置,count是要读取的字节数,至于要读取的数据从哪里开始读,这是由可读通道src的当前位置位置决定的。返回的long是从可读通道中实际读取的字节数

写入方法

方法名作用
abstract int write(ByteBuffer src)从给定缓冲区将字节序列写入此通道,也就是将内存缓冲区的数据写入到文件中。返回的int是写入字节的数目
abstract long write(ByteBuffer[] srcs, int offset, int length)从给定缓冲区的子序列将字节序列写入此通道。offset和length针对的是缓冲区数组srcs,offset是缓冲区数组的下标,length是要写入到文件中的缓冲区的数目。返回的long是写入字节数目
final long write(ByteBuffer[] srcs)从给定缓冲区将字节序列写入此通道。调用的是上一个方法,只是传递的offset是0,length是缓冲区数组dsts的长度,即将缓冲区数组中所有缓冲区的数组写入文件中
abstract int write(ByteBuffer src, long position)从给定的文件位置开始,从给定的缓冲区向该通道写入字节序列,给定了文件中要写入数据的位置,从缓冲区读取数据写入文件,从缓冲区读取字节的位置是根据缓冲区内部的位置决定的
abstract long transferTo(long position, long count, WritableByteChannel target)将字节从此通道的文件传输到给定的可写字节通道,position是当前通道里的位置,count是要传输的字节数量, target是目的可写通道,即接收数据的通道,写入该可写通道的位置是根据target当前位置决定的,而不是根据position决定的。返回的long是实际传输的字节数目,可能会小于count。此方法不会修改此通道的位置,其他的普通读写方法都会改变position位置

其他方法

方法名作用
abstract long position()返回此通道的文件位置,这个文件位置是真正的读取和写入文件的位置,读取时从该字节位置开始读取,写入时从该字节位置覆盖写入
abstract FileChannel position(long newPosition)设置此通道的文件位置,返回一个FileChannel文件通道,它有着设置好的文件位置,在该通道上的读取和写入操作都在该位置开始
abstract long size()返回此通道的文件的当前大小,返回的long是字节数目
abstract FileChannel truncate(long size)将此通道的文件截断为给定大小size, 如果给定的大小小于文件的当前大小,则文件将被截断, 丢弃给定大小以外的所有字节。如果给定的大小大于或等于文件的当前大小,则不会修改该文件。
abstract void force(boolean metaData)强制将对此通道文件的任何更新写入包含它的存储设备,即将在内存缓冲区的修改强制写回磁盘,防止断电时丢失更新。metaData参数传递false表示只需要将文件内容的更新写入存储器;传递true表示必须写入对文件内容和元数据的更新

内存映射

文件映射模式

模式名意义
MapMode.READ_ONLY只读映射的模式,任何修改MappedByteBuffer映射缓冲区的尝试都将导致抛出ReadOnlyBufferException异常
MapMode.READ_WRITE读/写映射的模式,对MappedByteBuffer映射缓冲区所做的更改最终将传播到文件中,它们可能对映射相同文件的其他程序可见,也可能不可见,因为每个程序的映射缓冲区MappedByteBuffer都不同
MapMode.PRIVATE专用(写入时复制)映射的模式,对结果缓冲区所做的更改将不会传播到该文件,也不会对映射相同文件的其他程序可见,相反,它们将导致创建缓冲区修改部分的私有副本,即要写入时,先复制共享的文件数据,然后单独修改自己的数据

文件映射方法

方法名作用
abstract MappedByteBuffer map(MapMode mode, long position, long size)将此通道文件的一个区域直接映射到内存中,mode是上面三种映射模式之一,position是要映射到内存中的文件中字节的开始位置,size是要映射到内存中的字节数量

锁方法

方法名作用
abstract FileLock lock(long position, long size, boolean shared)获取此通道文件给定区域的锁,position是要上锁的文件中的字节位置,size是要上锁的字节数量即区域大小,shared是为true,表示上的是共享锁,为false表示上的是独占锁。某些操作系统不支持共享锁,在这种情况下,对共享锁的请求会自动转换为对独占锁的请求,文件锁代表整个Java虚拟机持有。它们不适合控制同一虚拟机内多个线程对文件的访问,因为只有不同的虚拟机才有锁的效果,统一虚拟机多个线程没有锁的效果。此方法的调用将一直阻塞,直到可以锁定区域、关闭此通道或中断调用线程为止
final FileLock lock()获取此通道文件的独占锁,调用上面一个方法,传入的position是0,size是Long的最大值表示锁定整个文件,share为false表示独占锁。此方法的调用将一直阻塞,直到可以锁定区域、关闭此通道或中断调用线程为止
abstract FileLock tryLock(long position, long size, boolean shared)尝试获取此通道文件给定区域的锁,position、size、shared意义和上面一样,区别在于此方法不会阻塞,调用总是立即返回,要么在请求的区域上获得锁,要么未能获得锁,未能获得锁返回null
final FileLock tryLock()尝试获取此通道文件的独占锁,调用上一个方法实现,只不过是锁定整个文件,此方法不会阻塞,调用总是立即返回,要么在请求的区域上获得锁,要么未能获得锁,未能获得锁返回null
Java中,可以使用FileChannel来实现高并发处理。FileChannel提供了一种直接操作文件的方式,可以在多个线程之间共享文件,并实现高效的读写操作。下面是一个示例代码,展示如何使用FileChannel进行高并发处理: ```java import java.io.*; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.file.*; public class FileProcessing { public static void main(String[] args) { String filePath = "path/to/file"; try { // 打开文件通道 FileChannel channel = FileChannel.open(Paths.get(filePath), StandardOpenOption.READ); // 创建多个线程同时读取文件 int threadCount = 5; for (int i = 0; i < threadCount; i++) { Thread thread = new Thread(() -> { try { ByteBuffer buffer = ByteBuffer.allocate(1024); while (channel.read(buffer) != -1) { buffer.flip(); // 切换为读模式 // 处理文件内容 // ... buffer.clear(); // 清空缓冲区,为下一次读取做准备 } } catch (IOException e) { e.printStackTrace(); } }); thread.start(); } // 等待所有线程执行完毕 for (int i = 0; i < threadCount; i++) { Thread.currentThread().join(); } // 关闭文件通道 channel.close(); } catch (IOException | InterruptedException e) { e.printStackTrace(); } } } ``` 在上面的示例中,我们首先打开了一个文件通道。然后,创建了多个线程,每个线程都会读取文件通道中的内容并进行处理。在处理完一段内容后,我们需要调用`buffer.clear()`方法来清空缓冲区,为下一次读取做准备。 请注意,上述代码仅展示了如何使用FileChannel进行高并发处理的基本思路。实际应用中,你可能需要根据具体需求进行适当的调整和优化。 希望这可以帮助到你!如果你还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lolxxs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值