- commons-fileupload框架源码解析(一)--实例
- commons-fileupload框架源码解析(二)--HTTP
- commons-fileupload框架源码解析(三)--ParseRequest
- commons-fileupload框架源码解析(四)--FileItemIterator
- commons-fileupload框架源码解析(五)--MultipartStream
- commons-fileupload框架源码解析(六)--ParameterParser
- commons-fileupload框架源码解析(七)--FileCleaningTracker
- commons-fileupload框架源码解析(八)--DeferredFileOutputStream
简介
DeferredFileOutputStream是一个根据设定的最大内存阀值去控制写入到内存中,还是写入到硬盘中。
ThresholdingOutputStream
DeferredFileOutputStream继承ThresholdOutputStream,ThresholdOutputStream继承OuptStream,重写了write相关方法。
ThresholdOutputStream.write相关方法
@Override
public void write(final int b) throws IOException
{
checkThreshold(1);
getStream().write(b);
written++;
}
@Override
public void write(final byte b[]) throws IOException
{
checkThreshold(b.length);
getStream().write(b);
written += b.length;
}
@Override
public void write(final byte b[], final int off, final int len) throws IOException
{
checkThreshold(len);
getStream().write(b, off, len);
written += len;
}
主要是加上了chekThreshold(len)方法,并调用getStream()交给另一个流
处理,并统计写入了多少字节(written)。
ThresholdOutputStream.checkThreshold(int)
protected void checkThreshold(final int count) throws IOException
{
if (!thresholdExceeded && written + count > threshold)
{
thresholdExceeded = true;
thresholdReached();
}
}
检查当前的写入到内容流的字节数written是否大于阀值threshold,大于的时候会调用thresholdReached()
getStream & thresholdReached
/**
* Returns the underlying output stream, to which the corresponding
* <code>OutputStream</code> methods in this class will ultimately delegate.
* 获取输出流
* @return The underlying output stream.
*
* @throws IOException if an error occurs.
*/
protected abstract OutputStream getStream() throws IOException;
/**
* Indicates that the configured threshold has been reached, and that a
* subclass should take whatever action necessary on this event. This may
* include changing the underlying output stream.
* 当前的写入字节数written是否大于阀值threshold时触发
* @throws IOException if an error occurs.
*/
protected abstract void thresholdReached() throws IOException;
这两个是抽象方法,而DeferredFileOutputStream重写了,先看getStream
DeferredFileOutputStream.getStream
@Override
protected OutputStream getStream() throws IOException
{
return currentOutputStream;
}
返回currentOuputStream,一开始默认是内存流ByteArrayOutputStream。
DeferredFileOutputStream.thresholdReached
@Override
protected void thresholdReached() throws IOException
{
//如果prefix,suffix,directory不为null,outputFile不管是否已经引用了对象,都会重新调用File.createTempFile(String,String,File)来
//创建指定的临时文件,并让后outputFile指向这个文件
if (prefix != null) {
//创建临时文件
outputFile = File.createTempFile(prefix, suffix, directory);
}
FileUtils.forceMkdirParent(outputFile);//检查父级目录是否存在,不存在则创建,创建父级文件目录
final FileOutputStream fos = new FileOutputStream(outputFile);
try {
memoryOutputStream.writeTo(fos);//将已经内容流的数据写入进文件流
} catch (final IOException e){
fos.close();//当前出现异常时关闭流,并抛出异常
throw e;
}
currentOutputStream = fos;
memoryOutputStream = null;
}
当达到阀值的时候,thresholdReached()就会被调用,会将内存流memoryOutputStream中的数据转换到写入硬盘的流FileOuputStream中,并将FileOuputStream重新赋值currentOuptputStream