我正在努力实现以下目标。
假设我们有两个文件 - file1和文件2,其中包含以下内容
文件1:
header
d1
d2
file2的:
header
d3
d4
然后合并的文件应该是
输出文件:
header
d1
d2
d3
d4
请注意,我们正在跳过第二个文件中的标题。我使用Guava在Java中编写了以下代码。
LinkedList<InputSupplier<BufferedReader>> listOfSuppliers =
new LinkedList<InputSupplier<BufferedReader>>();
boolean firstFile = true;
for (Path path : inputPaths) {
InputSupplier<BufferedReader> reader = newBufferedReaderSupplier(fs.open(path));
if (!firstFile) {
String ignored = reader.getInput().readLine();
LOGGER.info("Ignored header from the second file " + ignored);
}
listOfSuppliers.add(reader);
firstFile = false;
}
InputSupplier<Reader> combined = CharStreams.join(listOfSuppliers);
OutputSupplier<OutputStreamWriter> outputStream
= Files.newWriterSupplier(output, Charsets.UTF_8, false);
CharStreams.copy(combined, outputStream);
此代码的问题在于,当我们跳过标题时,输出文件没有来自第二个文件的内容。我认为BufferedReader正在做一些导致整个文件被忽略的事情。
可以知道如何解决这个问题吗?
答案 0 :(得分:2)
我害怕,这一切都错了。来自InputSupplier.getInput()
javadoc:
与Iterable#iterator类似,可以重复调用此方法以获取到同一底层资源的独立通道。
这与您在
中所做的相反String ignored = reader.getInput().readLine();
我猜,你的InputSupplier并没有遵守合同。如果确实如此,上述行将是无操作。此外,它会使溪流畅通。 1
您从未说过您的文件很大,所以通过Files.readLines
读取所有文件,手动删除除第一个之外的所有标题行,并且连接是恕我直言的方式。
如果您发现效率低下,请注意最耗时的部分可能是char和back转换的字节。使用UTF-8(以及许多其他编码),跳过第一行可以通过InputStream
轻松完成(请注意BufferedReader
会考虑任何&#34; \ r&#34;,&#34 ; \ n&#34;或&#34; \ r \ n&#34;是换行符)。但要注意root of all evil!
1 虽然供应商的设计是为了防止资源泄漏,但他们没有任何魔力来实现它。它在Byte / CharStreams方法中的使用可以确保一切都被关闭。