La bonne:Comportement étrange FileInputStream/DataFileInputStream: seek() uant aux positions impaires
J'ai donc ce fichier de données binaires (taille - exactement 640631 octets), et je suis en train de faire Java lire il.
J'ai deux classes interchangeables implémentées en tant que couches pour lire ces données. L'un d'eux utilise RandomAccessFile
, qui fonctionne très bien et tout.
La mauvaise:
Un autre (celui de cette question est surtout de) tente d'utiliser FileInputStream
et DataInputStream
de sorte que les mêmes données pourraient être (au moins théoriquement) être lu sur MIDP 2.0 (CLDC 1.1) Configuration Java (qui n'a pas RandomAccessFile
).
Dans cette classe, j'ouvrir le fichier de données comme ceci:
FileInputStream res = new FileInputStream(new File(filename));
h = new DataInputStream(res);
... et mettre en œuvre seek()
/skip()
comme celui-ci (position
est une long
qui prend note d'une position actuelle dans un fichier):
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);
}
}
et
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;
}
Le laid:
Le problème avec la deuxième classe (la FileInputStream
/DataInputStream
un) est que parfois il décide de rétablir la position de fichier à un endroit étrange dans un fichier :) Cela se produit à la fois quand je lance ceci sur J2SE (un ordinateur) et J2ME (un téléphone mobile). Voici un exemple de l'utilisation réelle de cette classe de lecteur et d'un bug qui se produit:
// 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
j'ai pu déterminer que lorsqu'on lui a demandé de sauter un autre 37 octets, Java positionné le pointeur de fichier à octet 477 dès le début ou fichier à la place.
"Fraîchement" (juste après l'ouverture d'un fichier) cherchant une position 189710 (et au-delà) fonctionne correctement. Cependant, la réouverture d'un fichier chaque fois que j'ai besoin d'un seek()
est juste terriblement lent, surtout sur un téléphone mobile.
Que s'est-il passé?
Regardez comme votre enveloppé à la fin de la mémoire. –