2

いいもの:

したがって、このバイナリデータファイル(サイズ-正確に640631バイト)があり、Javaに読み取らせようとしています。

そのデータを読み取るためのレイヤーとして、2つの交換可能なクラスが実装されています。それらの1つはRandomAccessFile、を使用します。

悪い人:

もう1つ(この質問のほとんどが対象)は、MIDP 2.0(CLDC 1.1)Java構成(がない)でまったく同じデータを(少なくとも理論的には)読み取ることができるように使用しようFileInputStreamとします。DataInputStreamRandomAccessFile

そのクラスでは、次のようにデータファイルを開きます。

FileInputStream res = new FileInputStream(new File(filename));
h = new DataInputStream(res);

...そしてseek()/skip()をこのように実装します(これpositionlongファイル内の現在の位置を記録します):

public void seek(long pos) throws java.io.IOException {

    if (! this.isOpen()) {
        throw new java.io.IOException("No file is open");
    }

    if (pos < position) {
        // Seek to the start, then skip some bytes
        this.reset();
        this.skip(pos);
    } else if (pos > position) {
        // skip the remaining bytes until the position
        this.skip(pos - position);
    }
}

public void skip(long bytes) throws java.io.IOException {

    if (! this.isOpen()) {
        throw new java.io.IOException("No file is open");
    }

    long skipped = 0, step = 0;

    do {
        step = h.skipBytes((int)(bytes - skipped));
        if (step < 0) {
            throw new java.io.IOException("skip() failed");
        }
        skipped += step;
    } while (skipped < bytes);

    position += bytes;
}

ぶさいく:

2番目のクラス(FileInputStream/ DataInputStreamone)の問題は、ファイルの位置をファイル内の奇妙な場所にリセットすることがあることです:)これは、J2SE(コンピューター)とJ2ME(携帯電話)の両方で実行した場合に発生します。 。そのリーダークラスの実際の使用法と発生するバグの例を次に示します。

// Open the data file
Reader r = new Reader(filename);

// r.position = 0, actual position in a file = 0

// Skip to where the data block that is needed starts
// (determined by some other code)
r.seek(189248);

// r.position = 189248, actual position in a file = 189248

// Do some reading...
r.readID(); r.readName(); r.readSurname();

// r.position = 189332, actual position in a file = 189332

// Skip some bytes (an unneeded record)
r.skip(288);

// r.position = 189620, actual position in a file = 189620

// Do some more reading...
r.readID(); r.readName(); r.readSurname();

// r.position = 189673, actual position in a file = 189673

// Skip some bytes (an unneeded record)
r.skip(37);

// AAAAND HERE WE GO:
// r.position = 189710, actual position in a file = 477

さらに37バイトをスキップするように求められたときに、Javaがファイルポインタを最初のバイトまたはファイルからバイト477に配置したことを確認できました。

189710(およびそれ以降)の位置を探す「フレッシュ」(ファイルを開いた直後)は正常に機能します。ただし、特に携帯電話では、必要になるたびにファイルを再度開くのがseek()非常に遅くなります。

何が起きたの?

4

1 に答える 1

0

これには何も問題はありません。最後のスキップの前の r.position 値は正ですか? JDK ストリームに根本的なバグがない限り、またはリーダーを使用して複数のスレッドを使用している場合を除き、私が推測できる唯一の可能性は、フィールドを読み取るときに位置の値が誤って変更されていることです。

于 2010-10-19T12:52:50.517 に答える