0

次のコードが「öäüß」を変更するのはなぜですか? (大きなファイルを複数の小さなファイルに分割するために使用しています...)

InputStream is = new BufferedInputStream(new FileInputStream(file));
File newFile;
BufferedWriter bw;
newFile = new File(filePathBase + "." + String.valueOf(files.size() + 1) + fileExtension);
files.add(newFile);
bw = new BufferedWriter(new FileWriter(newFile));
try {
    byte[] c = new byte[1024];
    int lineCount = 0;
    int readChars = 0;
    while ( ( readChars = is.read(c) ) != -1 )
        for ( int i=0; i<readChars; i++ ) {
            bw.write(c[i]);
            if ( c[i] == '\n' )
                if ( ++lineCount % linesPerFile == 0 ) {
                    bw.close();
                    newFile = new File(filePathBase + "." + String.valueOf(files.size() + 1) + fileExtension);
                    files.add(newFile);
                    bw = new BufferedWriter(new FileWriter(newFile));
                }
        }
} finally {
    bw.close();
    is.close();
}

文字エンコーディングについての私の理解は、各バイトを同じに保つ限り、すべてが同じままであるべきだということです。このコードがバイトを変更するのはなぜですか?

事前にたくさんありがとう〜

==================== ソリューション ====================

@meritonとFileWriter@Jonathan Rosenne に感謝します。BufferedOutputStreamただし、すべてを に変更するだけでBufferedOutputStreamは不十分です。遅すぎるためです。ファイルの分割とコピーのコードを改善して、より大きな読み取り配列サイズを含めるようにし、write()必要な場合にのみ...

File newFile = new File(filePathBase + "." + String.valueOf(files.size() + 1) + fileExtension);
files.add(newFile);
InputStream iS = new BufferedInputStream(new FileInputStream(file));
OutputStream oS = new FileOutputStream(newFile); // BufferedOutputStream wrapper toooo slow!
try {
    byte[] c;
    if ( linesPerFile > 65536 )
        c = new byte[65536];
    else
        c = new byte[1024];
    int lineCount = 0;
    int readChars = 0;
    while ( ( readChars = iS.read(c) ) != -1 ) {
        int from = 0;
        for ( int idx=0; idx<readChars; idx++ )
            if ( c[idx] == '\n' && ++lineCount % linesPerFile == 0 ) {
                oS.write(c, from, idx+1 - from);
                oS.close();
                from = idx+1;
                newFile = new File(filePathBase + "." + String.valueOf(files.size() + 1) + fileExtension);
                files.add(newFile);
                oS = new FileOutputStream(newFile);
            }
        oS.write(c, from, readChars - from);
    }
} finally {
    iS.close();
    oS.close();
}
4

3 に答える 3

4

InputStream はバイトを読み取り、OutputStream はバイトを書き込みます。Reader は文字を読み取り、Writer は文字を書き込みます。

InputStream で読み取り、FileWriter で書き込みます。つまり、バイトを読み取りますが、文字を書き込みます。具体的には、

bw.write(c[i]); 

メソッドを呼び出します

public void write(int c) throws IOException

そのJavadocは次のように述べています。

1 文字を書き込みます。書き込まれる文字は、指定された整数値の下位 16 ビットに含まれます。上位 16 ビットは無視されます。

つまり、バイトは暗黙的に int に変換され、Unicode コード ポイントとして再解釈され、プラットフォームのデフォルト エンコーディングを使用してファイルに書き込まれます (FileWriter が使用するエンコーディングを指定していないため)。

于 2013-10-26T19:27:51.090 に答える
1

バイトを読み取り、文字を書き込んでいます。行 bw.write(c[i]); は各バイトが文字であると想定していますが、入力ファイルでは必ずしもそうではなく、使用されたエンコーディングに依存します。UTF-8 などのエンコーディングでは、1 文字あたり 2 バイト以上を使用する場合があり、各バイトを個別に変換しています。たとえば、UTF-8 では、ö は 2 バイト、16 進数の c3 b6 としてエンコードされます。それらを個別に処理すると、最初の文字が Ã として表示される場合があります。

于 2013-10-26T19:42:38.160 に答える
0

while条件をデバッグしてみてください。( readChars = is.read(c) ) != -1このため、無限ループに陥り、bw.close();呼び出されず、ファイルがまだ読み取りモードになっているため、同時に操作を実行しようとするとファイルが破損し、望ましくない結果が得られます。

于 2013-10-26T19:44:36.183 に答える