日常网络和数据库文件输入输出处理是很耗时间和消耗处理器时间的,所以I/O操作被普遍认为是昂贵的操作。 这里我们假设有一份非常大的文件,比如1G, 我们不可能拿任意一个InputStream 实现类去直接用那文件类File去封装传入构造方法直接处理,操作系统是不会让一个正在执行“非常耗时”的程序去占用大量时间去处理一个I/O 操作。所以我们必须拆分这个大文件为数个小的文件去依此处理。主体思想是先拆分成小字节块的文件在由这些小字节块文件合并成原来文件;这有点类似与网络传输一个大文件的过程,把文件拆除小的数据包然后再由数千甚至上万不等地路径传输到不同的终端。
主要核心:
按某个数量值去拆分大文件成小文件
小文件的读写都由一个特定的BufferSize (字节容器大小)来决定输入和输出流的字节负荷
合并 的思路也类似
按特定的BufferSize (字节容器大小)来决定读写可承受的负荷去处理多个拆分的小文件
下方带图阐述了主要思路
注意 : 本教程未用到同步和并发处理,仅是为了阐述I/O大文件拆分和合并的主体思想,若要用并发处理,下列代码实现需做改变。
FileSpliterAndMerger.png
FileSpliter.java
成员变量
- String inputPathName;
- String outputPathNamePrefix;
- int maxBufferSize;
- final int ONE_BYTE = 1024;
成员方法
+ FileSpliter(String inputPathName, String outputPathNamePrefix, int maxBufferSize)
+ void splitStart(int numOfSplits)
+ void split(int numOfSplits) throws Exception
+ static void readWrite(RandomAccessFile raf, BufferedOutputStream bw, long numBytes) throws IOException
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* FileSpliter: 用于拆分一个大容量文件,把其分成 numOfSplits 小块文件大小字节
* 处理,这个减缓IOStream的吞吐量。这个类可以日后加多线程处理或用
* 并行库来用不同的core或者thread去运算和处理每个文件。
* @author kaili
*
*/
public class FileSpliter {
private String inputPathName; // 输入文件路径
private String outputPathNamePrefix; // 输出文件路径
private int maxBufferSize; // 每个块的数据处理容器大小: maxBufferSize * ONE_BYTE = maxBufferSize kb
private final int ONE_BYTE = 1024;
/**
* 初始化下列参数列表成员变量
* @param inputPathName
* @param outputPathNamePrefix
* @param maxBufferSize
*/
public FileSpliter(String inputPathName, String outputPathNamePrefix,
int maxBufferSize) {
this.inputPathName = inputPathName;
this.outputPathNamePrefix = outputPathNamePrefix;
this.maxBufferSize = maxBufferSize;
}
/***
* 启动方法,间接调用拆分方法split
* @param numOfSplits
*/
public void splitStart(int numOfSplits) {
try {
split(numOfSplits);
} catch (Exception e) {
e.printStackTrace();
}
}
/