赞
踩
最近关乎性能问题,网上查了查资料,这里记录一下。
近来,在做服务器后台处理数据的时候,需要用到Java自带的几种流对数据进行读写,初始时没怎么在意,就随便用了一个,结果发现性能上并不尽如人意。于是对几种常用的流做了个小小的性能测试。测试代码如下:
1 public static int FileOutputStreamTime = 0; 2 public static int BufferedOutputStreamTime = 0; 3 public static int FileWriterTime = 0; 4 public static int FileInputStreamTime = 0; 5 public static int BufferedInputStreamTime = 0; 6 public static int FileReaderTime = 0; 7 8 public static void write(String filePath, String content){ 9 FileOutputStream out = null; 10 FileOutputStream outStr = null; 11 BufferedOutputStream buf = null; 12 FileWriter fw = null; 13 File f = new File(filePath); 14 15 try { 16 //Test FileOutputStream 17 long begin1 = System.currentTimeMillis(); 18 out = new FileOutputStream(f); 19 out.write(content.getBytes()); 20 out.close(); 21 long end1 = System.currentTimeMillis(); 22 FileOutputStreamTime += end1 - begin1; 23 24 //Test BufferedOutputStream 25 long begin2 = System.currentTimeMillis(); 26 outStr = new FileOutputStream(f); 27 buf = new BufferedOutputStream(outStr); 28 buf.write(content.getBytes()); 29 buf.flush(); 30 buf.close(); 31 long end2 = System.currentTimeMillis(); 32 BufferedOutputStreamTime += end2 - begin2; 33 34 //Test FileWriter 35 long begin3 = System.currentTimeMillis(); 36 // the second parameter "true",Whether or not a file will be covered 37 // or appended. 38 fw = new FileWriter(f); 39 // fw = new FileWriter("d:/test/testwrite/add2.txt",true); 40 fw.write(content); 41 fw.close(); 42 long end3 = System.currentTimeMillis(); 43 FileWriterTime += end3 - begin3; 44 } catch (Exception e) { 45 e.printStackTrace(); 46 } finally { 47 try { 48 fw.close(); 49 buf.close(); 50 outStr.close(); 51 out.close(); 52 } catch (Exception e) { 53 e.printStackTrace(); 54 } 55 } 56 } 57 58 public static void read(String filePath){ 59 FileInputStream in = null; 60 BufferedInputStream buf = null; 61 FileReader reader = null; 62 BufferedReader br = null; 63 StringBuffer sb = new StringBuffer(); 64 65 try { 66 //Test FileInputStream 67 long begin1 = System.currentTimeMillis(); 68 File f = new File(filePath); 69 in = new FileInputStream(f); 70 int len1 = 512; 71 byte[] bytes1 = new byte[len1]; 72 73 while ((len1 = in.read(bytes1, 0, len1)) != -1) { 74 if(len1 < 512){ 75 byte[] tmpBuf = new byte[len1]; 76 System.arraycopy(bytes1, 0, tmpBuf, 0, len1); 77 sb.append(new String(tmpBuf)); 78 tmpBuf = null; 79 }else{ 80 sb.append(new String(bytes1)); 81 } 82 } 83 84 in.close(); 85 long end1 = System.currentTimeMillis(); 86 FileInputStreamTime += end1 - begin1; 87 88 //Test BufferedInputStream 89 long begin2 = System.currentTimeMillis(); 90 int len2 = 512; 91 byte[] bytes2 = new byte[len2]; 92 buf = new BufferedInputStream(new FileInputStream(f)); 93 while ((len2 = buf.read(bytes2, 0, len2)) != -1) { 94 if(len2 < 512){ 95 byte[] tmpBuf = new byte[len2]; 96 System.arraycopy(bytes2, 0, tmpBuf, 0, len2); 97 sb.append(new String(tmpBuf)); 98 tmpBuf = null; 99 }else{ 100 sb.append(new String(bytes2)); 101 } 102 } 103 104 buf.close(); 105 long end2 = System.currentTimeMillis(); 106 BufferedInputStreamTime += end2 - begin2; 107 108 //Test FileReader 109 long begin3 = System.currentTimeMillis(); 110 reader = new FileReader(f); 111 br = new BufferedReader(reader); 112 String str; 113 while ((str = br.readLine()) != null) { 114 sb.append(str); 115 } 116 br.close(); 117 reader.close(); 118 long end3 = System.currentTimeMillis(); 119 FileReaderTime += end3 - begin3; 120 121 } catch (Exception e) { 122 e.printStackTrace(); 123 } finally { 124 try { 125 br.close(); 126 reader.close(); 127 in.close(); 128 buf.close(); 129 } catch (Exception e) { 130 e.printStackTrace(); 131 } 132 } 133 }
测试时,分别对不同大小的数据做500次同样的操作,取得的平均耗时如下:
10K | 100K | 200K | 400K | |
FileOutputStream | 0.496 | 0.794 | 1.078 | 1.602 |
BufferedOutputStream | 0.386 | 0.684 | 0.878 | 1.246 |
FileWriter | 0.586 | 0.996 | 1.3 | 1.946 |
FileInputStream | 0.158 | 0.544 | 0.984 | 1.876 |
BufferedInputStream | 0.152 | 0.396 | 0.668 | 1.068 |
FileReader | 0.152 | 0.608 | 1.254 | 2.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则是字节数组输出流接口. 这2个输出流都是我们经常用到的, 它们都是OutputStream的子类,而什么时候选择用它们呢, 这个就要看你运用到什么应用场景下了.
下来先来看下源码吧.
1.BufferedOutputStream会首先创建一个默认的容器量, capacity = 8192 = 8KB, 每次在写的时候都会去比对capacity是否还够用, 如果不够用的时候, 就flushBuffer(), 把buf中的数据写入对应的outputStream中, 然后将buf清空, 一直这样等到把内容写完. 在这过程中主要起到了一个数据缓冲的功能.
flushBuffer () 这个方法干了些什么呢, 来看看源码
这个类最重要的就是这2个方法, 这样节省了大量的内存空间, 合理的分配内存来完成数据输出,当你资源不是那么充沛时, 选择这个类来实现你想要的东西是不是很合适呢?
2.普通的OutputStream, 例如ByteArrayOutputStream也会首先创建一个默认的容器量, capacity = 32 = 32byte, 每次在写的时候都会去比对capacity是否还够用, 如果不够用的时候, 就重新创建buf的容量, 一直等到内容写完, 这些数据都会一直处于内存中.
- /**
- * Creates a new byte array output stream. The buffer capacity is
- * initially 32 bytes, though its size increases if necessary.
- */
- public ByteArrayOutputStream() {
- this(32);
- }
-
- /**
- * Creates a new byte array output stream, with a buffer capacity of
- * the specified size, in bytes.
- *
- * @param size the initial size.
- * @exception IllegalArgumentException if size is negative.
- */
- public ByteArrayOutputStream(int size) {
- if (size < 0) {
- throw new IllegalArgumentException("Negative initial size: "
- + size);
- }
- buf = new byte[size];
- }
-
-
- /**
- * Increases the capacity to ensure that it can hold at least the
- * number of elements specified by the minimum capacity argument.
- *
- * @param minCapacity the desired minimum capacity
- */
- private void grow(int minCapacity) {
- // overflow-conscious code
- int oldCapacity = buf.length;
- int newCapacity = oldCapacity << 1;
- if (newCapacity - minCapacity < 0)
- newCapacity = minCapacity;
- if (newCapacity - MAX_ARRAY_SIZE > 0)
- newCapacity = hugeCapacity(minCapacity);
- buf = Arrays.copyOf(buf, newCapacity);
- }
-
-
- /**
- * Increases the capacity if necessary to ensure that it can hold
- * at least the number of elements specified by the minimum
- * capacity argument.
- *
- * @param minCapacity the desired minimum capacity
- * @throws OutOfMemoryError if {@code minCapacity < 0}. This is
- * interpreted as a request for the unsatisfiably large capacity
- * {@code (long) Integer.MAX_VALUE + (minCapacity - Integer.MAX_VALUE)}.
- */
- private void ensureCapacity(int minCapacity) {
- // overflow-conscious code
- if (minCapacity - buf.length > 0)
- grow(minCapacity);
- }
-
-
-
- /**
- * Writes <code>len</code> bytes from the specified byte array
- * starting at offset <code>off</code> to this byte array output stream.
- *
- * @param b the data.
- * @param off the start offset in the data.
- * @param len the number of bytes to write.
- */
- public synchronized void write(byte b[], int off, int len) {
- if ((off < 0) || (off > b.length) || (len < 0) ||
- ((off + len) - b.length > 0)) {
- throw new IndexOutOfBoundsException();
- }
- ensureCapacity(count + len);
- System.arraycopy(b, off, buf, count, len);
- count += len;
- }
注释中已经对这个类进行了详细的解释
总结 :
当你资源不足够用时,选择BufferedOutputStream是最佳的选择,
当你选择快速完成一个作业时,可以选择ByteArrayOutputStream之类的输出流
转自:
https://www.cnblogs.com/Scott007/archive/2013/05/14/3078759.html
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。