0

私は以下を達成しようとしています。

次の内容の file1 と file 2 という 2 つのファイルがあるとします。

ファイル1:

header
d1
d2

ファイル2:

header
d3
d4

次に、マージされたファイルは

出力ファイル:

header
d1
d2
d3
d4

2 番目のファイルからヘッダーをスキップしていることに注意してください。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);

このコードの問題は、ヘッダーをスキップすると、出力ファイルに 2 番目のファイルの内容がないことです。BufferedReader がファイル全体を無視するようなことをしていると思います。

これを修正する方法を考えられますか?

4

1 に答える 1

2

I'm afraid, it's all wrong. From the InputSupplier.getInput() javadoc:

Like Iterable#iterator, this method may be called repeatedly to get independent channels to the same underlying resource.

This is the opposite of what you did in

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

I guess, your InputSupplier doesn't obey the contract. If it did, the above line would be a no-op. Moreover, it would leave the stream open.1

You never said that your files are huge, so reading all of them via Files.readLines, manually removing the header line from all but the first, and concatenating is IMHO the way to go.


In case you find it inefficient, note that the most time-consuming part is probably the byte to char and back conversion. With UTF-8 (and many other encodings), skipping the first line can be done trivially with an InputStream (note that BufferedReader considers any of "\r", "\n", or "\r\n" to be a line break). But beware of the root of all evil!


1 While the suppliers were designed in order to prevent resource leaks, they have no magic achieving it. It's their use in the Byte/CharStreams methods which assures everything gets closed.

于 2013-09-30T03:33:29.560 に答える