Guava +合并多个文件并跳过重复的标题

时间:2013-09-30 01:44:49

标签: java file guava

我正在努力实现以下目标。

假设我们有两个文件 - 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正在做一些导致整个文件被忽略的事情。

可以知道如何解决这个问题吗?

1 个答案:

答案 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方法中的使用可以确保一切都被关闭。