web-dev-qa-db-fra.com

EOFException - comment gérer?

Je suis un programmeur débutant en Java qui suit les tutoriels Java .

J'utilise un programme Java simple à partir de Tutoriels Java 's Page Flux de données , et au moment de l'exécution, il affiche toujours EOFException. Je me demandais si c'était normal, car le lecteur devait arriver à la fin du fichier.

import Java.io.*;

public class DataStreams {
    static final String dataFile = "F://Java//DataStreams//invoicedata.txt";

    static final double[] prices = { 19.99, 9.99, 15.99, 3.99, 4.99 };
    static final int[] units = { 12, 8, 13, 29, 50 };
    static final String[] descs = {
        "Java T-shirt",
        "Java Mug",
        "Duke Juggling Dolls",
        "Java Pin",
        "Java Key Chain"
    };
    public static void main(String args[]) {
        try {
            DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dataFile)));

            for (int i = 0; i < prices.length; i ++) {
                out.writeDouble(prices[i]);
                out.writeInt(units[i]);
                out.writeUTF(descs[i]);
            }

            out.close(); 

        } catch(IOException e){
            e.printStackTrace(); // used to be System.err.println();
        }

        double price;
        int unit;
        String desc;
        double total = 0.0;

        try {
            DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(dataFile)));

            while (true) {
                price = in.readDouble();
                unit = in.readInt();
                desc = in.readUTF();
                System.out.format("You ordered %d" + " units of %s at $%.2f%n",
                unit, desc, price);
                total += unit * price;
            }
        } catch(IOException e) {
            e.printStackTrace(); 
        }

        System.out.format("Your total is %f.%n" , total);
    }
}

Cela compile bien, mais le résultat est:

You ordered 12 units of Java T-shirt at $19.99
You ordered 8 units of Java Mug at $9.99
You ordered 13 units of Duke Juggling Dolls at $15.99
You ordered 29 units of Java Pin at $3.99
You ordered 50 units of Java Key Chain at $4.99
Java.io.EOFException
        at Java.io.DataInputStream.readFully(Unknown Source)
        at Java.io.DataInputStream.readLong(Unknown Source)
        at Java.io.DataInputStream.readDouble(Unknown Source)
        at DataStreams.main(DataStreams.Java:39)
Your total is 892.880000.

À partir de Tutoriels Java 's Page Flux de données , il est indiqué:

Notez que DataStreams détecte une condition de fin de fichier en interceptant EOFException , au lieu de rechercher une valeur de retour non valide. Toutes les implémentations de méthodes DataInput utilisent EOFException au lieu de valeurs de retour.

Donc, cela signifie-t-il que capturer EOFException est normal, donc le capturer et ne pas le gérer est correct, ce qui signifie que la fin du fichier est atteinte?

Si cela signifie que je devrais m'en occuper, veuillez me conseiller sur la façon de le faire.

MODIFIER

Parmi les suggestions, je l'ai corrigé en utilisant in.available() > 0 pour la condition de boucle while.

Ou bien, je ne pourrais rien faire pour gérer l'exception, parce que ça va.

18
Jonathan Lam

En lisant le fichier, vous ne terminez pas votre boucle. Donc, il lit toutes les valeurs et correctement jette EOFException à la prochaine itération de la lecture à la ligne ci-dessous:

 price = in.readDouble();

Si vous lisez la documentation, il est écrit:

Jette:

EOFException - si ce flux d'entrée atteint la fin avant la lecture de huit octets.

IOException - le flux a été fermé et le flux d'entrée contenu ne prend pas en charge la lecture après la fermeture, ou une autre erreur d'E/S se produit.

Mettez une condition de terminaison appropriée dans votre boucle while pour résoudre le problème, par exemple. au dessous de:

     while(in.available() > 0)  <--- if there are still bytes to read
20
Yogendra Singh

La meilleure façon de gérer cela serait de terminer votre boucle infinie par une condition appropriée.

Mais puisque vous avez demandé la gestion des exceptions:

Essayez d'utiliser deux prises. Votre EOFException est attendue, il ne semble donc pas y avoir de problème quand cela se produit. Toute autre exception doit être traitée.

...
} catch (EOFException e) {
   // ... this is fine
} catch(IOException e) {
    // handle exception which is not expected
    e.printStackTrace(); 
}
4
Martin Seeler

Vous pouvez également écrire le nombre d’éléments d’abord (en-tête) en utilisant:

out.writeInt(prices.length);

Lorsque vous lisez le fichier, vous lisez d'abord l'en-tête (nombre d'éléments):

int elementCount = in.readInt();

for (int i = 0; i < elementCount; i++) {
     // read elements
}
2
Katona

Vous pouvez utiliser while(in.available() != 0) au lieu de while(true).

2
akaHuman

Vous attrapez IOException qui attrape également EOFException, car elle est héritée. Si vous regardez l’exemple tiré du tutoriel ils ont souligné que vous devriez attraper EOFException - et c’est ce qu’ils font. Pour résoudre votre problème, EOFException avant IOException:

try
{
    //...
}
catch(EOFException e) {
    //eof - no error in this case
}
catch(IOException e) {
    //something went wrong
    e.printStackTrace(); 
}

À part cela, je n'aime pas le contrôle du flux de données utilisant des exceptions - ce n'est pas l'utilisation prévue des exceptions et donc (à mon avis) un style vraiment mauvais.

0
Jost

Placez votre code dans le bloc catch catch: I.e: 

try{
  if(in.available()!=0){
    // ------
  }
}catch(EOFException eof){
  //
}catch(Exception e){
  //
}
}
0
Sudarshan Nagre

Vous rencontrerez peut-être du code qui lit une InputStream et utilise l'extrait de code while(in.available()>0) pour vérifier la fin du flux plutôt que de rechercher une EOFException (fin du fichier).

Le problème avec cette technique, et la variable Javadoc fait écho à cela, est qu’elle ne vous indique que le nombre de blocs pouvant être lus sans bloquer le prochain appelant. En d'autres termes, il peut return 0 même s'il y a plus d'octets à lire. Par conséquent, la méthode InputStream available() ne doit jamais être utilisée pour vérifier la fin du flux.

Vous devez utiliser while (true) et

catch(EOFException e) {
//This isn't problem
} catch (Other e) {
//This is problem
}
0
Taleh Alqayev