2010-07-24 3 views
4

J'écris un format d'archive personnalisé en JAVA (J2ME pour être précis). L'archiveur fonctionne bien, mais j'ai peu de problèmes avec la désarchivage.Java DataInputStream.readUTF et nombre d'octets lus

Comment puis-je savoir combien d'octets ont été lus lors de la lecture d'une chaîne UTF8 avec la méthode readUTF? Je sais que les deux premiers octets d'une chaîne enregistrée en utilisant writeUTF sont une valeur courte de la longueur de la chaîne, mais j'aimerais une meilleure solution.

Ou existe-t-il un moyen de connaître le nombre d'octets restants jusqu'à la fin de DataInputStream (la méthode available ne semble pas renvoyer de valeurs significatives). Le flux a été ouvert par une FileConnection, c'est-à-dire FileConnection.openDataInputStream.

Merci les gars!

Répondre

4

Je ne vois pas de moyen d'y parvenir en utilisant directement l'API CLDC. Une solution simple, cependant, serait de rouler votre propre "CountingInputStream" qui étend InputStream et compte le nombre d'octets lus. Vous auriez simplement besoin de surcharger les trois méthodes de lecture.

La taille du fichier est disponible via FileConnection.

+0

Je connais le 'fileSize()'. Je suis d'accord sur 'CountingInputStream', mais cela semble moche (au moins pour moi). –

+0

Je vois ce que vous voulez dire, mais je ne pense pas que ce soit si moche. Une telle classe est assez utile et certainement réutilisable, même dans d'autres situations que pour FileConnections. Et même si c'est légèrement moche, c'est encapsulé et rangé dans une petite classe. – aioobe

1

La méthode available() renvoie ce qui est documenté pour renvoyer, ce qui n'est pas ce que vous essayez de l'utiliser. Voir le Javadoc.

Vous pouvez écrire votre propre octet FilterInputStream et le placer entre le flux d'entrée de données et le flux sous-jacent. Mais vous devrez obtenir le nombre total d'octets de la source à partir de la source, cette information n'est disponible pour aucun flux d'entrée.

+0

AFAIK, FilterInputStream est pas disponible sur le profil MID. – aioobe

+0

Peu importe, vous pouvez tout écrire vous-même tout aussi facilement. – EJP

+0

Avez-vous vraiment besoin de ces octets? Vous obtiendrez des indications EOF quand vous arriverez à la fin du flux ... – EJP

2

Cela peut être un peu en retard, mais je l'ai récemment travaillé sur quelque chose où je devais connaître la quantité d'octets qui ont été lecture, par opposition à combien sont gauche à lire, comme cette question demande. Mais vous pouvez déduire ce nombre de la solution que j'ai. Je voulais connaître la quantité d'octets lus pour pouvoir suivre la progression du téléchargement (au cas où cela prendrait du temps).

Initialement, j'utilisais simplement DataInputStream # readFully() pour télécharger les fichiers.

buffer = new byte[length]; 
in.readFully(buffer); 

Mais parfois, je suis resté en attente pour aller de 50 - 60 secondes pour que le téléchargement se termine, en fonction de la taille. Je voulais obtenir des mises à jour en temps réel sur la façon dont les choses se passaient, donc j'ai changé pour utiliser uniquement le DataInputStream # read (octet [] b, int off, int len). Donc, il y a là System.out à la fin me disant chaque fois que je l'ai sauté un point de pourcentage:

buffer = new byte[length]; 
int totalRead = 0; 
int percentage = 0; 

while (totalRead < length) 
{ 
    int bytesRead = in.read(buffer, totalRead, (length - totalRead)); 

    if (bytesRead < 0) 
     throw new IOException("Data stream ended prematurely"); 

    totalRead += bytesRead; 
    double progress = ((totalRead*1.0)/length) * 100; 
    if ((int)progress > percentage) 
    { 
     percentage = (int)progress; 
     System.out.println("Downloading: " + percentage + "%"); 
    } 
} 

Pour savoir combien d'octets restent à lire, quelques modifications mineures peuvent être apportées au dernier exemple. Avoir une variable de suivi à la place de mon pourcentage, par exemple:

buffer = new byte[length]; 
int totalRead = 0; 
int bytesLeft= 0; 

while (totalRead < length) 
{ 
    bytesLeft = length - totalRead; 
    int bytesRead = in.read(buffer, totalRead, bytesLeft); 

    if (bytesRead < 0) 
     throw new IOException("Data stream ended prematurely"); 

    totalRead += bytesRead; 
    System.out.println("Bytes left to read: " + bytesLeft); 
} 
0

C'est une question assez vieux, mais je vais poster ma solution car cela pourrait aider quelqu'un:

Il est en fait un CountingInputStream pratique wrapper dans Apache Commons IO http://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/input/CountingInputStream.html

il est dérivé de java.io.FilterInputStream vous pouvez donc essentiellement l'enrouler autour de tout flux d'entrée standard.

Dans votre cas, en supposant DataInputStream variables désigne le flux que vous travaillez avec:

CountingInputStream counter = new CountingInputStream(dataInputStream); 
dataInputStream = new DataInputStream(counter); 
... 
counter.getByteCount() //this returns num of bytes read from dataInputStream 
Questions connexes