2

私はいくつかのファイル読み取り書き込みタスクで遊ぶ必要があるプロジェクトに取り組んでいます。ファイルから一度に 8 バイトを読み取り、そのブロックに対していくつかの操作を実行してから、そのブロックを 2 番目のファイルに書き込み、最初のファイルが毎回 8 バイトのチャンクで完全に読み取られるまでサイクルを繰り返し、操作後にデータを処理する必要があります。 2番目に追加/追加する必要があります。しかし、そうする中で、私はいくつかの問題に直面しています。以下は私がしようとしているものです:

private File readFromFile1(File file1) {

    int offset = 0;
    long message= 0;

    try {
        FileInputStream fis = new FileInputStream(file1);
        byte[] data = new byte[8];
        file2 = new File("file2.txt");
        FileOutputStream fos = new FileOutputStream(file2.getAbsolutePath(), true);
        DataOutputStream dos = new DataOutputStream(fos);

        while(fis.read(data, offset, 8) != -1)
        {
            message = someOperation(data); // operation according to business logic
            dos.writeLong(message);
        }
        fos.close();
        dos.close();
        fis.close(); 
    } catch (IOException e) {
        System.out.println("Some error occurred while reading from File:" + e);
    }
    return file2;
}

この方法では、目的の出力が得られません。どんな助けでも大歓迎です。

4

2 に答える 2

0

次のコードを検討してください。

private File readFromFile1(File file1) {

    int offset = 0;
    long message = 0;
    File file2 = null;

    try {
        FileInputStream fis = new FileInputStream(file1);

        byte[] data = new byte[8]; //Read buffer
        byte[] tmpbuf = new byte[8]; //Temporary chunk buffer

        file2 = new File("file2.txt");
        FileOutputStream fos = new FileOutputStream(file2.getAbsolutePath(), true);
        DataOutputStream dos = new DataOutputStream(fos);

        int readcnt; //Read count
        int chunk; //Chunk size to write to tmpbuf

        while ((readcnt = fis.read(data, 0, 8)) != -1) {

            //// POINT A ////
            //Skip chunking system if an 8 byte octet is read directly.
            if(readcnt == 8 && offset == 0){
                message = someOperation(tmpbuf); // operation according to business logic
                dos.writeLong(message);
                continue;
            }

            //// POINT B ////
            chunk = Math.min(tmpbuf.length - offset, readcnt); //Determine how much to add to the temp buf.

            System.arraycopy(data, 0, tmpbuf, offset, chunk); //Copy bytes to temp buf

            offset = offset + chunk; //Sets the offset to temp buf

            if (offset == 8) {
                message = someOperation(tmpbuf); // operation according to business logic
                dos.writeLong(message);

                if (chunk < readcnt) {
                    System.arraycopy(data, chunk, tmpbuf, 0, readcnt - chunk);
                    offset = readcnt - chunk;
                } else {
                    offset = 0;
                }
            }
        }

        //// POINT C ////
        //Process remaining bytes here...
        //message = foo(tmpbuf);
        //dos.writeLong(message);

        fos.close();
        dos.close();
        fis.close(); 
    } catch (IOException e) {
        System.out.println("Some error occurred while reading from File:" + e);
    }

    return file2;
}

このコードの抜粋で、私がしたことは次のとおりです。

  1. 読み取りコードを変更して、read() メソッドから実際に読み取ったバイト数を含めます (readcnt と記述)。
  2. バイト チャンク システムを追加しました (チャンク バッファに少なくとも 8 バイトが存在するまで処理は行われません)。
  3. 最終バイト (8 バイトのオクテットを構成しない) を個別に処理できます。

コードからわかるように、読み取られるデータは、少なくとも 8 バイトが使用可能になるまで、最初にチャンキング バッファー (tmpbuf で示されます) に格納されます。これは、8 バイトが常に使用可能であるとは限らない場合にのみ発生します (8 バイトが直接使用可能で、何もチャンクされていない場合は、直接処理します。コードの「ポイント A」を参照してください)。これは、過剰な配列のコピーを防ぐための最適化の形式として行われます。

チャンキング システムは、値が 8 に達するまでバイトが tmpbuf に書き込まれるたびに増加するオフセットを使用します (「チャンク」の割り当てで使用される Math.min() メソッドが値を制限するため、それを超えることはありません)。オフセット == 8 で、処理コードの実行に進みます。

その特定の読み取りで実際に処理されたよりも多くのバイトが生成された場合は、オフセットを適切に設定しながら、最初から tmpbuf への書き込みを続行します。それ以外の場合は、オフセットを 0 に設定します。

サイクルを繰り返します。

コードは、実際に書き込まれた量を示すオフセット変数を使用して、配列 tmpbuf のオクテットに収まらないデータの最後の数バイトを残します。このデータは、ポイント C で個別に処理できます。

本来よりもはるかに複雑に思えますが、おそらくより良い解決策があります (おそらく既存の Java ライブラリ メソッドを使用します)。これが理解できるほど明確であることを願っています。

于 2013-10-17T15:32:30.513 に答える