0
votes

Itération avec ObjectInputStream.readObject () à partir d'un fichier .txt

J'ai du mal à lire les données d'objet d'un fichier .txt en utilisant la méthode readObject () d'ObjectInputStream. J'écris plusieurs objets utilisateur dans un .txt pour enregistrer les utilisateurs lorsque le serveur du programme est en panne et que l'écriture fonctionne correctement, bien que lorsque j'essaie de lire les informations, je ne sais pas comment faire une boucle sur / lire la ligne suivante dans le fichier.

public void readObjectFromFile() {
        boolean cont = true;
        User user;

try {
            FileInputStream fileIn = new FileInputStream("files/userlist.txt");
            ObjectInputStream objectIn = new ObjectInputStream(fileIn);


            while(cont){
                Object obj = objectIn.readObject();
                if(obj != null) {
                    registeredUsers.add((User)objectIn.readObject());
                    user = (User)obj;
                    userPasswords.put(user.getUsername(), user.getPassword());
                    System.out.println(user.getUsername());
                }else {
                    cont = false;
                }
            }

        }catch (Exception ex) {
            ex.printStackTrace();

        }
}

public void addUserToDatabase(User user) {
        try(FileOutputStream fos = new FileOutputStream("files/userlist.txt", true);
                ObjectOutputStream oos = new ObjectOutputStream(fos)){
            oos.writeObject(user);
            oos.write('\n');
            oos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Je voudrais lire le fichier ligne par ligne, et stocker les informations de chaque ligne dans un objet utilisateur et les stocker dans les utilisateurs enregistrés -liste.


2 commentaires

readObject () ne renvoie pas null à la fin du flux. Il peut le faire à chaque fois que vous avez écrit un null. Donc s'arrêter à null n'est pas valide. Vous devez attraper EOFException et casser à la place. Les données sérialisées ne sont pas du texte et ne doivent pas être stockées dans un fichier nommé .txt. Il n'y a donc pas non plus de «ligne par ligne». Et n'écrivez pas de nouvelles lignes dans les flux d'objets. Ils n'accomplissent rien.


Et vous ne pouvez pas ajouter à un objet un flux comme ça. La deuxième lecture rencontrera un autre en-tête de flux et barf. Gardez le fichier ouvert.


3 Réponses :


-1
votes

Problème: vous lisez deux fois en boucle while.

  1. Premier appel:
    objectIn.readObject ()
  2. Deuxième appel:
    registeredUsers.add ((Utilisateur) objectIn.readObject () );

N'appelez pas la méthode readObject () deux fois en utilisant la référence qui a déjà été prise.

Autre problème fonctionnel, vous pouvez également corriger les éléments suivants pour améliorer votre code:

  1. Ne rendez pas la boucle while si complexe.

  2. Pas besoin d'utiliser un compteur booléen séparé dans la boucle while.

  3. Il suffit de taper une fois à l'utilisateur et non plusieurs fois (au moment de l'appel readObject () lui-même).

Veuillez vous référer au code suivant:

User user = null;
while((user = (User) objectIn.readObject()) != null){
                registeredUsers.add(user);
                userPasswords.put(user.getUsername(), user.getPassword());
                System.out.println(user.getUsername());
        }


5 commentaires

Merci! Excellente contribution! J'ai changé la boucle while comme vous l'avez suggéré, mais je ne lis toujours que le premier objet du fichier, et je n'ai aucune idée de comment le réparer ... :(


EDIT: J'ai réalisé où se situe mon prochain problème, en écrivant le dans le fichier, j'écris un saut de ligne ('\ n') après chaque writeObject, et quand j'essaye de le lire avec la méthode readObject, il lance une OptionalDataException - toutes les idées de comment puis-je contourner cela?


@RasmusOberg Oui: n'écrivez pas la nouvelle ligne. C'est inutile. Cette boucle while est toujours incorrecte: voir mon commentaire sous votre question.


D'accord, d'abord - n'écrivez pas la nouvelle ligne, ensuite - ne sauvegardez pas le fichier au format .txt? Puis-je le stocker dans un fichier .dat avec? Et dois-je indiquer où un objet s'arrête et un autre commence lors de l'écriture dans le fichier? Merci beaucoup pour votre aide!


@RasmusOberg Vous pouvez le stocker dans le nom de fichier que vous voulez, mais ce n'est pas du texte, donc utiliser .txt est trompeur, surtout pour vous-même, car cela vous a conduit à faire des choses inappropriées comme tester pour null, ajouter une nouvelle ligne,. .. Vous n'avez pas besoin d'indiquer où l'objet s'arrête. Il sait.



-1
votes

Récupérez-vous déjà les données du fichier? J'ai déjà fait cela avec des fichiers délimités par des tuyaux ("|"), donc: value1 | value2 | value3

Vous n'êtes pas sûr de la composition de votre fichier, mais si vous lisez déjà les données, vous pouvez passer aux lignes suivantes et créer de nouveaux objets User comme ceci:

    private List <UserEntry> collectFileContents(InputStream is, String fileName) throws Exception {
    try {
        List <UserEntry> userEntries = new ArrayList <UserEntry>(); 
        String line = "";
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        br.readLine();
        while ((line = br.readLine()) != null) {
            if (line.length() > 0) {
                UserEntry entry = new UserEntry();
                try {
                    String[] lineValues = line.split("\\|",-1);
                    entry.setVal1(lineValues[0]);
                    entry.setVal2(lineValues[1]);
                    //etc..
                    userEntries.add(entry);
                } catch (ArrayIndexOutOfBoundsException  ex) {
                    //error handling here
                    continue;
                }
            }
        }
        return userEntries;
    }catch(Exception ex) {
        //error handling here
    }

}


1 commentaires

Ce ne sont pas des données | -delimitées. Ce sont des données sérialisées. Lisez la question.



0
votes

D'accord, je l'ai résolu!

public void readUsersFromFile() {
        try {
            FileInputStream fileIn = new FileInputStream("files/userlist.dat");
            ObjectInputStream objectIn = new ObjectInputStream(fileIn);
            boolean keepReading = true;
            try {
                while(keepReading) {
                    User user = (User)objectIn.readObject();
                    registeredUsers.add(user);
                    userPasswords.put(user.getUsername(), user.getPassword());
                    System.out.println(user.getUsername());
                    objectIn = new ObjectInputStream(fileIn);

                }
            }catch(EOFException e) {
                keepReading = false;
            }
        }catch (Exception ex) {
            ex.printStackTrace();

        }
    }


1 commentaires

On vous a donné cette solution. «Je l'ai résolu» est une fausse affirmation. Ne déchirez pas votre crédibilité.