FileChannel的使用

⚠️ FileChannel 工作模式

FileChannel 只能工作在阻塞模式下

获取

不能直接打开 FileChannel,必须通过 FileInputStream、FileOutputStream 或者 RandomAccessFile 来获取 FileChannel,它们都有 getChannel 方法

  • 通过 FileInputStream 获取的 channel 只能读

  • 通过 FileOutputStream 获取的 channel 只能写

  • 通过 RandomAccessFile 是否能读写根据构造 RandomAccessFile 时的读写模式决定

读取

会从 channel 读取数据填充 ByteBuffer,返回值表示读到了多少字节,-1 表示到达了文件的末尾

int readBytes = channel.read(buffer);

写入

写入的正确姿势如下, SocketChannel

ByteBuffer buffer = ...;
buffer.put(...); // 存入数据
buffer.flip();   // 切换读模式
​
while(buffer.hasRemaining()) {
    channel.write(buffer);
}

在 while 中调用 channel.write 是因为 write 方法并不能保证一次将 buffer 中的内容全部写入 channel

关闭

channel 必须关闭,不过调用了 FileInputStream、FileOutputStream 或者 RandomAccessFile 的 close 方法会间接地调用 channel 的 close 方法

位置

获取当前位置

long pos = channel.position();

设置当前位置

long newPos = ...;
channel.position(newPos);

设置当前位置时,如果设置为文件的末尾

  • 这时读取会返回 -1

  • 这时写入,会追加内容,但要注意如果 position 超过了文件末尾,再写入时在新内容和原末尾之间会有空洞(00)

大小

使用 size 方法获取文件的大小

强制写入

操作系统出于性能的考虑,会将数据缓存,不是立刻写入磁盘。可以调用 force(true) 方法将文件内容和元数据(文件的权限等信息)立刻写入磁盘

两个Channel传输数据

package com.aqiuo.channel;
​
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
​
public class TestChannel {
    public static void main(String[] args) throws IOException {
        try(FileChannel from=new FileInputStream("from.txt").getChannel();
            FileChannel to = new FileOutputStream("to.txt").getChannel();
        ) {
            long size = from.size();
            long l = from.transferTo(0, size, to);
​
        }
    }
}

超过 2g 大小的文件传输

public class TestFileChannelTransferTo {
    public static void main(String[] args) {
        try (
                FileChannel from = new FileInputStream("data.txt").getChannel();
                FileChannel to = new FileOutputStream("to.txt").getChannel();
        ) {
            // 效率高,底层会利用操作系统的零拷贝进行优化
            long size = from.size();
            // left 变量代表还剩余多少字节
            for (long left = size; left > 0; ) {
                System.out.println("position:" + (size - left) + " left:" + left);
                left -= from.transferTo((size - left), left, to);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

当内存超过两G,就会导致一次性传输失败,需要多传几次,就可以采用上述方法。

3.3 Path

JDK7引入了Path和paths类。

  • Path用来表示文件路径。

  • Paths是工具类,用来获取Path实例。

Path source=Paths.get("1.txt"); //相对路径
Path source=Paths.get("d:/1.txt") //绝对路径
Path source=Paths.get("d:\\data","project");
  • .代表当前路径

  • ..代表当前路径

相关推荐

  1. FileChannel使用

    2024-06-17 12:42:03       7 阅读
  2. 5.FileChannel

    2024-06-17 12:42:03       13 阅读
  3. git使用

    2024-06-17 12:42:03       46 阅读
  4. websoket 使用

    2024-06-17 12:42:03       36 阅读
  5. Logstash使用方法

    2024-06-17 12:42:03       43 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-17 12:42:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-17 12:42:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-17 12:42:03       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-17 12:42:03       20 阅读

热门阅读

  1. 网络协议五

    2024-06-17 12:42:03       5 阅读
  2. 数组模拟栈和队列

    2024-06-17 12:42:03       7 阅读
  3. 编程后端:深入探索其所属的行业领域

    2024-06-17 12:42:03       7 阅读
  4. 基于对抗神经网络的图像生成

    2024-06-17 12:42:03       8 阅读
  5. 深入Linux Core文件生成与自定义命名规则

    2024-06-17 12:42:03       10 阅读
  6. Rocky Linux安装Docker

    2024-06-17 12:42:03       10 阅读
  7. react中组件的生命周期

    2024-06-17 12:42:03       8 阅读
  8. 头歌初识redis答案

    2024-06-17 12:42:03       9 阅读
  9. 解决Oracle死锁问题

    2024-06-17 12:42:03       7 阅读
  10. 简单的Scikit-Learn入门示例

    2024-06-17 12:42:03       9 阅读