2010-10-19 29 views
2

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é?

+0

Regardez comme votre enveloppé à la fin de la mémoire. –

Répondre

0

Je ne vois rien de mal à cela. Êtes-vous sûr de la valeur de r.position avant le dernier saut? À moins qu'il y ait un bogue sous-jacent dans les flux JDK ou si vous avez plusieurs threads multiples à l'aide du Reader, la seule possibilité que je puisse deviner est que quelque chose modifie incorrectement la valeur de position lorsque vous lisez vos champs.

+0

Salut, merci pour votre réponse. La valeur 'r.position' est très bien, le problème est avec la position * effective * dans un fichier de données - Java décide en quelque sorte de se déplacer * en arrière * dans un fichier vers une position arbitraire. – Linas

+0

Je comprends. Mais puisque vous n'avez pas fourni le code pour vos méthodes readID, readName, etc., le seul endroit restant pour l'erreur (à part un bogue de bas niveau) semble être dans ces méthodes ou la valeur de r.position. Considérez la conséquence si l'une des méthodes readXXX met par inadvertance le r.valeur de position incorrecte par une sorte d'erreur de débordement, ou si elles se sont déclenchées une recherche incorrecte eux-mêmes. Le dernier appel à sauter pourrait alors être faux alors que le premier ne l'était pas. C'est juste une supposition parce que je ne peux penser à rien d'autre que cela pourrait être. – kaliatech