文件传输的几种方式效率比较
package com.yonge.nio;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.nio.ByteBuffer;import java.nio.channels.FileChannel;/** * 文件传输几种方式比较 * @author wb-gaoy * @version $Id: ChannelTest.java,v 0.1 2012-12-13 下午7:28:40 wb-gaoy Exp $ */public class ChannelTest { public boolean copyFileByIO(File srcFile, File targetDir) throws IOException { FileInputStream fis = new FileInputStream(srcFile); FileOutputStream fos = new FileOutputStream(targetDir + File.separator + srcFile.getName()); byte[] bytes = new byte[1024 * 1024]; int length = -1; while ((length = fis.read(bytes)) != -1) { fos.write(bytes, 0, length); } fis.close(); fos.close(); return true; } public boolean copyFileByNIO(File srcFile, File targetDir) throws IOException { FileInputStream fis = new FileInputStream(srcFile); FileOutputStream fos = new FileOutputStream(targetDir + File.separator + srcFile.getName()); try { FileChannel fisChannel = fis.getChannel(); FileChannel fosChannel = fos.getChannel(); ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 1024); while (fisChannel.read(byteBuffer) != -1) { byteBuffer.flip(); fosChannel.write(byteBuffer); byteBuffer.clear(); } fosChannel.close(); fisChannel.close(); } finally { fis.close(); fos.close(); } return true; } public boolean copyFileByTransfer(File srcFile, File targetDir) throws IOException { FileInputStream fis = new FileInputStream(srcFile); FileOutputStream fos = new FileOutputStream(targetDir + File.separator + srcFile.getName()); try { FileChannel fisChannel = fis.getChannel(); FileChannel fosChannel = fos.getChannel(); fisChannel.transferTo(0, fisChannel.size(), fosChannel); fosChannel.close(); fisChannel.close(); } finally { fis.close(); fos.close(); } return true; } //注意:如果目标文件已经存在或磁盘间的格式不一样(例如源文件磁盘是ntfs,而目标磁盘是fat32),则不会成功 public boolean moveFile(File srcFile, File targetFile) { srcFile.renameTo(new File(targetFile + File.separator + srcFile.getName())); return true; } /** * @param args */ public static void main(String[] args) { final ChannelTest test = new ChannelTest(); final File targetDir = new File("e:/temp"); Thread thread1 = new Thread(new Runnable() { @Override public void run() { try { long start = System.currentTimeMillis(); test.copyFileByIO(new File("e:/ppl20120921145445000611.rar"), targetDir); System.out.println("IO cost:" + (System.currentTimeMillis() - start) + "ms"); } catch (IOException e) { e.printStackTrace(); } } }, "A"); thread1.start(); Thread thread2 = new Thread(new Runnable() { @Override public void run() { try { long start = System.currentTimeMillis(); test.copyFileByNIO(new File("e:/ppl20120921145445000612.rar"), targetDir); System.out.println("NIO cost:" + (System.currentTimeMillis() - start) + "ms"); } catch (IOException e) { e.printStackTrace(); } } }, "B"); thread2.start(); Thread thread3 = new Thread(new Runnable() { @Override public void run() { long start = System.currentTimeMillis(); test.moveFile(new File("e:/ppl20120921145445000613.rar"), targetDir); System.out.println("Move cost:" + (System.currentTimeMillis() - start) + "ms"); } }, "C"); thread3.start(); Thread thread4 = new Thread(new Runnable() { @Override public void run() { long start = System.currentTimeMillis(); try { test.copyFileByTransfer(new File("e:/ppl20120921145445000614.rar"), targetDir); } catch (IOException e) { e.printStackTrace(); } System.out.println("Transfer cost:" + (System.currentTimeMillis() - start) + "ms"); } }, "D"); thread4.start(); }}?上面是四种文件传输方式,测试结果是transfer的效率最低,而网上都说这种效率高,不知道是什么原因,欢迎大家测试一下,说说各自的想法。
1 楼 xiaoZ5919 2012-12-14 我测试了一下。首先我觉得你这样测试有点科学! 不应该用线程来同时进行,即便是测试的是IO,也不能保证分给每个线程的时间片是一样的。我测试了结果如下:文件大小为3.4M
第一次用transferTo 花了235m
再一次IO 花了29ms
我觉得有可能是因为缓存的原因所以又用transferTo试了一次
基本在20ms,又试了一次IO也基本在20ms。
估计是文件比较小,transferTo的优势不明显。
我用netty写过了文件传输的东东,客户端用的transferTo,服务端还是用的buffer + fileoutstream。传输这个3.4m的文件1000次,客户端一次minor gc都没有。然而服务端gc很多 2 楼 yonge812 2012-12-15 xiaoZ5919 写道我测试了一下。首先我觉得你这样测试有点科学! 不应该用线程来同时进行,即便是测试的是IO,也不能保证分给每个线程的时间片是一样的。我测试了结果如下:
文件大小为3.4M
第一次用transferTo 花了235m
再一次IO 花了29ms
我觉得有可能是因为缓存的原因所以又用transferTo试了一次
基本在20ms,又试了一次IO也基本在20ms。
估计是文件比较小,transferTo的优势不明显。
我用netty写过了文件传输的东东,客户端用的transferTo,服务端还是用的buffer + fileoutstream。传输这个3.4m的文件1000次,客户端一次minor gc都没有。然而服务端gc很多
我也对单个方法执行测试了的,确实transferTo是最慢的,文件的大小从几十k到几百M都试过,答案一样的,如果是服务员与客户端通信,可能不一样吧,没试过 3 楼 xiaoZ5919 2012-12-15 yonge812 写道xiaoZ5919 写道我测试了一下。首先我觉得你这样测试有点科学! 不应该用线程来同时进行,即便是测试的是IO,也不能保证分给每个线程的时间片是一样的。我测试了结果如下:
文件大小为3.4M
第一次用transferTo 花了235m
再一次IO 花了29ms
我觉得有可能是因为缓存的原因所以又用transferTo试了一次
基本在20ms,又试了一次IO也基本在20ms。
估计是文件比较小,transferTo的优势不明显。
我用netty写过了文件传输的东东,客户端用的transferTo,服务端还是用的buffer + fileoutstream。传输这个3.4m的文件1000次,客户端一次minor gc都没有。然而服务端gc很多
我也对单个方法执行测试了的,确实transferTo是最慢的,文件的大小从几十k到几百M都试过,答案一样的,如果是服务员与客户端通信,可能不一样吧,没试过
确实是慢! 谢谢你的测试,我猜测transferTo在内核态完成,使用到内存分配是由系统来完成的。而且jvm的内存是事先分配好的。 4 楼 canghailan 2012-12-17 transferTo在传输速度上可能没有什么优势,毕竟到底层都是磁盘IO,但是在资源消耗上(CPU,内存)可能要好。
http://java--hhf.iteye.com/blog/1747507#comments8楼中写了我的一些看法。