2013-05-10 3 views
2

Je suis en train de concevoir une application d'écriture manuscrite pour android.Écrire et lire plusieurs objets dans le fichier

Je voudrais écrire des informations (class LogInfo) dans un fichier journal, chaque fois que l'utilisateur appuie sur le bouton Entrée. Après cela, je voudrais lire les informations stockées.

Cela fait partie de ma classe avec une méthode d'écriture personnalisée:

public class LogInfo implements Serializable { 

private static final long serialVersionUID = -5777674941129067422L; 

public static List<Point[][]> strokes; 
public static List<byte[]> codes; 

// Only write and read methods shown 

private void writeObject(ObjectOutputStream stream) throws IOException 
{ 
    stream.defaultWriteObject(); 
    stream.writeInt(strokes.size()); 
    Point[][] pointsArray = null; 
    for (int i = 0; i < strokes.size(); i++) 
    { 
     pointsArray = ((Point[][])strokes.get(i)); 
     stream.writeInt(pointsArray.length); 
     for (int j = 0; j < pointsArray.length; j++) 
     { 
      stream.writeInt(pointsArray[j].length); 
      for (int k = 0; k < pointsArray[j].length; k++) 
      { 
       stream.writeInt(pointsArray[j][k].x); 
       stream.writeInt(pointsArray[j][k].y); 
       //stream.writeObject(elementData[i]); 
      } 
     } 
    } 

    int size = codes.size(); 
    stream.writeInt(size); 
    for (int i = 0; i < size; i++) 
    { 
     stream.write(codes.get(i)); 
    } 
} 

Ceci est la méthode de lecture:

private void readObject(java.io.ObjectInputStream stream) 
    { 
     stream.defaultReadObject(); 
     int strokesSize = stream.readInt(); 
     for (int i = 0; i < strokesSize; i++) 
     { 
      int arrayXSize = stream.readInt(); 
      Point[][] points = new Point[arrayXSize][]; 
      for (int j = 0; j < arrayXSize; j++) 
      { 
       int arrayYSize = stream.readInt(); 
       points[j] = new Point[arrayYSize]; 
       for (int k = 0; k < arrayYSize; k++) 
        points[j][k] = new Point(stream.readInt(), stream.readInt()); 
      } 
      strokes.add(points); 
     } 

     int codesSize = stream.readInt(); 
     for (int i = 0; i < codesSize; i++) 
     { 
      byte[] buffer = new byte[3]; 
      stream.read(buffer, 0, 3); 
      codes.add(buffer); 
     } 
    } 

Il fonctionne bien quand je sauve un seul objet le fichier. Lorsque j'essaie d'enregistrer plus, la lecture ne fonctionne pas (elle lance un StreamCorruptedException). Il lit seulement un objet dans la boucle while!

Dans la classe principale, je viens d'utiliser deux méthodes simples:

// WRITE TO FILE 
logInfo.writeLog(); 

// READ FROM FILE 
ArrayList<LogInfo> logInfoArrayList = logInfo.readLog(); 

définis comme:

public void writeLog() 
{ 
    File file = new File (Environment.getExternalStorageDirectory().getAbsolutePath(), "data.log"); 
    FileOutputStream fos; 
    try { 
     fos = new FileOutputStream(file, true); 
     //fos = openFileOutput(Environment.getExternalStorageDirectory().getAbsolutePath() + "/data.log", Context.MODE_APPEND); 
     ObjectOutputStream os = new ObjectOutputStream(fos); 
     os.writeObject(this); 
     os.close(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

public ArrayList<LogInfo> readLog() 
{ 
    ArrayList<LogInfo> logInfoArray = new ArrayList<LogInfo>(); 

    try{ 
     File file = new File (Environment.getExternalStorageDirectory().getAbsolutePath(), "data.log"); 
     FileInputStream fis = new FileInputStream(file); 
     ObjectInputStream reader = new ObjectInputStream(fis); 

     LogInfo tempLogInfo = new LogInfo(); 
     while((tempLogInfo = (LogInfo)reader.readObject()) != null) 
      logInfoArray.add(tempLogInfo); 
     reader.close(); 
    } catch (Exception e) { 
    //TODO Auto-generated catch block 
    e.printStackTrace(); 
    } 

    return logInfoArray; 
} 

a demandé MISE À JOUR:

//We use this class to not write a header in a file that already exist 
class MyObjectOutputStream extends ObjectOutputStream { 

    public MyObjectOutputStream(OutputStream os) throws IOException { 
     super(os); 
     } 

    @Override 
    protected void writeStreamHeader() {} 
} 
+0

Pourriez-vous poster la pile d'exception trace – gZerone

+0

5 au 10 octobre: ​​56: 40,320: W/System.err (26121): java.io.StreamCorruptedException: Format incorrect: ac 5 au 10 octobre: ​​56: 40,335: W /System.err(26121): \t à java.io.ObjectInputStream.corruptStream (ObjectInputStream.java:701) 05-10 10: 56: 40.340: W/System.err (26121): \t à java.io.ObjectInputStream .readNonPrimitiveContent (ObjectInputStream.java:814) 05-10 10: 56: 40.345: W/Système.err (26121): \t à java.io.ObjectInputStream.readObject (ObjectInputStream.java:2003) 05-10 10: 56: 40.350: W/System.err (26121): \t à com.myapp.LogInfo.readLog (LogInfo.java:116) – Marek

+0

Il est incorrect de faire une boucle jusqu'à null. readObject() ne renvoie pas la valeur null à la fin du flux. Il lance EOFException. – EJP

Répondre

5
  1. Vous pouvez » t ajouter à un fichier existant créé avec un ObjectOutputStream, au moins pas sans effort. Il y a un truc quelque part sur l'extension ObjectOutputStream et la substitution de la méthode writeStreamHeader() afin de ne pas écrire l'en-tête du flux la deuxième fois, mais je ne suis pas en faveur de cela. Vous devriez vraiment réécrire le fichier entier, peut-être sous forme de liste.

  2. Vous n'avez pas besoin de tout ce code. Juste faire strokes et codes non-statique et non-transitoire, et se débarrasser des méthodes readObject() et writeObject() tout à fait.

+0

La classe de points n'est pas sérialisable. Je ne peux pas démissionner de redéfinir readObject() et writeObject() – Marek

+0

java.awt.Point est sérialisable. En utilisez-vous un autre? – EJP

+0

J'utilise l'importation android.graphics.Point. Aussi, quand je rends ce champ non-statique, même avec ces méthodes, j'obtiens une exception "Point non sérialisable". Pourquoi...? – Marek

0

@EJP a raison.Il ne peut pas s'ajouter à un fichier existant créé avec un ObjectOutputStream. Vous pouvez effectuer les étapes suivantes pour le résoudre: 1. Conserver la référence d'objet ObjectOutputStream 2. une fois que writeObject() a été appelé, n'appelez pas close() 3. fournissez une méthode pour fermer ObjectOutputStream.

+0

Le problème a déjà été résolu en utilisant ObjectOutputStream personnalisé – Marek

+0

Comment avez-vous résolu cela? Pourriez-vous poster votre code ObjectOutputStream personnalisé? – handrenliang

+0

Vous pouvez trouver le code mis à jour dans la question. Vous devez uniquement remplacer la méthode writeStreamHeader() – Marek

0

il est un moyen d'enregistrer plusieurs objets dans un seul fichier: vous devez d'abord faire un tableau d'objets (Object [] objects), puis mettre vos objets un par un comme un objet dans ce tableau, puis écrire ce tableau à l'aide writeObject(objects) méthode. bonne chance.

Questions connexes