Java IO之FileChannel

本文比较了通过普通输入输出流与FileChannel进行大文件复制的方法,强调了FileChannel在防止内存溢出和提升效率方面的优势,并提供了500M文件复制的示例代码。

概述

对于文件的复制,平时我们都是使用输入输出流进行操作,利用源文件创建出一个输入流,然后利用目标文件创建出一个输出流,最后将输入流的数据读取写入到输出流中。这样也是可以进行操作的。但是利用fileChannel是很有用的一个方式。它能直接连接输入输出流的文件通道,将数据直接写入到目标文件中去。

优势

可防止OOM(内存溢出),高效率(后面详解)

使用

下面以复制500多M的一个本地文件主例。

方法一:使用普通方式

代码如下

    /**
     * 普通的文件复制方法
     *
     * @param fromFile 源文件
     * @param toFile   目标文件
     * @throws FileNotFoundException 未找到文件异常
     */
    public static void fileCopyNormal(File fromFile, File toFile) throws FileNotFoundException {
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            inputStream = new BufferedInputStream(new FileInputStream(fromFile));
            outputStream = new BufferedOutputStream(new FileOutputStream(toFile));
            byte[] bytes = new byte[1024];
            int i;
            //读取到输入流数据,然后写入到输出流中去,实现复制
            while ((i = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, i);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null)
                    inputStream.close();
                if (outputStream != null)
                    outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

测试方法

	public static void main(String[] args) throws FileNotFoundException {
		long start = System.currentTimeMillis();
		File src = new File("F:\\oxygen.zip");
		File dest = new File("F:\\copy_oxygen.zip");
		fileCopyNormal(src,dest);
		long end = System.currentTimeMillis();
		System.out.println("用时:"+(end -start)+" ms");
	}

方式二:使用filechannel进行文件复制

代码如下

	  /**
     * 用filechannel进行文件复制
     *
     * @param fromFile 源文件
     * @param toFile   目标文件
     */
    public static void fileCopyWithFileChannel(File fromFile, File toFile) {
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;
        FileChannel fileChannelInput = null;
        FileChannel fileChannelOutput = null;
        try {
            fileInputStream = new FileInputStream(fromFile);
            fileOutputStream = new FileOutputStream(toFile);
            //得到fileInputStream的文件通道
            fileChannelInput = fileInputStream.getChannel();
            //得到fileOutputStream的文件通道
            fileChannelOutput = fileOutputStream.getChannel();
            //将fileChannelInput通道的数据,写入到fileChannelOutput通道
            fileChannelInput.transferTo(0, fileChannelInput.size(), fileChannelOutput);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fileInputStream != null)
                    fileInputStream.close();
                if (fileChannelInput != null)
                    fileChannelInput.close();
                if (fileOutputStream != null)
                    fileOutputStream.close();
                if (fileChannelOutput != null)
                    fileChannelOutput.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
	public static void main(String[] args) throws FileNotFoundException {
		long start = System.currentTimeMillis();
		File src = new File("F:\\oxygen.zip");
		File dest = new File("F:\\copy_oxygen.zip");
		fileCopyWithFileChannel(src,dest);
		long end = System.currentTimeMillis();
		System.out.println("用时:"+(end -start)+" ms");
	}
Java中`RandomAccessFile`和`FileChannel`可以结合使用,以实现文件的随机读写和高效操作。以下是它们的使用方法: ### 打开FileChannel 无法直接打开一个`FileChannel`,需要通过`RandomAccessFile`来获取一个`FileChannel`实例。示例代码如下: ```java import java.io.RandomAccessFile; import java.nio.channels.FileChannel; public class OpenFileChannelExample { public static void main(String[] args) throws Exception { RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw"); FileChannel inChannel = aFile.getChannel(); } } ``` 这里`getChannel()`方法用于获取与`RandomAccessFile`流关联的唯一`FileChannel` [^2][^4]。 ### 从FileChannel读取数据 在获取`FileChannel`后,可以调用多个`read()`方法之一从`FileChannel`中读取数据。示例代码如下: ```java import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class ReadFromChannelExample { public static void main(String[] args) throws Exception { RandomAccessFile reader = new RandomAccessFile("data/nio-data.txt", "r"); FileChannel channel = reader.getChannel(); ByteBuffer buf = ByteBuffer.allocate(48); int bytesRead = channel.read(buf); } } ``` 上述代码先创建`RandomAccessFile`和`FileChannel`,然后分配一个`ByteBuffer`,最后调用`read()`方法将数据从`FileChannel`读取到`ByteBuffer`中 [^3][^5]。 ### 通过FileChannel写入数据 可以使用`FileChannel`进行文件写入操作。示例代码如下: ```java import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.charset.StandardCharsets; public class WriteToChannelExample { public static void main(String[] args) { String file = "./test.txt"; try (RandomAccessFile writer = new RandomAccessFile(file, "rw"); FileChannel channel = writer.getChannel()) { ByteBuffer buff = ByteBuffer.wrap("Hello world".getBytes(StandardCharsets.UTF_8)); channel.write(buff); } catch (Exception e) { e.printStackTrace(); } } } ``` 这段代码创建一个`RandomAccessFile`和`FileChannel`,将字符串包装成`ByteBuffer`,然后使用`write()`方法将数据写入`FileChannel` [^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值