前天项目组遇到文件上传,对内存加大的问题。特意看了看相关知识,也对这个有一定的了解
try {
FileInputStream fis=new FileInputStream(new File("/home/saas/maven/maven.zip"));
BufferedInputStream bis=new BufferedInputStream(fis);
FileOutputStream fos=new FileOutputStream(new File("/home/saas/bb.sh"));
byte[] buffer=new byte[1024*1024*1024];//这是自定义java缓冲区
int len=0;
while((len=bis.read(buffer))>0){//
fos.write(buffer, 0, len);//貌似直接就调用了io的底层
// fos.flush();
System.out.println("复制了 1024*1024*1024 Byte");
}
fis.close();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
首先这里个FileInputtream里面的close方法和flush()方法 不调用也会将文件,这个文件也会被复制成功,并且数据对。原理是这样的,因为fos里面直接调用的本地方法,将数据写入文件,所以不关掉也能成功,但不关掉会造成内存不能回收,有可能造成内存泄漏什么的
其次,BufferedInputream和BufferedOutputStream 都是提供缓存,可以看到里面有个缓存数组buf[] 默认是8092字节。以下是源码
/**
* Writes the specified byte to this buffered output stream.
*
* @param b the byte to be written.
* @exception IOException if an I/O error occurs.
*/
public synchronized void write(int b) throws IOException {
if (count >= buf.length) {
flushBuffer();
}
buf[count++] = (byte)b;
}
这里首先判断一下,当前是缓冲区是否已经满了,如果没满,就继续写,如果满了,就会flushBuffer,flushBuffer其实就是将调用本地方法,将字节数组里的数据写入文件里面,以下是源码
/** Flush the internal buffer */
private void flushBuffer() throws IOException {
if (count > 0) {
out.write(buf, 0, count);
count = 0;
}
}
当你调用BufferOutputStream 的write.如果传入的是FileInputStream的话,BufferOutputSream 里面的out就会指向FileInputStream。这里使用了装饰模式。
另外可以看到源码,FileInputStream里面的flush是继承OutputStream的,而OutputStream里的flush是个空的方法,什么都没干