JavaIO 使用缓冲字节流和文件字节流拷贝文件

系统管理员 2022-05-25 11:39 386阅读 0赞

文件字节流复制文件的原理是:读取一个个字节(或者字节数组),然后再写入文件中去。

缓冲字节流复制文件的原理是:读取一个个字节(或者字节数组)放到缓冲字节数组中,等到缓冲字节数组读满后,再把这几次读取到的字节一并写到文件中去。这样使用缓冲字节流,就能少写几次文件,进而节省时间

测试代码:

(1)批量读取比较:

  1. public class TestBuffered_File
  2. {
  3. public static void copyFileBufferd(File srcFile,File destFile,int bufsize) throws IOException
  4. {
  5. if(!srcFile.exists())
  6. {
  7. throw new FileNotFoundException("文件"+srcFile+"不存在");
  8. }
  9. if(!srcFile.isFile())
  10. {
  11. throw new IllegalArgumentException(srcFile+"不是文件");
  12. }
  13. //创建缓冲字节流对象,内部缓冲设置为bufSize
  14. BufferedInputStream in=new BufferedInputStream(
  15. new FileInputStream(srcFile),bufsize);
  16. BufferedOutputStream out=new BufferedOutputStream(
  17. new FileOutputStream(destFile),bufsize);
  18. int size=0;
  19. byte[] buffer=new byte[512];
  20. //读到字节串到内部缓存,默认缓冲区的大小是8192字节
  21. while((size=in.read(buffer))!=-1)
  22. {
  23. out.write(buffer,0,size);//把读取到的字节串写入到缓冲区,缓冲区写满会自动写入文件
  24. // out.flush();//刷新缓冲区写入文件
  25. }
  26. out.flush();//刷新缓冲区写入文件
  27. in.close();
  28. out.close();
  29. }
  30. /**
  31. * 使用FileInputStream和FileOutputStream 按字节数组拷贝文件
  32. * @param srcFile 源文件File对象
  33. * @param targetFile 目标文件File对象
  34. * @throws IOException
  35. */
  36. public static void copyFileByBytes(File srcFile,File targetFile) throws IOException
  37. {
  38. if(!srcFile.exists())
  39. {
  40. throw new IllegalArgumentException( srcFile+"文件不存在");
  41. }
  42. if(!srcFile.isFile())
  43. {
  44. throw new IllegalArgumentException( srcFile+"不是文件");
  45. }
  46. FileInputStream in=new FileInputStream(srcFile);
  47. FileOutputStream out=new FileOutputStream(targetFile);
  48. byte[] buf=new byte[512];
  49. int size=0;
  50. while((size=in.read(buf, 0, buf.length))!=-1)
  51. {
  52. out.write(buf, 0, size);
  53. out.flush();//刷新写入文件中去。
  54. }
  55. in.close();
  56. out.close();
  57. }
  58. /**
  59. * 把时间戳(long 毫秒数)转换为格式化时间字符串
  60. * @param timeStamp long毫秒数
  61. * @return 格式化时间字符串
  62. */
  63. public static String timeStampToDateString(long timeStamp)
  64. {
  65. Date date = new Date(timeStamp);
  66. /*
  67. m 小时中的分钟数
  68. s 分钟中的秒数
  69. S 毫秒数
  70. */
  71. DateFormat format = new SimpleDateFormat("mm:ss:SS");
  72. String dateString=format.format(date);
  73. return dateString;
  74. }
  75. public static void main(String[] args)
  76. {
  77. String packagePath;
  78. try
  79. {
  80. //使用缓冲字节流拷贝文件
  81. long start=System.currentTimeMillis();//获取当前的时间戳
  82. packagePath = FilePath.getSrcPackagePath(TestBufferedCopy.class);
  83. copyFileBufferd(new File(packagePath+"李玉刚_刚好遇见你.mp3"),
  84. new File(packagePath+"李玉刚_刚好遇见你副本4.mp3"),1024*10);
  85. long end=System.currentTimeMillis();//获取复制后的时间戳
  86. System.out.println("使用缓冲字节流(每次读取字节数组512)拷贝文件用时(分钟:秒:毫秒):"
  87. +timeStampToDateString(end-start));
  88. //使用文件字节流,按字节数组拷贝文件
  89. start=System.currentTimeMillis();
  90. copyFileByBytes(new File(packagePath+"李玉刚_刚好遇见你.mp3"),
  91. new File(packagePath+"李玉刚_刚好遇见你副本5.mp3"));
  92. end=System.currentTimeMillis();
  93. System.out.println("使用文件字节流(每次读取字节数组512)拷贝文件用时(分钟:秒:毫秒):"
  94. +timeStampToDateString(end-start));
  95. } catch (UnsupportedEncodingException e1)
  96. {
  97. e1.printStackTrace();
  98. } catch (IOException e)
  99. {
  100. e.printStackTrace();
  101. }
  102. }
  103. }

运行结果:

  1. 使用缓冲字节流(每次读取字节数组512)拷贝文件用时(分钟:秒:毫秒):00:00:34
  2. 使用文件字节流(每次读取字节数组512)拷贝文件用时(分钟:秒:毫秒):00:00:101

可见,每次读取相同的字节数组的条件下,缓冲字节流多了缓冲,进而减少写入文件的次数,从而比文件字节流用时少。

(2)逐个字节读取比较:

  1. import java.io.BufferedInputStream;
  2. import java.io.BufferedOutputStream;
  3. import java.io.File;
  4. import java.io.FileInputStream;
  5. import java.io.FileNotFoundException;
  6. import java.io.FileOutputStream;
  7. import java.io.IOException;
  8. import java.io.UnsupportedEncodingException;
  9. import java.text.DateFormat;
  10. import java.text.SimpleDateFormat;
  11. import java.util.Date;
  12. import com.lan.filepath.FilePath;
  13. public class TestBuffered_FileByByte
  14. {
  15. public static void copyFileBufferdByByte(File srcFile, File destFile, int bufsize)
  16. throws IOException
  17. {
  18. if (!srcFile.exists())
  19. {
  20. throw new FileNotFoundException("文件" + srcFile + "不存在");
  21. }
  22. if (!srcFile.isFile())
  23. {
  24. throw new IllegalArgumentException(srcFile + "不是文件");
  25. }
  26. // 创建缓冲字节流对象,内部缓冲设置为bufSize
  27. BufferedInputStream in = new BufferedInputStream(
  28. new FileInputStream(srcFile), bufsize);
  29. BufferedOutputStream out = new BufferedOutputStream(
  30. new FileOutputStream(destFile), bufsize);
  31. int size = 0;
  32. // 读到字节串到内部缓存,默认缓冲区的大小是8192字节
  33. while ((size = in.read()) != -1)
  34. {
  35. out.write(size);// 把读取到的字节写入到缓冲区,缓冲区写满会自动写入文件
  36. }
  37. out.flush();// 刷新缓冲区写入文件
  38. in.close();
  39. out.close();
  40. }
  41. /**
  42. * 使用FileInputStream和FileOutputStream 按字节数组拷贝文件
  43. *
  44. * @param srcFile
  45. * 源文件File对象
  46. * @param targetFile
  47. * 目标文件File对象
  48. * @throws IOException
  49. */
  50. public static void copyFileByByte(File srcFile, File targetFile)
  51. throws IOException
  52. {
  53. if (!srcFile.exists())
  54. {
  55. throw new IllegalArgumentException(srcFile + "文件不存在");
  56. }
  57. if (!srcFile.isFile())
  58. {
  59. throw new IllegalArgumentException(srcFile + "不是文件");
  60. }
  61. FileInputStream in = new FileInputStream(srcFile);
  62. FileOutputStream out = new FileOutputStream(targetFile);
  63. int size = 0;
  64. while ((size = in.read()) != -1)
  65. {
  66. out.write(size);
  67. }
  68. in.close();
  69. out.close();
  70. }
  71. /**
  72. * 把时间戳(long 毫秒数)转换为格式化时间字符串
  73. *
  74. * @param timeStamp
  75. * long毫秒数
  76. * @return 格式化时间字符串
  77. */
  78. public static String timeStampToDateString(long timeStamp)
  79. {
  80. Date date = new Date(timeStamp);
  81. /*
  82. * m 小时中的分钟数 s 分钟中的秒数 S 毫秒数
  83. */
  84. DateFormat format = new SimpleDateFormat("mm:ss:SS");
  85. String dateString = format.format(date);
  86. return dateString;
  87. }
  88. public static void main(String[] args)
  89. {
  90. String packagePath;
  91. try
  92. {
  93. // 使用缓冲字节流拷贝文件
  94. long start = System.currentTimeMillis();// 获取当前的时间戳
  95. packagePath = FilePath.getSrcPackagePath(TestBufferedCopy.class);
  96. copyFileBufferdByByte(new File(packagePath + "李玉刚_刚好遇见你.mp3"),
  97. new File(packagePath + "李玉刚_刚好遇见你副本6.mp3"), 1024 * 10);
  98. long end = System.currentTimeMillis();// 获取复制后的时间戳
  99. System.out.println("使用缓冲字节流(逐个字节)拷贝文件用时(分钟:秒:毫秒):"
  100. + timeStampToDateString(end - start));
  101. // 使用文件字节流,按字节数组拷贝文件
  102. start = System.currentTimeMillis();
  103. copyFileByByte(new File(packagePath + "李玉刚_刚好遇见你.mp3"),
  104. new File(packagePath + "李玉刚_刚好遇见你副本7.mp3"));
  105. end = System.currentTimeMillis();
  106. System.out.println("使用文件字节流(逐个字节)拷贝文件用时(分钟:秒:毫秒):"
  107. + timeStampToDateString(end - start));
  108. } catch (UnsupportedEncodingException e1)
  109. {
  110. e1.printStackTrace();
  111. } catch (IOException e)
  112. {
  113. e.printStackTrace();
  114. }
  115. }
  116. }

运行结果:

  1. 使用缓冲字节流(逐个字节)拷贝文件用时(分钟:秒:毫秒):00:00:279
  2. 使用文件字节流(逐个字节)拷贝文件用时(分钟:秒:毫秒):00:35:982

可以看到逐个字节逐个字节的来拷贝文件,使用文件字节流要读一个字节写一个字节,耗时很大。虽然也是每次读取一个字节一个字节的读取,但是使用缓冲字节流读取满缓冲,才写一次文件,也就是读取1024 * 10次,才写一次文件。相比于使用文件字节流节省了1024 * 10-1次写文件的操作。这样就节省更多的时间。

总结:

(1) 如果使用文件字节流,复制文件,每次读取一个数组,写一个数组,比每次读取一个字节,写一个字节更快。

(2) 使用缓冲字节流比文件字节流更快(多分配内存(缓冲)):每次读取一个数组放到一个大的数组中去(缓冲),然后大的数组(缓冲)满了再一次性写入。

发表评论

表情:
评论列表 (有 0 条评论,386人围观)

还没有评论,来说两句吧...

相关阅读

    相关 使用节流读/写文件

    Java 的 I/O 流提供了一条通道,这条通道可以把数据送给目的地。输入流的指向称作源,程序从指向源的输入流中读取源中的数据。输出流的指向是数据要去的目的地,程序通过向输出流

    相关 IO复制文件节流

    复制文件 通过该原理,我们知道我们应该采用字节流。(图片) 而字节流有4种方式,所以做这个题目我们有4种方式。重点第4种。 public class Copy

    相关 使用节流读/写文件

    Java 的 I/O 流提供了一条通道,这条通道可以把数据送给目的地。输入流的指向称作源,程序从指向源的输入流中读取源中的数据。输出流的指向是数据要去的目的地,程序通过向...