不同方式复制文件效率的比较
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了不同方式复制文件效率的比较相关的知识,希望对你有一定的参考价值。
文件拷贝
测试复制文件的大小:4.5MB
1 /* 2 3 * BufferedInputStram&BufferedOutputStream 4 5 * 这两个流类为IO提供了带缓冲区的操作,一般打开文件进行写入 6 7 * 或读取操作时,都会加上缓冲,这种流模式提高了IO的性能 8 9 * 10 11 * 从应用程序中把输入放入文件,相当于将一缸水倒入到另一个 12 13 * 缸中: 14 15 * FileOutPutStream----->write()方法相当于一滴一滴的 16 17 * 把水转移过去 18 19 * DataOutputStream----->writeXxx()方法会方便一些,相当于 20 21 * 一瓢一瓢的把水转移过去 22 23 * BufferedOutputStream---write方法更方便,相当于把水一瓢 24 25 * 一瓢先放入桶中,在从桶中倒入得到缸中 26 27 * */ 28 29 30 31 32 33 package Zhang; 34 35 36 37 import java.io.BufferedInputStream; 38 39 import java.io.BufferedOutputStream; 40 41 import java.io.File; 42 43 import java.io.FileInputStream; 44 45 import java.io.FileOutputStream; 46 47 import java.io.IOException; 48 49 50 51 52 53 public class IOUtil { 54 55 /** 56 57 * 读取指定的文件内容,按照十六进制输出到控制台 58 59 * 并且每输出10个byte换行 60 61 * @param fileName 文件名 62 63 * @throws FileNotFoundException 64 65 * */ 66 67 public static void printHex(String fileName) throws Exception{ 68 69 FileInputStream in=new FileInputStream(fileName); 70 71 int b; 72 73 int i=1;//每十个字节换行。 74 75 while((b=in.read())!=-1){ 76 77 if(b<=0xf){ 78 79 //单位十六进制数,前面补0 80 81 System.out.print("0"); 82 83 } 84 85 System.out.print(Integer.toHexString(b)+" "); 86 87 if(i++%10==0){//够十个换行 88 89 System.out.println(); 90 91 } 92 93 } 94 95 in.close(); 96 97 } 98 99 public static void printHexByByteArray(String fileName)throws Exception{ 100 101 FileInputStream in=new FileInputStream(fileName); 102 103 byte[] buf=new byte[10*1024]; //20KB 104 105 106 107 /* 108 109 * 从in中批量读取字节,放入到buf这个字节数组中,从0开始放, 110 111 * 最多放buf.length个,返回的是读取到的字节的个数 112 113 * */ 114 115 /* 116 117 int bytes=in.read(buf,0,buf.length);//一次性读完,说明字节数组足够大 118 119 //bytes是实际读取到的长度 120 121 int j=1; //j的作用在于接下来的输出中每十个进行一次换行 122 123 for(int i=0;i<bytes;i++){ //遍历的时候只能到实际读取的位置处,而不是数组的长度 124 125 if(buf[i]<=0xf) System.out.print("0"); 126 127 System.out.print(Integer.toHexString(buf[i])+" "); 128 129 if(j++%10==0){ 130 131 System.out.println(); 132 133 } 134 135 } 136 137 */ 138 139 //当字节数组不够大,一次性读不完文件时我们该怎么办? 140 141 int bytes=0; 142 143 int j=1; 144 145 while((bytes=in.read(buf,0,buf.length))!=-1){ 146 147 for(int i=0;i<bytes;i++){ 148 149 //byte类型8位。int类型32位,为了避免类型转换错误,通过&0xff将高24位清零 150 151 if(buf[i]<=0xf){ 152 153 System.out.print("0"); 154 155 } 156 157 //if(buf[i]<=0xf) System.out.print("0"); 158 159 System.out.print(Integer.toHexString(buf[i]&0xff)+" "); 160 161 if(j++%10==0){ 162 163 System.out.println(); 164 165 } 166 167 } 168 169 } 170 171 in.close(); 172 173 } 174 175 /** 176 177 * 文件的拷贝 178 179 * */ 180 181 public static void copyFile(File srcFile,File destFile) throws IOException{ 182 183 if(!srcFile.exists()){ 184 185 throw new IllegalArgumentException(srcFile+"文件不存在"); 186 187 } 188 189 if(!srcFile.isFile()){ 190 191 throw new IllegalArgumentException(srcFile+"不是一个文件"); 192 193 } 194 195 FileInputStream in=new FileInputStream(srcFile); 196 197 FileOutputStream out=new FileOutputStream(destFile); 198 199 byte[] buf=new byte[8*1024]; 200 201 int b; 202 203 while((b=in.read(buf,0,buf.length))!=-1){ 204 205 //out.write(buf, 0, buf.length); 206 207 /* 208 209 * 该是写入buf.length个字节还是写入b个字节 210 211 * 写buf.length个字节一定是不恰当的,因为最终读取的时候 212 213 * buf总会出现一次未被写满的情况出现,这样copy的文件明显 214 215 * 不符合要求 216 217 * 218 219 * 在断点调试中发现即使读取的内容已经到文件的末尾没有把buf 220 221 * 数组读满read方法返回的仍是读取到的长度(也就是b)的值 222 223 * 在下次循环的时候会返回-1,也就是说 会用b来控制下次write 224 225 * 方法写入到数组中的长度才是符合要求的 226 227 * 228 229 * 说明文档中对read方法的返回值的描述: 230 231 * 读入缓冲区的字节总数,如果因为已经到达文件末尾而没有 232 233 * 更多的数据,则返回 -1。 234 235 * 236 237 * 请注意:这里说的是如果因为已经到达文件末尾而没有更多的 238 239 * 数据,也就是指当执行read方法的时候是先判断是不是到文件尾, 240 241 * 如果是到文件尾才返回-1,如果不是返回读取的字节数。而不 242 243 * 是指执行read中执行着时遇到文件尾返回-1.仔细体会一下。 244 245 * */ 246 247 out.write(buf,0,b); 248 249 250 251 out.flush(); 252 253 /* 254 255 * 刷新此输出流并强制写出所有缓冲的输出字节。flush 的常规协定是: 256 257 * 如果此输出流的实现已经缓冲了以前写入的任何字节,则调用此方法指 258 259 * 示应将这些字节立即写入它们预期的目标。 260 261 * 262 263 * 如果此流的预期目标是由基础操作系统提供的一个抽象(如一个文件), 264 265 * 则刷新此流只能保证将以前写入到流的字节传递给操作系统进行写入, 266 267 * 但不保证能将这些字节实际写入到物理设备(如磁盘驱动器)。 268 269 * */ 270 271 } 272 273 in.close(); 274 275 out.close(); 276 277 } 278 279 /** 280 281 * 进行文件的拷贝,利用带缓冲的字节流 282 283 * */ 284 285 public static void copyFileByBuffer(File srcFile,File destFile)throws IOException{ 286 287 if(!srcFile.exists()){ 288 289 throw new IllegalArgumentException(srcFile+"文件不存在"); 290 291 } 292 293 if(!srcFile.isFile()){ 294 295 throw new IllegalArgumentException(srcFile+"不是一个文件"); 296 297 } 298 299 300 301 BufferedInputStream bis=new BufferedInputStream( 302 303 new FileInputStream(srcFile)); 304 305 BufferedOutputStream bos=new BufferedOutputStream( 306 307 new FileOutputStream(destFile)); 308 309 int c; 310 311 while((c=bis.read())!=-1){ 312 313 bos.write(c); 314 315 bos.flush();//刷新缓冲区 316 317 } 318 319 bis.close(); 320 321 bos.close(); 322 323 } 324 325 public static void copyByByte(File srcFile,File destFile)throws IOException{ 326 327 if(!srcFile.exists()){ 328 329 throw new IllegalArgumentException(srcFile+"文件不存在"); 330 331 } 332 333 if(!srcFile.isFile()){ 334 335 throw new IllegalArgumentException(srcFile+"不是一个文件"); 336 337 } 338 339 FileInputStream in=new FileInputStream(srcFile); 340 341 FileOutputStream out=new FileOutputStream(destFile); 342 343 int b; 344 345 while((b=in.read())!=-1){ 346 347 out.write(b); 348 349 out.flush();//不是缓冲的话不写flush也是没有问题的。 350 351 } 352 353 in.close(); 354 355 out.close(); 356 357 } 358 359 }
测试
1 package Zhang; 2 3 4 5 import java.io.File; 6 7 import java.io.IOException; 8 9 10 11 12 13 14 15 public class IOUtilTest4 { 16 17 public static void main(String[] args) { 18 19 try { 20 21 long start=System.currentTimeMillis(); 22 23 IOUtil.copyByByte(new File("/home/zhang/Desktop/1.mp3"), new File("/home/zhang/Desktop/2.mp3")); 24 25 long end=System.currentTimeMillis(); 26 27 System.out.println("一个字节一个字节复制完成,用时:"+(end-start)); 28 29 } catch (IOException e) { 30 31 // TODO Auto-generated catch block 32 33 e.printStackTrace(); 34 35 } 36 37 try { 38 39 long start=System.currentTimeMillis(); 40 41 IOUtil.copyFileByBuffer(new File("/home/zhang/Desktop/1.mp3"), new File("/home/zhang/Desktop/3.mp3")); 42 43 long end=System.currentTimeMillis(); 44 45 System.out.println("缓冲复制完成,用时:"+(end-start)); 46 47 } catch (IOException e) { 48 49 // TODO Auto-generated catch block 50 51 e.printStackTrace(); 52 53 } 54 55 try { 56 57 long start=System.currentTimeMillis(); 58 59 IOUtil.copyFile(new File("/home/zhang/Desktop/1.mp3"), new File("/home/zhang/Desktop/4.mp3")); 60 61 long end=System.currentTimeMillis(); 62 63 System.out.println("批量复制完成,用时:"+(end-start)); 64 65 } catch (IOException e) { 66 67 // TODO Auto-generated catch block 68 69 e.printStackTrace(); 70 71 } 72 73 } 74 75 }
输出
一个字节一个字节复制完成,用时:15598
缓冲复制完成,用时:13096
批量复制完成,用时:8
以上是关于不同方式复制文件效率的比较的主要内容,如果未能解决你的问题,请参考以下文章