我想将包含字符串的大文件拆分为一组新的(较小的)文件,并尝试使用nio2。
我不想将整个文件加载到内存中,因此我尝试了BufferedReader。
较小的文本文件应受文本行数的限制。
该解决方案有效,但是我想问一问,有人知道使用usion java 8(也许是带有stream()-api的lamdas)和nio2具有更好性能的解决方案:
public void splitTextFiles(Path bigFile, int maxRows) throws IOException{
int i = 1;
try(BufferedReader reader = Files.newBufferedReader(bigFile)){
String line = null;
int lineNum = 1;
Path splitFile = Paths.get(i + "split.txt");
BufferedWriter writer = Files.newBufferedWriter(splitFile, StandardOpenOption.CREATE);
while ((line = reader.readLine()) != null) {
if(lineNum > maxRows){
writer.close();
lineNum = 1;
i++;
splitFile = Paths.get(i + "split.txt");
writer = Files.newBufferedWriter(splitFile, StandardOpenOption.CREATE);
}
writer.append(line);
writer.newLine();
lineNum++;
}
writer.close();
}
}
当心直接使用/ 及其子类和/的/ factory方法之间的区别。在前一种情况下,如果未指定任何显式字符集,则使用系统的默认编码,而后者始终默认为。因此,我强烈建议您始终指定所需的字符集,即使它是或要记录您的意图,也可以避免在创建或的各种方法之间切换时感到意外。 InputStreamReader
OutputStreamWriter
Reader
Writer
Files
UTF-8
Charset.defaultCharset()
StandardCharsets.UTF_8
Reader
Writer
如果要在行边界处分割,则无法解决文件内容的问题。因此,您无法像合并时那样优化它。
如果您愿意牺牲可移植性,则可以尝试一些优化。如果您知道charset编码将明确映射'\n'
到(byte)'\n'
大多数单字节编码的情况,并且UTF-8
您可以扫描字节级别的换行符以获取拆分的文件位置,并避免从应用程序传输任何数据到I / O系统。
public void splitTextFiles(Path bigFile, int maxRows) throws IOException {
MappedByteBuffer bb;
try(FileChannel in = FileChannel.open(bigFile, READ)) {
bb=in.map(FileChannel.MapMode.READ_ONLY, 0, in.size());
}
for(int start=0, pos=0, end=bb.remaining(), i=1, lineNum=1; pos<end; lineNum++) {
while(pos<end && bb.get(pos++)!='\n');
if(lineNum < maxRows && pos<end) continue;
Path splitFile = Paths.get(i++ + "split.txt");
// if you want to overwrite existing files use CREATE, TRUNCATE_EXISTING
try(FileChannel out = FileChannel.open(splitFile, CREATE_NEW, WRITE)) {
bb.position(start).limit(pos);
while(bb.hasRemaining()) out.write(bb);
bb.clear();
start=pos;
lineNum = 0;
}
}
}
缺点是它不适用于UTF-16
or或EBCDIC
and之类的编码,BufferedReader.readLine()
与之不同的是,它不像'\r'
旧MacOS9中那样支持单独作为行终止符。
此外,它仅支持小于2GB的文件。由于虚拟地址空间有限,该限制在32Bit JVM上甚至可能更小。对于大于限制的文件,有必要遍历源文件的各个块,map
然后逐个进行迭代。
这些问题可以解决,但会增加此方法的复杂性。考虑到速度在我的机器上仅提高了约15%(我并没有期望更多,因为I / O在这里占主导地位),并且在复杂性提高时甚至会更小,我认为这是不值得的。
最重要的是,对于此任务,Reader
/ Writer
方法已足够,但您应注意Charset
该操作所使用的方法。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句