0

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

假设我们有两个文件 - file1 和 file 2,内容如下

文件1:

header
d1
d2

文件2:

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

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

4

1 回答 1

2

恐怕,一切都错了。从InputSupplier.getInput()javadoc:

与 Iterable#iterator 一样,可以重复调用此方法以获取到相同底层资源的独立通道。

这与你所做的相反

String ignored = reader.getInput().readLine();

我猜,您的 InputSupplier 不遵守合同。如果是这样,上面的行将是无操作的。此外,它会使流保持打开状态。1

您从未说过您的文件很大,因此通过 阅读所有文件Files.readLines,手动从除第一个之外的所有文件中删除标题行,并且连接是恕我直言的方法。


如果您发现它效率低下,请注意最耗时的部分可能是字节到字符和反向转换。使用 UTF-8(和许多其他编码),跳过第一行可以用 an 轻松完成InputStream(注意,BufferedReader将 "\r"、"\n" 或 "\r\n" 中的任何一个视为换行符) . 但要提防万恶之源


1虽然供应商的设计目的是为了防止资源泄漏,但他们没有实现它的魔法。它们在 Byte/CharStreams 方法中的使用确保了一切都被关闭。

于 2013-09-30T03:33:29.560 回答