Java实现文件拷贝

简介:

经过一组简单的测试发现JAVA NIO提供的文件内存映射方法实现文件拷贝速度最快,不管是大文件还是小文件,特别是大文件的拷贝速度比普通方法提高20倍,唯一有个前提就是内存需要足够大,否则文件映射肯定失败(当然可以通过分割文件,部分映射的方法避免,但就比较麻烦了);其次NIO提供的文件管道传输速度也比较好,如果没法做文件内存映射,推荐这种拷贝方法;另外,Buffer的大小,对于读写速度还是有影响的,基本就是Buffer越大读写越快(有个疑问就是Buffer.allocateDirec()效率提高不明显);最后,总体看来NIO的效率比老IO高,不管使用哪种方式,老IO使用流读写只能一个字节一个字节的抠,NIO使用块的方式读写还是相对比较快,所以没有特别需求的情况下,推荐使用NIO,目前NIO基本能覆盖老IO的所有功能(当然NIO还提供N多新功能)。


  • 测试环境

1
2
3
4
5
6
7
8
9
Eclipse(Juno) JVM(Sun JDK1. 7 ) 参数:
-Xms1536m
-Xmx1536m
-Xverify:none -XX:+UseParallelGC
-XX:PermSize=128M
-XX:MaxPermSize=128M
OS参数:
Win7 64Bit + 4GB
物理磁盘空间充足


  • 测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
import  java.io.FileInputStream;
import  java.io.FileNotFoundException;
import  java.io.FileOutputStream;
import  java.io.IOException;
import  java.io.RandomAccessFile;
import  java.nio.ByteBuffer;
import  java.nio.MappedByteBuffer;
import  java.nio.channels.FileChannel;
public  class  FileCopy {
     private  static  final  int  BUFFER_SIZE_1024 =  1024 ;
     private  static  final  int  BUFFER_SIZE_4096 =  4096 ;
     private  static  final  int  BUFFER_SIZE_10240 =  10240 ;
        
     private  static  final  String FROM_FILE_42MB =  "G:/from_42MB.rar" ;
     private  static  final  String FROM_FILE_1GB =  "G:/from_350MB.rar" ;
        
     private  static  int  BUFFER_SIZE = BUFFER_SIZE_1024;
     private  static  String FROM_FILE = FROM_FILE_42MB;
     /**
      * @param args
      * @throws Exception
      */
     public  static  void  main(String[] args)  throws  Exception {
         System.out.println( "File :"  + FROM_FILE +  " ---- Buffer Size : "  + BUFFER_SIZE +  "--------------" );
         testFileCopy();
            
         BUFFER_SIZE = BUFFER_SIZE_4096;
         System.out.println( "File :"  + FROM_FILE +  " ---- Buffer Size : "  + BUFFER_SIZE +  "--------------" );
         testFileCopy();
            
         BUFFER_SIZE = BUFFER_SIZE_10240;
         System.out.println( "File :"  + FROM_FILE +  " ---- Buffer Size : "  + BUFFER_SIZE +  "--------------" );
         testFileCopy();
            
         BUFFER_SIZE = BUFFER_SIZE_1024;
         FROM_FILE = FROM_FILE_1GB;
         System.out.println( "File :"  + FROM_FILE +  " ---- Buffer Size : "  + BUFFER_SIZE +  "--------------" );
         testFileCopy();
            
         BUFFER_SIZE = BUFFER_SIZE_4096;
         FROM_FILE = FROM_FILE_1GB;
         System.out.println( "File :"  + FROM_FILE +  " ---- Buffer Size : "  + BUFFER_SIZE +  "--------------" );
         testFileCopy();
            
         BUFFER_SIZE = BUFFER_SIZE_10240;
         FROM_FILE = FROM_FILE_1GB;
         System.out.println( "File :"  + FROM_FILE +  " ---- Buffer Size : "  + BUFFER_SIZE +  "--------------" );
         testFileCopy();
            
     }
     private  static  void  testFileCopy()  throws  FileNotFoundException,
             IOException {
         coypByMbb();
         copyByNioTransferFrom();
         copyByNioTransferTo();
         coypByBufferRead();
         coypByFastBufferRead();           
         coypByStream(); //Old IO style
     }
     /**
      * 使用FileChannel.transferFrom()实现
      * @throws FileNotFoundException
      * @throws IOException
      */
     private  static  void  copyByNioTransferFrom()  throws  FileNotFoundException,
             IOException {
         long  startTime = System.currentTimeMillis();
         RandomAccessFile fromFile =  new  RandomAccessFile(FROM_FILE,  "rw" );
         FileChannel fromChannel = fromFile.getChannel();
         RandomAccessFile toFile =  new  RandomAccessFile( "G:/to1.rar" "rw" );
         FileChannel toChannel = toFile.getChannel();
         long  position =  0 ;
         long  count = fromChannel.size();
         toChannel.transferFrom(fromChannel, position, count);
         long  endTime = System.currentTimeMillis();
         System.out.println( "copyByNioTransferFrom time consumed(buffer size no effect) : "
                 + (endTime - startTime));
     }
     /**
      * 使用FileChannel.transferTo()实现
      * @throws FileNotFoundException
      * @throws IOException
      */
     private  static  void  copyByNioTransferTo()  throws  FileNotFoundException,
             IOException {
         long  startTime = System.currentTimeMillis();
         RandomAccessFile fromFile =  new  RandomAccessFile(FROM_FILE,  "rw" );
         FileChannel fromChannel = fromFile.getChannel();
         RandomAccessFile toFile =  new  RandomAccessFile( "G:/to2.rar" "rw" );
         FileChannel toChannel = toFile.getChannel();
         long  position =  0 ;
         long  count = fromChannel.size();
         fromChannel.transferTo(position, count, toChannel);
         long  endTime = System.currentTimeMillis();
         System.out.println( "copyByNioTransferTo time consumed(buffer size no effect) : "
                 + (endTime - startTime));
     }
     /**
      * 使用Channel, Buffer简单读写实现
      * @throws IOException
      */
     private  static  void  coypByBufferRead()  throws  IOException {
         long  startTime = System.currentTimeMillis();
         FileInputStream fin =  new  FileInputStream(FROM_FILE);
         FileOutputStream fout =  new  FileOutputStream( "G:/to3.rar" );
         FileChannel fcin = fin.getChannel();
         FileChannel fcout = fout.getChannel();
         ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
         while  ( true ) {
             buffer.clear();
             int  r = fcin.read(buffer);
             if  (r == - 1 ) {
                 break ;
             }
             buffer.flip();
             fcout.write(buffer);
         }
         long  endTime = System.currentTimeMillis();
         System.out.println( "coypByBufferRead time consumed(buffer size take effect) : "
                 + (endTime - startTime));
     }
     /**
      * 使用连续内存的Buffer实现
      * @throws IOException
      */
     private  static  void  coypByFastBufferRead()  throws  IOException {
         long  startTime = System.currentTimeMillis();
         FileInputStream fin =  new  FileInputStream(FROM_FILE);
         FileOutputStream fout =  new  FileOutputStream( "G:/to4.rar" );
         FileChannel fcin = fin.getChannel();
         FileChannel fcout = fout.getChannel();
         ByteBuffer buffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
         while  ( true ) {
             buffer.clear();
             int  r = fcin.read(buffer);
             if  (r == - 1 ) {
                 break ;
             }
             buffer.flip();
             fcout.write(buffer);
         }
         long  endTime = System.currentTimeMillis();
         System.out.println( "coypByFastBufferRead time consumed(buffer size take effect) : "
                 + (endTime - startTime));
     }
     /**
      * 使用文件内存映射实现
      * @throws IOException
      */
     private  static  void  coypByMbb()  throws  IOException {
         long  startTime = System.currentTimeMillis();
         FileInputStream fin =  new  FileInputStream(FROM_FILE);
         RandomAccessFile fout =  new  RandomAccessFile( "G:/to5.rar" "rw" );
         FileChannel fcin = fin.getChannel();
         FileChannel fcout = fout.getChannel();
         MappedByteBuffer mbbi = fcin.map(FileChannel.MapMode.READ_ONLY,  0 ,
                 fcin.size());
         MappedByteBuffer mbbo = fcout.map(FileChannel.MapMode.READ_WRITE,  0 ,
                 fcin.size());
         mbbo.put(mbbi);
         mbbi.clear();
         mbbo.clear();
         long  endTime = System.currentTimeMillis();
         System.out
                 .println( "coypByMbb time consumed(buffer size no effect) : "  + (endTime - startTime));
     }
     /**
      * 使用传统IO的流读写方式实现
      * @throws IOException
      */
     private  static  void  coypByStream()  throws  IOException {
         long  startTime = System.currentTimeMillis();
         FileInputStream fin =  new  FileInputStream(FROM_FILE);
         FileOutputStream fout =  new  FileOutputStream( "G:/to6.rar" );
         byte [] buffer =  new  byte [BUFFER_SIZE];
         while  ( true ) {
             int  ins = fin.read(buffer);
             if  (ins == - 1 ) {
                 fin.close();
                 fout.flush();
                 fout.close();
                 break ;
             else {
                 fout.write(buffer,  0 , ins);
             }             
         }
         long  endTime = System.currentTimeMillis();
         System.out.println( "coypByStream time consumed(buffer size take effect) : "  + (endTime - startTime));
     }
}
  • 测试结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    File :G:/from_42MB.rar ---- Buffer Size :  1024 --------------
    coypByMbb time consumed(buffer size no effect) :  47
    copyByNioTransferFrom time consumed(buffer size no effect) :  62
    copyByNioTransferTo time consumed(buffer size no effect) :  47
    coypByBufferRead time consumed(buffer size take effect) :  249
    coypByFastBufferRead time consumed(buffer size take effect) :  188
    coypByStream time consumed(buffer size take effect) :  187
              
    File :G:/from_42MB.rar ---- Buffer Size :  4096 --------------
    coypByMbb time consumed(buffer size no effect) :  15
    copyByNioTransferFrom time consumed(buffer size no effect) :  16
    copyByNioTransferTo time consumed(buffer size no effect) :  31
    coypByBufferRead time consumed(buffer size take effect) :  125
    coypByFastBufferRead time consumed(buffer size take effect) :  79
    coypByStream time consumed(buffer size take effect) :  93
              
    File :G:/from_42MB.rar ---- Buffer Size :  10240 --------------
    coypByMbb time consumed(buffer size no effect) :  16
    copyByNioTransferFrom time consumed(buffer size no effect) :  32
    copyByNioTransferTo time consumed(buffer size no effect) :  31
    coypByBufferRead time consumed(buffer size take effect) :  78
    coypByFastBufferRead time consumed(buffer size take effect) :  62
    coypByStream time consumed(buffer size take effect) :  63
              
    File :G:/from_350MB.rar ---- Buffer Size :  1024 --------------
    coypByMbb time consumed(buffer size no effect) :  280
    copyByNioTransferFrom time consumed(buffer size no effect) :  453
    copyByNioTransferTo time consumed(buffer size no effect) :  7785
    coypByBufferRead time consumed(buffer size take effect) :  8144
    coypByFastBufferRead time consumed(buffer size take effect) :  7068
    coypByStream time consumed(buffer size take effect) :  8503
              
    File :G:/from_350MB.rar ---- Buffer Size :  4096 --------------
    coypByMbb time consumed(buffer size no effect) :  1904
    copyByNioTransferFrom time consumed(buffer size no effect) :  5978
    copyByNioTransferTo time consumed(buffer size no effect) :  7379
    coypByBufferRead time consumed(buffer size take effect) :  7621
    coypByFastBufferRead time consumed(buffer size take effect) :  7474
    coypByStream time consumed(buffer size take effect) :  8200
              
    File :G:/from_350MB.rar ---- Buffer Size :  10240 --------------
    coypByMbb time consumed(buffer size no effect) :  328
    copyByNioTransferFrom time consumed(buffer size no effect) :  6864
    copyByNioTransferTo time consumed(buffer size no effect) :  7021
    coypByBufferRead time consumed(buffer size take effect) :  7199
    coypByFastBufferRead time consumed(buffer size take effect) :  7941
    coypByStream time consumed(buffer size take effect) :  7801



     本文转自sarchitect 51CTO博客,原文链接:http://blog.51cto.com/stevex/1272956,如需转载请自行联系原作者




相关文章
|
23天前
|
Java Apache 开发工具
【Azure 事件中心】 org.slf4j.Logger 收集 Event Hub SDK(Java) 输出日志并以文件形式保存
【Azure 事件中心】 org.slf4j.Logger 收集 Event Hub SDK(Java) 输出日志并以文件形式保存
|
13天前
|
Arthas Java 测试技术
Java字节码文件、组成,jclasslib插件、阿里arthas工具,Java注解
Java字节码文件、组成、详解、分析;常用工具,jclasslib插件、阿里arthas工具;如何定位线上问题;Java注解
Java字节码文件、组成,jclasslib插件、阿里arthas工具,Java注解
|
11天前
|
Java API 开发者
【Java字节码操控新篇章】JDK 22类文件API预览:解锁Java底层的无限可能!
【9月更文挑战第6天】JDK 22的类文件API为Java开发者们打开了一扇通往Java底层世界的大门。通过这个API,我们可以更加深入地理解Java程序的工作原理,实现更加灵活和强大的功能。虽然目前它还处于预览版阶段,但我们已经可以预见其在未来Java开发中的重要地位。让我们共同期待Java字节码操控新篇章的到来!
|
27天前
|
Java
Java系列之 重命名文件/图片,renameTo() 方法的使用
这篇文章介绍了Java中File类的renameTo()方法,包括其使用方式、参数、返回值以及一些使用时的注意事项,并通过示例代码演示了如何使用该方法来重命名文件。
Java系列之 重命名文件/图片,renameTo() 方法的使用
|
9天前
|
Java API 开发者
【Java字节码的掌控者】JDK 22类文件API:解锁Java深层次的奥秘,赋能开发者无限可能!
【9月更文挑战第8天】JDK 22类文件API的引入,为Java开发者们打开了一扇通往Java字节码操控新世界的大门。通过这个API,我们可以更加深入地理解Java程序的底层行为,实现更加高效、可靠和创新的Java应用。虽然目前它还处于预览版阶段,但我们已经可以预见其在未来Java开发中的重要地位。让我们共同期待Java字节码操控新篇章的到来,并积极探索类文件API带来的无限可能!
|
10天前
|
算法 Java
Java 压缩文件
在Java中压缩文件是一个常见的需求,通常可以通过使用Java自带的`java.util.zip`包来实现。这个包提供了`ZipOutputStream`类来创建ZIP格式的压缩文件。以下是一个简单的示例,展示了如何将多个文件压缩到一个ZIP文件中。 ### 示例:将多个文件压缩到一个ZIP文件中 ```java import java.io.*; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class ZipFilesExample { public static vo
|
1月前
|
Java
java网络编程 UDP通信协议实现局域网内文件的发送和接收
java网络编程 UDP通信协议实现局域网内文件的发送和接收
java网络编程 UDP通信协议实现局域网内文件的发送和接收
|
22天前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之配置Logback以仅记录错误级别的日志到一个滚动文件中的问题如何解决
Java应用结构规范问题之配置Logback以仅记录错误级别的日志到一个滚动文件中的问题如何解决
|
22天前
|
Java 程序员
Java系统中的错误码设计问题之实现一个基于properties文件的错误消息管理系统如何解决
Java系统中的错误码设计问题之实现一个基于properties文件的错误消息管理系统如何解决
12 1
|
28天前
|
Java
【Java基础面试二】、个Java文件里可以有多个类吗(不含内部类)?
这篇文章讨论了Java文件中类的定义规则,指出一个Java文件可以包含多个类(不包含内部类),但其中最多只能有一个public类,且如果有public类,它的名称必须与文件名一致。