經過一組簡單的測試發現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
<code>Eclipse(Juno) JVM(Sun JDK1.</code><code>7</code><code>) 參數:</code>
<code>-Xms1536m</code>
<code>-Xmx1536m</code>
<code>-Xverify:none -XX:+UseParallelGC</code>
<code>-XX:PermSize=128M</code>
<code>-XX:MaxPermSize=128M</code>
<code>OS參數:</code>
<code>Win7 64Bit + 4GB</code>
<code>實體磁盤空間充足</code>
測試代碼
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
<code>import</code> <code>java.io.FileInputStream;</code>
<code>import</code> <code>java.io.FileNotFoundException;</code>
<code>import</code> <code>java.io.FileOutputStream;</code>
<code>import</code> <code>java.io.IOException;</code>
<code>import</code> <code>java.io.RandomAccessFile;</code>
<code>import</code> <code>java.nio.ByteBuffer;</code>
<code>import</code> <code>java.nio.MappedByteBuffer;</code>
<code>import</code> <code>java.nio.channels.FileChannel;</code>
<code>public</code> <code>class</code> <code>FileCopy {</code>
<code> </code><code>private</code> <code>static</code> <code>final</code> <code>int</code> <code>BUFFER_SIZE_1024 = </code><code>1024</code><code>;</code>
<code> </code><code>private</code> <code>static</code> <code>final</code> <code>int</code> <code>BUFFER_SIZE_4096 = </code><code>4096</code><code>;</code>
<code> </code><code>private</code> <code>static</code> <code>final</code> <code>int</code> <code>BUFFER_SIZE_10240 = </code><code>10240</code><code>;</code>
<code> </code>
<code> </code><code>private</code> <code>static</code> <code>final</code> <code>String FROM_FILE_42MB = </code><code>"G:/from_42MB.rar"</code><code>;</code>
<code> </code><code>private</code> <code>static</code> <code>final</code> <code>String FROM_FILE_1GB = </code><code>"G:/from_350MB.rar"</code><code>;</code>
<code> </code><code>private</code> <code>static</code> <code>int</code> <code>BUFFER_SIZE = BUFFER_SIZE_1024;</code>
<code> </code><code>private</code> <code>static</code> <code>String FROM_FILE = FROM_FILE_42MB;</code>
<code> </code><code>/**</code>
<code> </code><code>* @param args</code>
<code> </code><code>* @throws Exception</code>
<code> </code><code>*/</code>
<code> </code><code>public</code> <code>static</code> <code>void</code> <code>main(String[] args) </code><code>throws</code> <code>Exception {</code>
<code> </code><code>System.out.println(</code><code>"File :"</code> <code>+ FROM_FILE + </code><code>" ---- Buffer Size : "</code> <code>+ BUFFER_SIZE + </code><code>"--------------"</code><code>);</code>
<code> </code><code>testFileCopy();</code>
<code> </code>
<code> </code><code>BUFFER_SIZE = BUFFER_SIZE_4096;</code>
<code> </code><code>BUFFER_SIZE = BUFFER_SIZE_10240;</code>
<code> </code><code>BUFFER_SIZE = BUFFER_SIZE_1024;</code>
<code> </code><code>FROM_FILE = FROM_FILE_1GB;</code>
<code> </code><code>}</code>
<code> </code><code>private</code> <code>static</code> <code>void</code> <code>testFileCopy() </code><code>throws</code> <code>FileNotFoundException,</code>
<code> </code><code>IOException {</code>
<code> </code><code>coypByMbb();</code>
<code> </code><code>copyByNioTransferFrom();</code>
<code> </code><code>copyByNioTransferTo();</code>
<code> </code><code>coypByBufferRead();</code>
<code> </code><code>coypByFastBufferRead(); </code>
<code> </code><code>coypByStream();</code><code>//Old IO style</code>
<code> </code><code>* 使用FileChannel.transferFrom()實作</code>
<code> </code><code>* @throws FileNotFoundException</code>
<code> </code><code>* @throws IOException</code>
<code> </code><code>private</code> <code>static</code> <code>void</code> <code>copyByNioTransferFrom() </code><code>throws</code> <code>FileNotFoundException,</code>
<code> </code><code>long</code> <code>startTime = System.currentTimeMillis();</code>
<code> </code><code>RandomAccessFile fromFile = </code><code>new</code> <code>RandomAccessFile(FROM_FILE, </code><code>"rw"</code><code>);</code>
<code> </code><code>FileChannel fromChannel = fromFile.getChannel();</code>
<code> </code><code>RandomAccessFile toFile = </code><code>new</code> <code>RandomAccessFile(</code><code>"G:/to1.rar"</code><code>, </code><code>"rw"</code><code>);</code>
<code> </code><code>FileChannel toChannel = toFile.getChannel();</code>
<code> </code><code>long</code> <code>position = </code><code>0</code><code>;</code>
<code> </code><code>long</code> <code>count = fromChannel.size();</code>
<code> </code><code>toChannel.transferFrom(fromChannel, position, count);</code>
<code> </code><code>long</code> <code>endTime = System.currentTimeMillis();</code>
<code> </code><code>System.out.println(</code><code>"copyByNioTransferFrom time consumed(buffer size no effect) : "</code>
<code> </code><code>+ (endTime - startTime));</code>
<code> </code><code>* 使用FileChannel.transferTo()實作</code>
<code> </code><code>private</code> <code>static</code> <code>void</code> <code>copyByNioTransferTo() </code><code>throws</code> <code>FileNotFoundException,</code>
<code> </code><code>RandomAccessFile toFile = </code><code>new</code> <code>RandomAccessFile(</code><code>"G:/to2.rar"</code><code>, </code><code>"rw"</code><code>);</code>
<code> </code><code>fromChannel.transferTo(position, count, toChannel);</code>
<code> </code><code>System.out.println(</code><code>"copyByNioTransferTo time consumed(buffer size no effect) : "</code>
<code> </code><code>* 使用Channel, Buffer簡單讀寫實作</code>
<code> </code><code>private</code> <code>static</code> <code>void</code> <code>coypByBufferRead() </code><code>throws</code> <code>IOException {</code>
<code> </code><code>FileInputStream fin = </code><code>new</code> <code>FileInputStream(FROM_FILE);</code>
<code> </code><code>FileOutputStream fout = </code><code>new</code> <code>FileOutputStream(</code><code>"G:/to3.rar"</code><code>);</code>
<code> </code><code>FileChannel fcin = fin.getChannel();</code>
<code> </code><code>FileChannel fcout = fout.getChannel();</code>
<code> </code><code>ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);</code>
<code> </code><code>while</code> <code>(</code><code>true</code><code>) {</code>
<code> </code><code>buffer.clear();</code>
<code> </code><code>int</code> <code>r = fcin.read(buffer);</code>
<code> </code><code>if</code> <code>(r == -</code><code>1</code><code>) {</code>
<code> </code><code>break</code><code>;</code>
<code> </code><code>}</code>
<code> </code><code>buffer.flip();</code>
<code> </code><code>fcout.write(buffer);</code>
<code> </code><code>}</code>
<code> </code><code>System.out.println(</code><code>"coypByBufferRead time consumed(buffer size take effect) : "</code>
<code> </code><code>* 使用連續記憶體的Buffer實作</code>
<code> </code><code>private</code> <code>static</code> <code>void</code> <code>coypByFastBufferRead() </code><code>throws</code> <code>IOException {</code>
<code> </code><code>FileOutputStream fout = </code><code>new</code> <code>FileOutputStream(</code><code>"G:/to4.rar"</code><code>);</code>
<code> </code><code>ByteBuffer buffer = ByteBuffer.allocateDirect(BUFFER_SIZE);</code>
<code> </code><code>System.out.println(</code><code>"coypByFastBufferRead time consumed(buffer size take effect) : "</code>
<code> </code><code>* 使用檔案記憶體映射實作</code>
<code> </code><code>private</code> <code>static</code> <code>void</code> <code>coypByMbb() </code><code>throws</code> <code>IOException {</code>
<code> </code><code>RandomAccessFile fout = </code><code>new</code> <code>RandomAccessFile(</code><code>"G:/to5.rar"</code><code>, </code><code>"rw"</code><code>);</code>
<code> </code><code>MappedByteBuffer mbbi = fcin.map(FileChannel.MapMode.READ_ONLY, </code><code>0</code><code>,</code>
<code> </code><code>fcin.size());</code>
<code> </code><code>MappedByteBuffer mbbo = fcout.map(FileChannel.MapMode.READ_WRITE, </code><code>0</code><code>,</code>
<code> </code><code>mbbo.put(mbbi);</code>
<code> </code><code>mbbi.clear();</code>
<code> </code><code>mbbo.clear();</code>
<code> </code><code>System.out</code>
<code> </code><code>.println(</code><code>"coypByMbb time consumed(buffer size no effect) : "</code> <code>+ (endTime - startTime));</code>
<code> </code><code>* 使用傳統IO的流讀寫方式實作</code>
<code> </code><code>private</code> <code>static</code> <code>void</code> <code>coypByStream() </code><code>throws</code> <code>IOException {</code>
<code> </code><code>FileOutputStream fout = </code><code>new</code> <code>FileOutputStream(</code><code>"G:/to6.rar"</code><code>);</code>
<code> </code><code>byte</code><code>[] buffer = </code><code>new</code> <code>byte</code><code>[BUFFER_SIZE];</code>
<code> </code><code>int</code> <code>ins = fin.read(buffer);</code>
<code> </code><code>if</code> <code>(ins == -</code><code>1</code><code>) {</code>
<code> </code><code>fin.close();</code>
<code> </code><code>fout.flush();</code>
<code> </code><code>fout.close();</code>
<code> </code><code>} </code><code>else</code><code>{</code>
<code> </code><code>fout.write(buffer, </code><code>0</code><code>, ins);</code>
<code> </code><code>} </code>
<code> </code><code>System.out.println(</code><code>"coypByStream time consumed(buffer size take effect) : "</code> <code>+ (endTime - startTime));</code>
<code>}</code>
測試結果
<code>File :G:/from_42MB.rar ---- Buffer Size : </code><code>1024</code><code>--------------</code>
<code>coypByMbb time consumed(buffer size no effect) : </code><code>47</code>
<code>copyByNioTransferFrom time consumed(buffer size no effect) : </code><code>62</code>
<code>copyByNioTransferTo time consumed(buffer size no effect) : </code><code>47</code>
<code>coypByBufferRead time consumed(buffer size take effect) : </code><code>249</code>
<code>coypByFastBufferRead time consumed(buffer size take effect) : </code><code>188</code>
<code>coypByStream time consumed(buffer size take effect) : </code><code>187</code>
<code> </code>
<code>File :G:/from_42MB.rar ---- Buffer Size : </code><code>4096</code><code>--------------</code>
<code>coypByMbb time consumed(buffer size no effect) : </code><code>15</code>
<code>copyByNioTransferFrom time consumed(buffer size no effect) : </code><code>16</code>
<code>copyByNioTransferTo time consumed(buffer size no effect) : </code><code>31</code>
<code>coypByBufferRead time consumed(buffer size take effect) : </code><code>125</code>
<code>coypByFastBufferRead time consumed(buffer size take effect) : </code><code>79</code>
<code>coypByStream time consumed(buffer size take effect) : </code><code>93</code>
<code>File :G:/from_42MB.rar ---- Buffer Size : </code><code>10240</code><code>--------------</code>
<code>coypByMbb time consumed(buffer size no effect) : </code><code>16</code>
<code>copyByNioTransferFrom time consumed(buffer size no effect) : </code><code>32</code>
<code>coypByBufferRead time consumed(buffer size take effect) : </code><code>78</code>
<code>coypByFastBufferRead time consumed(buffer size take effect) : </code><code>62</code>
<code>coypByStream time consumed(buffer size take effect) : </code><code>63</code>
<code>File :G:/from_350MB.rar ---- Buffer Size : </code><code>1024</code><code>--------------</code>
<code>coypByMbb time consumed(buffer size no effect) : </code><code>280</code>
<code>copyByNioTransferFrom time consumed(buffer size no effect) : </code><code>453</code>
<code>copyByNioTransferTo time consumed(buffer size no effect) : </code><code>7785</code>
<code>coypByBufferRead time consumed(buffer size take effect) : </code><code>8144</code>
<code>coypByFastBufferRead time consumed(buffer size take effect) : </code><code>7068</code>
<code>coypByStream time consumed(buffer size take effect) : </code><code>8503</code>
<code>File :G:/from_350MB.rar ---- Buffer Size : </code><code>4096</code><code>--------------</code>
<code>coypByMbb time consumed(buffer size no effect) : </code><code>1904</code>
<code>copyByNioTransferFrom time consumed(buffer size no effect) : </code><code>5978</code>
<code>copyByNioTransferTo time consumed(buffer size no effect) : </code><code>7379</code>
<code>coypByBufferRead time consumed(buffer size take effect) : </code><code>7621</code>
<code>coypByFastBufferRead time consumed(buffer size take effect) : </code><code>7474</code>
<code>coypByStream time consumed(buffer size take effect) : </code><code>8200</code>
<code>File :G:/from_350MB.rar ---- Buffer Size : </code><code>10240</code><code>--------------</code>
<code>coypByMbb time consumed(buffer size no effect) : </code><code>328</code>
<code>copyByNioTransferFrom time consumed(buffer size no effect) : </code><code>6864</code>
<code>copyByNioTransferTo time consumed(buffer size no effect) : </code><code>7021</code>
<code>coypByBufferRead time consumed(buffer size take effect) : </code><code>7199</code>
<code>coypByFastBufferRead time consumed(buffer size take effect) : </code><code>7941</code>
<code>coypByStream time consumed(buffer size take effect) : </code><code>7801</code>
<code></code>
本文轉自sarchitect 51CTO部落格,原文連結:http://blog.51cto.com/stevex/1272956,如需轉載請自行聯系原作者