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.
3 Réponses :
Problème: vous lisez deux fois en boucle while.
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:
Ne rendez pas la boucle while si complexe.
Pas besoin d'utiliser un compteur booléen séparé dans la boucle while.
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()); }
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.
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 } }
Ce ne sont pas des données | -delimitées. Ce sont des données sérialisées. Lisez la question.
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(); } }
On vous a donné cette solution. «Je l'ai résolu» est une fausse affirmation. Ne déchirez pas votre crédibilité.
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 attraperEOFException
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.