IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Entrée/Sortie Java Discussion :

Lecture d'un fichier (String) : StreamCorruptedException sur le 2ème élément


Sujet :

Entrée/Sortie Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Juin 2007
    Messages
    122
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 122
    Par défaut Lecture d'un fichier (String) : StreamCorruptedException sur le 2ème élément
    Bonjour,
    Lors du démarrage d'une application web sous Tomcat, il y a écriture d'une ligne dans le fichier system.txt avec la méthode suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     ...  
    File systemFile = new File(pathfile);
    ....
     public static void setDate() {
            SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy 'at' HH:mm:ss");
            Date date = new Date();
            String st;        
            try {
                ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream (systemFile,true));
                st = "restart : "  + sdf.format(date) + "\n";
                oos.writeUTF(st);
                oos.close();
            } catch (FileNotFoundException e){
                log.debug("setDate() : FileNotFoundException = " + e);            
            } catch (IOException e) {
                log.debug("setDate() : IOException = " + e);
            }
        }
    Le fichier peut être consulté dans un navigateur par l'administrateur de l'application. La lecture de ce fichier s'effectue avec la méthode suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    ..
        private static final Log log = LogFactory.getLog(SystemStart.class);
        private static FileInputStream fis = null;
        private static ObjectInputStream ois = null;
        private static Vector vect;
    ...
        public static Vector readSystemFile() {
     
            String st = "";
     
            vect = new Vector();
            try {
                fis = new FileInputStream (new File("pathfile"));
                ois = new ObjectInputStream (fis);            
            }
            catch (FileNotFoundException ex){
                log.debug("readSystemFile() : FileNotFoundException = " + ex);                
            }
            catch (IOException ex){
                log.debug("readSystemFile() : IOException-1 = " + ex);                            
            }      
            try {
                while(fis.available() > 0) {
                    st = ois.readUTF(); 
                    vect.add(st);
                    log.debug("readSystemFile() : st = " + st);
                }    
            }
            catch (IOException ex){
                log.debug("readSystemFile() : IOException-2 = " + ex); 
            }
     
            return vect;
        }
    Si la lecture de la 1ère ligne/string [st = ois.readUTF()] est correcte, j'ai l'exception suivante lors de la lecture du 2ème élément :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    readSystemFile() : IOException-2 = java.io.StreamCorruptedException: invalid type code: AC
    Si au niveau du système je visualise le fichier créé :
    cat /home/cabosse/services/system.txt
    ’w!restart : 20/12/16 at 10:43:47
    ’w!restart : 20/12/16 at 10:46:29
    ’w!restart : 20/12/16 at 10:50:17
    Je constate la présence de 4 caractères bizarres en début de ligne; ces caractères n'apparaissent pas lors de la visu de la 1ère ligne dans le navigateur pas plus que dans le fichier de log [log.debug("readSystemFile() : st = " + st);] : sans doute du à l'encodage UTF.

    Dans une autre partie de l'application, j'utilise le même principe pour l'écriture/lecture de fichier, mais dans ce cas sur des objets encapsulant 4 String, et j'ai toujours cette exception sur la lecture du 2ème objet. Je dois donc faire une erreur sur le principe employé!
    Des pistes ... des idées à explorer?

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Billets dans le blog
    2
    Par défaut
    Salut,

    ObjectOuputStream sert à créer des fichiers de données structurés. Il y a un header qui commence chaque fichier (écrit par la méthode writeStreamHeader()). Comme tu travailles en mode append, tu te retrouves avec plusieurs fichiers collés les uns aux autres, mais il ne peuvent être lus avec un seul ObjectInputStream qui lui s'attend à avoir un header au début et après uniquement des blocs de données, et pas des headers en plein milieu.

    Pourquoi utiliser un fichier structuré pour lui donner une extension txt et n'écrire que du texte dedans ? Et surtout l'afficher ensuite comme un log. Pourquoi ne pas utiliser une API de logging ? Ou un simple fichier texte (un BufferedWriter ou un PrintWriter) ?

    Avec ObjectOutputStream/InputObjectStream, il va te falloir bidouiller :
    1. soit par extension, en redéfinissant writeStreamHeader, pour que le header ne soit pas écrit (sauf la première fois, quand le fichier est vide), et encore la lecture risque d'être coton (ce n'est pas avec available qu'il faut boucler (ce n'est pas parce que le tampon est vide que le fichier est complètement lu, rien ne le garantit en tout cas) - available() sert juste à connaitre le nombre d'octets qu'on peut lire sans bloquer le thread).
    2. soit éventuellement, en enchainant plusieurs InputObjectStream sur un unique InputStream : j'ai jamais essayé, mais je suppose que ça doit pouvoir fonctionner. Pour savoir combien de lecture il faudra enchaîner, il faudra procéder en lazy (en laissant planter la lecture), puisque pour savoir s'il y a quelque chose à lire il faut le lire, donc le consommer.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    Membre confirmé
    Inscrit en
    Juin 2007
    Messages
    122
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 122
    Par défaut
    Merci pour la réponse et les précisions.

    Effectivement, je n'avais pas considéré le rôle de writeStreamHeader(), et je me retrouve avec un assemblage de poupées russes.
    Concernant le fichier system.txt, il aurait pu être traité comme un fichier de logs ( ce qu'il est réellement), mais je l'ai pris comme exemple le plus simple des divers fichiers que j'avais a traiter et auxquels je voulais appliquer une procédure générique.

    Donc partant du fait que ObjectInputStream et ObjectOutputStream ne sont pas les plus appropriés, je vais poser le problème dans sa globalité.
    J'ai 3 classes (Coefficients, Commandes, et une 3ème non finalisée) sur le modèle suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    String identifiant;
    string, int, boolean, float;
    getters/setters
    Chaque classe va différer sur le nombre de string, int, float, boolean.

    J'ai donc 3 fichiers (coefficients, commandes, ... ) qui vont recevoir les objets lors de l'instanciation de ces classes (d'ou l'utilisation de append()).
    Pour la lecture, j'ai besoin de récupérer soit un des objets du fichier (lecture séquentielle et accès identifiant), soit le dernier objet du fichier.

    J'ai un dernier cas de fichier qui concerne des objets de classe1 et de classe2 : ce fichier a une structure de "blocs" qui sont construits comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    {obj-class1, obj-class1, obj-class2, obj-class2, obj-class2, obj-class2}
    Il y a donc écriture de 6 objets consécutifs.
    Dans ce cas je dois faire une lecture modulo 6, et lorsque j'ai récupéré un bloc effectuer un traitement adéquat.

    Partant de ces considérations, j'aimerais savoir quelles sont les classes de java.io qui sont le plus à même de répondre à mes besoins.

    Citation Envoyé par joel.drigo
    Avec ObjectOutputStream/InputObjectStream, il va te falloir bidouiller :
    Pas terrible : je vais avoir l'impression de revenir au langage C !!

  4. #4
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Je vois personellement plusieurs options possibles:

    ObjectOutputStream: tu va devoir relire tout le fichier, stocker tout en mémoire, ajouter le nouvel élément dans la structure en mémoire, tout réécrire dans le fichier. On fait mieux coté performances...
    Fichier à la main: beaucoup de bidouilles pour accéder aux données aux bons endroit. On peux un peu simplifier en stockant les données dans une structure type json
    Base de donneés: ben c'est typiquement ce que tu fais là

    Vu ce que tu veux faire, moi je n'écrirait pas ça dans des fichiers mais dans une base de données. Une table par objet et c'est réglé. Avec un fichier plat, tu va toujours galérer à tout scanner pour arriver à trouver le début de ton enregistrement. Il existe des bases de données embarquées comme h2 qui font très bien le boulot en java. Ensuite pour la transformation object => table, tu peux passer par du jpa, fait ça à la main, voir t'orienter vers des trucs comme objectdb ou apache jdo.

Discussions similaires

  1. Réponses: 2
    Dernier message: 10/10/2006, 09h33
  2. [struts]lecture d'un fichier en locale sur un serveur:
    Par dasmadja dans le forum Struts 1
    Réponses: 2
    Dernier message: 18/09/2006, 13h37
  3. Lecture d'un fichier sur le web (http)
    Par omeya4 dans le forum C++
    Réponses: 3
    Dernier message: 12/06/2006, 21h32
  4. Lecture d'un fichier Excel uniquement sur un seul poste
    Par loutsky dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 24/05/2006, 08h09
  5. Réponses: 6
    Dernier message: 23/02/2006, 12h09

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo