当前位置:   article > 正文

几种Java读写数据的流性能对比_bufferedinputstream和inputstream效率比较

bufferedinputstream和inputstream效率比较

最近关乎性能问题,网上查了查资料,这里记录一下。

 

近来,在做服务器后台处理数据的时候,需要用到Java自带的几种流对数据进行读写,初始时没怎么在意,就随便用了一个,结果发现性能上并不尽如人意。于是对几种常用的流做了个小小的性能测试。测试代码如下:

  1. 1 public static int FileOutputStreamTime = 0;
  2. 2 public static int BufferedOutputStreamTime = 0;
  3. 3 public static int FileWriterTime = 0;
  4. 4 public static int FileInputStreamTime = 0;
  5. 5 public static int BufferedInputStreamTime = 0;
  6. 6 public static int FileReaderTime = 0;
  7. 7
  8. 8 public static void write(String filePath, String content){
  9. 9 FileOutputStream out = null;
  10. 10 FileOutputStream outStr = null;
  11. 11 BufferedOutputStream buf = null;
  12. 12 FileWriter fw = null;
  13. 13 File f = new File(filePath);
  14. 14
  15. 15 try {
  16. 16 //Test FileOutputStream
  17. 17 long begin1 = System.currentTimeMillis();
  18. 18 out = new FileOutputStream(f);
  19. 19 out.write(content.getBytes());
  20. 20 out.close();
  21. 21 long end1 = System.currentTimeMillis();
  22. 22 FileOutputStreamTime += end1 - begin1;
  23. 23
  24. 24 //Test BufferedOutputStream
  25. 25 long begin2 = System.currentTimeMillis();
  26. 26 outStr = new FileOutputStream(f);
  27. 27 buf = new BufferedOutputStream(outStr);
  28. 28 buf.write(content.getBytes());
  29. 29 buf.flush();
  30. 30 buf.close();
  31. 31 long end2 = System.currentTimeMillis();
  32. 32 BufferedOutputStreamTime += end2 - begin2;
  33. 33
  34. 34 //Test FileWriter
  35. 35 long begin3 = System.currentTimeMillis();
  36. 36 // the second parameter "true",Whether or not a file will be covered
  37. 37 // or appended.
  38. 38 fw = new FileWriter(f);
  39. 39 // fw = new FileWriter("d:/test/testwrite/add2.txt",true);
  40. 40 fw.write(content);
  41. 41 fw.close();
  42. 42 long end3 = System.currentTimeMillis();
  43. 43 FileWriterTime += end3 - begin3;
  44. 44 } catch (Exception e) {
  45. 45 e.printStackTrace();
  46. 46 } finally {
  47. 47 try {
  48. 48 fw.close();
  49. 49 buf.close();
  50. 50 outStr.close();
  51. 51 out.close();
  52. 52 } catch (Exception e) {
  53. 53 e.printStackTrace();
  54. 54 }
  55. 55 }
  56. 56 }
  57. 57
  58. 58 public static void read(String filePath){
  59. 59 FileInputStream in = null;
  60. 60 BufferedInputStream buf = null;
  61. 61 FileReader reader = null;
  62. 62 BufferedReader br = null;
  63. 63 StringBuffer sb = new StringBuffer();
  64. 64
  65. 65 try {
  66. 66 //Test FileInputStream
  67. 67 long begin1 = System.currentTimeMillis();
  68. 68 File f = new File(filePath);
  69. 69 in = new FileInputStream(f);
  70. 70 int len1 = 512;
  71. 71 byte[] bytes1 = new byte[len1];
  72. 72
  73. 73 while ((len1 = in.read(bytes1, 0, len1)) != -1) {
  74. 74 if(len1 < 512){
  75. 75 byte[] tmpBuf = new byte[len1];
  76. 76 System.arraycopy(bytes1, 0, tmpBuf, 0, len1);
  77. 77 sb.append(new String(tmpBuf));
  78. 78 tmpBuf = null;
  79. 79 }else{
  80. 80 sb.append(new String(bytes1));
  81. 81 }
  82. 82 }
  83. 83
  84. 84 in.close();
  85. 85 long end1 = System.currentTimeMillis();
  86. 86 FileInputStreamTime += end1 - begin1;
  87. 87
  88. 88 //Test BufferedInputStream
  89. 89 long begin2 = System.currentTimeMillis();
  90. 90 int len2 = 512;
  91. 91 byte[] bytes2 = new byte[len2];
  92. 92 buf = new BufferedInputStream(new FileInputStream(f));
  93. 93 while ((len2 = buf.read(bytes2, 0, len2)) != -1) {
  94. 94 if(len2 < 512){
  95. 95 byte[] tmpBuf = new byte[len2];
  96. 96 System.arraycopy(bytes2, 0, tmpBuf, 0, len2);
  97. 97 sb.append(new String(tmpBuf));
  98. 98 tmpBuf = null;
  99. 99 }else{
  100. 100 sb.append(new String(bytes2));
  101. 101 }
  102. 102 }
  103. 103
  104. 104 buf.close();
  105. 105 long end2 = System.currentTimeMillis();
  106. 106 BufferedInputStreamTime += end2 - begin2;
  107. 107
  108. 108 //Test FileReader
  109. 109 long begin3 = System.currentTimeMillis();
  110. 110 reader = new FileReader(f);
  111. 111 br = new BufferedReader(reader);
  112. 112 String str;
  113. 113 while ((str = br.readLine()) != null) {
  114. 114 sb.append(str);
  115. 115 }
  116. 116 br.close();
  117. 117 reader.close();
  118. 118 long end3 = System.currentTimeMillis();
  119. 119 FileReaderTime += end3 - begin3;
  120. 120
  121. 121 } catch (Exception e) {
  122. 122 e.printStackTrace();
  123. 123 } finally {
  124. 124 try {
  125. 125 br.close();
  126. 126 reader.close();
  127. 127 in.close();
  128. 128 buf.close();
  129. 129 } catch (Exception e) {
  130. 130 e.printStackTrace();
  131. 131 }
  132. 132 }
  133. 133 }

 

  测试时,分别对不同大小的数据做500次同样的操作,取得的平均耗时如下:

不同流耗时对比(ms)
 10K100K200K400K
FileOutputStream0.4960.7941.0781.602
BufferedOutputStream0.3860.6840.8781.246
FileWriter0.5860.9961.31.946
FileInputStream0.1580.5440.9841.876
BufferedInputStream0.1520.3960.6681.068
FileReader0.1520.6081.2542.19

  通过测试,可以发现,就写数据而言,BufferedOutputStream耗时是最短的,而性能FileWriter最差;读数据方面,BufferedInputStream性能最好,而FileReader性能最差劲。所以,以后在涉及到流的读写方面时,要注意一下了~

  FileOutputStream 用于写入诸如图像数据之类的原始字节的流。要写入字符流,请考虑使用 FileWriter。

  BufferedOutputStream的数据成员buf是一个位数组,默认为512字节。当使用write()方法写入数据时,实际上会先将数据写至buf中,当buf已满时才会实现给定的OutputStream对象的write()方法,将buf数据写至目的地,而不是每次都对目的地作写入的动作。BufferedInputStream也是类似。

  另外,有时只是要存储一个对象的成员数据,而不是整个对象的信息,成员数据的类型假设都是Java的基本数据类型,这样的需求不必要使用到与Object输入、输出相关的流对象,可以使用DataInputStream、DataOutputStream来写入或读出数据。在从文件中读出数据时,不用费心地自行判断读入字符串时或读入int类型时何时该停止,使用对应的readUTF()或readInt()方法就可以正确地读入完整类型数据。

  在Java程序执行的过程中,很多数据都是以对象的方式存在于内存中。有时会希望直接将内存中整个对象存储至文件,而不是只存储对象中的某些基本类型成员信息,而在下一次程序运行时,希望可以从文件中读出数据并还原为对象。这时可以使用java.io.ObjectInputStream和java.io.ObjectOutputStream来进行这项工作。

  ByteArrayInputStream可以将一个数组当作流输入的来源,而ByteArrayOutputStream则可以将一个位数组当作流输出的目的地。在这里举一个简单的文件位编辑程序作为例子,您可以打开一个简单的文本文件,其中有简单的A、B、C、D、E、F、G等字符,在读取文件之后,可以直接以程序来指定文件中位的位置来修改所指定的字符。作法是将文件读入数组中,指定数组索引修改元素,然后重新将数组存回文件。

  java.io.Reader和java.io.Writer支持Unicode标准字符集(Character Set)(字节流则只支持ISO-Latin-1 8-bit)。在处理流数据时,会根据系统默认的字符编码来进行字符转换,Reader和Writer是抽象类,在进行文本文件的字符读写时真正会使用其子类,子类通常会重新定义相关的方法。

  如果想要存取的是一个文本文件,可以直接使用java.io.FileReader和java.io.FileWriter类,它们分别继承自InputStreamReader与OutputStreamWriter。可以直接指定文件名称或File对象来打开指定的文本文件,并读入流转换后的字符,字符的转换会根据系统默认的编码(若要指定编码,则还是使用InputStreamReader与OutputStreamWriter)。

  java.io.BufferedReader与java.io.BufferedWriter类各拥有8192字符的缓冲区。当BufferedReader在读取文本文件时,会先尽量从文件中读入字符数据并置入缓冲区,而之后若使用read()方法,会先从缓冲区中进行读取。如果缓冲区数据不足,才会再从文件中读取,使用BufferedWriter时,写入的数据并不会先输出至目的地,而是先存储至缓冲区中。如果缓冲区中的数据满了,才会一次对目的地进行写出。例如一个文件,通过缓冲区可减少对硬盘的输入/输出动作,以提高文件存取的效率。

 

BufferedOutputStream和ByteArrayOutputStream区别

今天主要是想记录下BufferedOutputStream和ByteArrayOutputStream区别

众所周知BufferedOutputStream是一个缓冲数据输出流接口, ByteArrayOutputStream则是字节数组输出流接口. 这2个输出流都是我们经常用到的, 它们都是OutputStream的子类,而什么时候选择用它们呢, 这个就要看你运用到什么应用场景下了.

下来先来看下源码吧.

1.BufferedOutputStream会首先创建一个默认的容器量, capacity = 8192 = 8KB, 每次在写的时候都会去比对capacity是否还够用, 如果不够用的时候, 就flushBuffer(), 把buf中的数据写入对应的outputStream中, 然后将buf清空, 一直这样等到把内容写完. 在这过程中主要起到了一个数据缓冲的功能.

  1. public synchronized void write(byte b[], int off, int len) throws IOException {  
  2.       // 在这判断需要写的数据长度是否已经超出容器的长度了,如果超出则直接写到相应的outputStream中,并清空缓冲区  
  3.       if (len >= buf.length) {  
  4.           flushBuffer();  
  5.           out.write(b, off, len);  
  6.           return;  
  7.       }  
  8.       // 判断缓冲区剩余的容量是否还够写入当前len的内容,如果不够则清空缓冲区  
  9.       if (len > buf.length - count) {  
  10.           flushBuffer();  
  11.       }  
  12.       // 将要写的数据先放入内存中,等待数据达到了缓冲区的长度后,再写到相应的outputStream中  
  13.       System.arraycopy(b, off, buf, count, len);  
  14.       count += len;  
  15.     }  



flushBuffer () 这个方法干了些什么呢, 来看看源码

  1. private void flushBuffer() throws IOException {  
  2.        if (count > 0) {  
  3.           // 把写入内存中的数据写到构造方法里传入的OutputStream句柄里, 并把容量大小清楚  
  4.     out.write(buf, 0, count);  
  5.     count = 0;  
  6.        }  
  7.    }  


这个类最重要的就是这2个方法, 这样节省了大量的内存空间, 合理的分配内存来完成数据输出,当你资源不是那么充沛时, 选择这个类来实现你想要的东西是不是很合适呢?

2.普通的OutputStream, 例如ByteArrayOutputStream也会首先创建一个默认的容器量, capacity = 32 = 32byte, 每次在写的时候都会去比对capacity是否还够用, 如果不够用的时候, 就重新创建buf的容量, 一直等到内容写完, 这些数据都会一直处于内存中.

 

  1. /**
  2. * Creates a new byte array output stream. The buffer capacity is
  3. * initially 32 bytes, though its size increases if necessary.
  4. */
  5. public ByteArrayOutputStream() {
  6. this(32);
  7. }
  8. /**
  9. * Creates a new byte array output stream, with a buffer capacity of
  10. * the specified size, in bytes.
  11. *
  12. * @param size the initial size.
  13. * @exception IllegalArgumentException if size is negative.
  14. */
  15. public ByteArrayOutputStream(int size) {
  16. if (size < 0) {
  17. throw new IllegalArgumentException("Negative initial size: "
  18. + size);
  19. }
  20. buf = new byte[size];
  21. }
  22. /**
  23. * Increases the capacity to ensure that it can hold at least the
  24. * number of elements specified by the minimum capacity argument.
  25. *
  26. * @param minCapacity the desired minimum capacity
  27. */
  28. private void grow(int minCapacity) {
  29. // overflow-conscious code
  30. int oldCapacity = buf.length;
  31. int newCapacity = oldCapacity << 1;
  32. if (newCapacity - minCapacity < 0)
  33. newCapacity = minCapacity;
  34. if (newCapacity - MAX_ARRAY_SIZE > 0)
  35. newCapacity = hugeCapacity(minCapacity);
  36. buf = Arrays.copyOf(buf, newCapacity);
  37. }
  38. /**
  39. * Increases the capacity if necessary to ensure that it can hold
  40. * at least the number of elements specified by the minimum
  41. * capacity argument.
  42. *
  43. * @param minCapacity the desired minimum capacity
  44. * @throws OutOfMemoryError if {@code minCapacity < 0}. This is
  45. * interpreted as a request for the unsatisfiably large capacity
  46. * {@code (long) Integer.MAX_VALUE + (minCapacity - Integer.MAX_VALUE)}.
  47. */
  48. private void ensureCapacity(int minCapacity) {
  49. // overflow-conscious code
  50. if (minCapacity - buf.length > 0)
  51. grow(minCapacity);
  52. }
  53. /**
  54. * Writes <code>len</code> bytes from the specified byte array
  55. * starting at offset <code>off</code> to this byte array output stream.
  56. *
  57. * @param b the data.
  58. * @param off the start offset in the data.
  59. * @param len the number of bytes to write.
  60. */
  61. public synchronized void write(byte b[], int off, int len) {
  62. if ((off < 0) || (off > b.length) || (len < 0) ||
  63. ((off + len) - b.length > 0)) {
  64. throw new IndexOutOfBoundsException();
  65. }
  66. ensureCapacity(count + len);
  67. System.arraycopy(b, off, buf, count, len);
  68. count += len;
  69. }


注释中已经对这个类进行了详细的解释

总结 :

当你资源不足够用时,选择BufferedOutputStream是最佳的选择,

当你选择快速完成一个作业时,可以选择ByteArrayOutputStream之类的输出流

 

转自:

https://www.cnblogs.com/Scott007/archive/2013/05/14/3078759.html

https://www.iteye.com/blog/z276356445t-1955400

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/147121
推荐阅读
相关标签
  

闽ICP备14008679号