0

「\n\n」によって 2 つの部分に分割されたファイルがあります。最初の部分は長すぎない文字列で、2 番目の部分はバイト配列で、かなり長くなる可能性があります。

次のようにファイルを読み込もうとしています:

    byte[] result;
    try (final FileInputStream fis = new FileInputStream(file)) {

        final InputStreamReader isr = new InputStreamReader(fis);
        final BufferedReader reader = new BufferedReader(isr);

        String line;
        // reading until \n\n
        while (!(line = reader.readLine()).trim().isEmpty()){
            // processing the line
        }

        // copying the rest of the byte array
        result = IOUtils.toByteArray(reader);
        reader.close();
    }

結果の配列はあるべきサイズですが、その内容は壊れています。またはでtoByteArray直接使用しようとすると、結果の内容が空になります。fisisr

ファイルの残りの部分を正しく効率的に読み取るにはどうすればよいですか?

ありがとう!

4

3 に答える 3

1

または、ファイルをバイト配列に読み込み、\n\n 位置を見つけて、配列を行とバイトに分割することもできます

    byte[] a = Files.readAllBytes(Paths.get("file"));
    String line = "";
    byte[] result = a;
    for (int i = 0; i < a.length - 1; i++) {
        if (a[i] == '\n' && a[i + 1] == '\n') {
            line = new String(a, 0, i);
            int len = a.length - i - 1;
            result = new byte[len];
            System.arraycopy(a, i + 1, result, 0, len);
            break;
        }
    }
于 2013-02-27T05:55:31.497 に答える
1

コンテンツが壊れている理由は、IOUtils.toByteArray(...)関数がデータをデフォルトの文字エンコーディングの文字列として読み取るためです。つまり、デフォルトのエンコーディングで規定されているロジックを使用して、8 ビットのバイナリ値をテキスト文字に変換します。これにより、通常、多くのバイナリ値が破損します。

文字セットがどの程度正確に実装されているかに応じて、これが機能する可能性がわずかにあります。

result = IOUtils.toByteArray(reader, "ISO-8859-1");

ISO-8859-1 は、1 文字につき 1 バイトのみを使用します。すべての文字値が定義されているわけではありませんが、多くの実装ではとにかくそれらを渡します。多分あなたはそれで幸運です。

new String(bytes)しかし、はるかにクリーンな解決策は、バイナリ データを最後に文字列として読み取ってから変換し直すのではなく、最初に文字列をバイナリ データとして読み取ってからテキストに変換することです。

ただし、これは、パフォーマンスのために独自のバージョンの BufferedReader を実装する必要があることを意味する場合があります。

標準の BufferedReader のソース コードは、明らかな Google 検索で見つけることができます。たとえば、次のようになります。

http://www.docjar.com/html/api/java/io/BufferedReader.java.html

少し長いですが、概念的に理解するのは難しくありませんので、参考にしていただければ幸いです。

于 2013-02-27T05:28:37.987 に答える
0

すべてのコメントに感謝します - 最終的な実装は次のように行われました:

    try (final FileInputStream fis = new FileInputStream(file)) {

        ByteBuffer buffer = ByteBuffer.allocate(64);

        boolean wasLast = false;
        String headerValue = null, headerKey = null;
        byte[] result = null;

        while (true) {
            byte current = (byte) fis.read();
            if (current == '\n') {
                if (wasLast) {
                    // this is \n\n
                    break;
                } else {
                    // just a new line in header
                    wasLast = true;
                    headerValue = new String(buffer.array(), 0, buffer.position()));
                    buffer.clear();
                }
            } else if (current == '\t') {
                // headerKey\theaderValue\n
                headerKey = new String(buffer.array(), 0, buffer.position());
                buffer.clear();
            } else {
                buffer.put(current);
                wasLast = false;
            }
        }
        // reading the rest
        result = IOUtils.toByteArray(fis);
    }
于 2013-02-27T07:04:04.867 に答える