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,如需转载请自行联系原作者




相关文章
|
4天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
16 2
|
1月前
|
Java
Java“解析时到达文件末尾”解决
在Java编程中,“解析时到达文件末尾”通常指在读取或处理文件时提前遇到了文件结尾,导致程序无法继续读取所需数据。解决方法包括:确保文件路径正确,检查文件是否完整,使用正确的文件读取模式(如文本或二进制),以及确保读取位置正确。合理设置缓冲区大小和循环条件也能避免此类问题。
|
1月前
|
Java
利用GraalVM将java文件变成exe可执行文件
这篇文章简明地介绍了如何使用GraalVM将一个简单的Java程序编译成exe可执行文件,首先通过javac命令编译Java文件生成class文件,然后使用native-image命令将class文件转换成独立的exe文件,并展示了如何运行这个exe文件。
61 0
利用GraalVM将java文件变成exe可执行文件
|
8天前
|
存储 缓存 安全
在 Java 编程中,创建临时文件用于存储临时数据或进行临时操作非常常见
在 Java 编程中,创建临时文件用于存储临时数据或进行临时操作非常常见。本文介绍了使用 `File.createTempFile` 方法和自定义创建临时文件的两种方式,详细探讨了它们的使用场景和注意事项,包括数据缓存、文件上传下载和日志记录等。强调了清理临时文件、确保文件名唯一性和合理设置文件权限的重要性。
20 2
|
17天前
|
存储 安全 Java
如何保证 Java 类文件的安全性?
Java类文件的安全性可以通过多种方式保障,如使用数字签名验证类文件的完整性和来源,利用安全管理器和安全策略限制类文件的权限,以及通过加密技术保护类文件在传输过程中的安全。
|
18天前
|
存储 Java API
Java实现导出多个excel表打包到zip文件中,供客户端另存为窗口下载
Java实现导出多个excel表打包到zip文件中,供客户端另存为窗口下载
25 4
|
21天前
|
Java 数据格式 索引
使用 Java 字节码工具检查类文件完整性的原理是什么
Java字节码工具通过解析和分析类文件的字节码,检查其结构和内容是否符合Java虚拟机规范,确保类文件的完整性和合法性,防止恶意代码或损坏的类文件影响程序运行。
|
21天前
|
Java API Maven
如何使用 Java 字节码工具检查类文件的完整性
本文介绍如何利用Java字节码工具来检测类文件的完整性和有效性,确保类文件未被篡改或损坏,适用于开发和维护阶段的代码质量控制。
|
1月前
|
Java
用java搞定时任务,将hashmap里面的值存到文件里面去
本文介绍了如何使用Java的`Timer`和`TimerTask`类创建一个定时任务,将HashMap中的键值对写入到文本文件中,并提供了完整的示例代码。
36 1
用java搞定时任务,将hashmap里面的值存到文件里面去
|
30天前
|
Java
Java开发如何实现文件的移动,但是在移动结束后才进行读取?
【10月更文挑战第13天】Java开发如何实现文件的移动,但是在移动结束后才进行读取?
54 2