2016-12-11 2 views
1

Ich versuche, eine Treemap aus einer Datei zu lesen. Ich weiß, dass es eine in der Datei serialisiert ist, mein Problem ist, dass OIS eine EOFexception auf diese Datei wirft.ObjectInputStream löst EOFexception beim Lesen einer Datei mit einem Objekt

public class FileDBMapApi { 

    private FileOutputStream OutPutter; 
    private FileInputStream Inputter; 
    private ObjectInputStream InputStream; 
    private ObjectOutputStream OutputStream; 
    private NavigableMap<Integer, Object> data; 
    private File currentFile; 
    private int autoIncrement; 

    /** 
    * @param dataFile is the file to use as a database 
    */ 
    public FileDBMapApi(String dataFile) { 
     String fullPath = "data/" + dataFile; 
     currentFile = new File(fullPath); 
    } 

    // initialiserar databasen 
    public void init() { 
     // checkar om filen existerar och isåfall assignar inputter och outputter till filen 
     System.out.println(currentFile.exists() && !currentFile.isDirectory()); 
     if (currentFile.exists() && !currentFile.isDirectory()) { 
      try { 
       OutPutter = new FileOutputStream(currentFile); 
       OutPutter.flush(); 
       Inputter = new FileInputStream(currentFile); 
       OutputStream = new ObjectOutputStream(OutPutter); 
       OutputStream.flush(); 
       InputStream = new ObjectInputStream(Inputter); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } else { 
      // annars så skapar den filen och assignar det istället 
      try { 
       boolean temp1 = currentFile.getParentFile().mkdirs(); 
       boolean temp2 = currentFile.createNewFile(); 
       if (temp2) { 
        OutPutter = new FileOutputStream(currentFile); 
        Inputter = new FileInputStream(currentFile); 
        OutputStream = new ObjectOutputStream(OutPutter); 
        InputStream = new ObjectInputStream(Inputter); 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 

     // läser in hashmapen från filen 
     this.convertData(); 
    } 

    public void write() { 
     try { 
      PrintWriter n = new PrintWriter(currentFile); 
      n.close(); 
      OutputStream.writeObject(data); 
      OutputStream.flush(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    public int add(Object o) { 
     int id = autoIncrement; 
     data.put(autoIncrement, o); 
     autoIncrement++; 
     return id; 
    } 

    public Object get(int i) { 
     return data.get(i); 
    } 

    public void close() { 
     try { 
      OutPutter.close(); 
      Inputter.close(); 
      InputStream.close(); 
      OutputStream.flush(); 
      OutputStream.close(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    // returnar data 
    public NavigableMap<Integer, Object> getAll() { 
     return data; 
    } 

    public long getFileSize() { 
     return currentFile.length(); 
    } 

    // tar data från en fil och sätter in det till en hashmap 
    private void convertData() { 
     try { 
      if (InputStream.read() != -1) { 
       data = (NavigableMap) InputStream.readObject(); 
      } else { 
       data = new TreeMap<>(); 
       System.out.println(data); 
      } 
      if (!data.isEmpty()) autoIncrement = data.lastKey(); 
      else autoIncrement = 0; 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    public void closeAndWrite() { 
     write(); 
     close(); 
    } 

} 

Es ist die Methode, die die convertData(0 Ausnahme auslöst. Ich habe die fragliche Datei überprüft und es enthält tatsächlich eine serialisierte Treemap, die mit der Methode write() und auch close() serialisiert wurde. Jetzt meine Frage ist, wo mache ich etwas falsch beim Speichern oder Abrufen der Daten?

Antwort

0

Ich werde kommen, wo der Fehler ist aber wirklich macht Ihren Code überhaupt keinen Sinn und braucht eine gründliche Überprüfung:

public class FileDBMapApi { 

    private FileOutputStream OutPutter; 
    private FileInputStream Inputter; 

Sie die FileInput/OutputStreams separat als Datenelemente nicht benötigen. Löschen.

// initialiserar databasen 
    public void init() { 
     // checkar om filen existerar och isåfall assignar inputter och outputter till filen 
     System.out.println(currentFile.exists() && !currentFile.isDirectory()); 
     if (currentFile.exists() && !currentFile.isDirectory()) { 
      try { 
       OutPutter = new FileOutputStream(currentFile); 
       OutPutter.flush(); 
       Inputter = new FileInputStream(currentFile); 
       OutputStream = new ObjectOutputStream(OutPutter); 
       OutputStream.flush(); 
       InputStream = new ObjectInputStream(Inputter); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } else { 
      // annars så skapar den filen och assignar det istället 
      try { 
       boolean temp1 = currentFile.getParentFile().mkdirs(); 
       boolean temp2 = currentFile.createNewFile(); 
       if (temp2) { 
        OutPutter = new FileOutputStream(currentFile); 
        Inputter = new FileInputStream(currentFile); 
        OutputStream = new ObjectOutputStream(OutPutter); 
        InputStream = new ObjectInputStream(Inputter); 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 

Sie können alle diese gewundenen Doppelsprech dazu reduzieren:

try { 
    currentFile.getParentFile().mkdirs(); 
    OutputStream = new ObjectOutputStream(new FileOutputStream(currentFile)); 
    InputStream = new ObjectInputStream(new FileInputStream(currentFile)); 
} catch (IOException exc) { 
    exc.printStackTrace(); 
} 

... obwohl es noch besser wäre, wenn init()IOException warf, anstatt zu kontrollieren und es intern zu absorbieren. All der komplexe Code, den Sie geschrieben haben, erfüllt genau das nicht mehr. Das gleichzeitige Öffnen einer Datei für die Ausgabe und Eingabe ist nicht sinnvoll und funktioniert auf manchen Plattformen wie Windows nicht. Du musst das überdenken.

Das Problem ist hier. Die PrintWriter ist nicht verwendet, also sollte es entfernt werden, aber das eigentliche Problem hier ist, dass Sie gerade die Ausgabedatei abgeschnitten haben, die garantiert eine IOException beim Lesen über eine ObjectInputStream erzeugt. Löschen.

public void close() { 
     try { 
      OutPutter.close(); 
      Inputter.close(); 
      InputStream.close(); 
      OutputStream.flush(); 
      OutputStream.close(); 

Das ist alles Unsinn. flush() vor close() ist redundant, und Sie müssen nur und OutputStream schließen. Sie schließen ihre verschachtelten Streams für Sie, und selbst wenn dies nicht der Fall ist, macht es keinen Sinn, den verschachtelten Ausgabestream zu schließen und dann zu versuchen, den äußeren Ausgabestream zu spülen und zu schließen.

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

Wieder sollte das Verfahren IOException werfen, nicht absorbieren.

public long getFileSize() { 
     return currentFile.length(); 
    } 

Das ist ziemlich bedeutungslos. Auf einigen Betriebssystemen wie Windows wird der Verzeichniseintrag nicht aktualisiert, bis Sie die Datei schließen, so dass Sie hier nur Null zurückgeben könnten. Sie sollten die aktuelle Länge der Datei nicht kennen müssen.

 try { 
      if (InputStream.read() != -1) { 

Dies ergibt keinen Sinn. Hier haben Sie ein Byte gelesen und weggeworfen. Da Sie keine zusätzlichen Bytes geschrieben haben, kann dies nur dazu führen, dass Sie nicht mehr mit dem Stream synchronisiert sind. Entferne das.

   data = (NavigableMap) InputStream.readObject(); 
      } else { 
       data = new TreeMap<>(); 
       System.out.println(data); 
      } 

Dieses 'else' ergibt auch keinen Sinn.Wenn die Datei leer ist oder keine weiteren Objekte mehr enthält, wird eine EOFException ausgelöst, und Sie sollten hieraus ausweichen. In der Tat, wieder sollten Sie die IOExceptions aller Arten hier geworfen werden, anstatt sinnlos eine leere TreeMap ersetzen.

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

Siehe oben Re werfen IOException. Schreibe keinen Code wie diesen.

public void closeAndWrite() { 

Diese Methode sollte writeAndClose() benannt werden, wenn Sie es wirklich brauchen, was Sie nicht tun.

Ich habe die fragliche Datei überprüft und es enthält tatsächlich eine serialisierte Treemap.

Überprüft wie? Es gibt nur eine Möglichkeit, das zu überprüfen, und zwar unter der Nummer readObject().

+0

Okey vielen Dank für Ihre harte Kritik! (Nein, wirklich danke!) Ich habe jetzt den Code geändert, wie du es vorgeschlagen hast, und ich werde aus meinen Fehlern lernen. (Ich lerne immer noch!) Aber wenn ich versuche, eine Testdatei mit einem Write auszuführen, und wenn ich es erneut starte, wird das "Objekt" nicht angezeigt. Es ist nur eine leere 'Treemap'. Nun würde dies bedeuten, dass es eine "EOFException" ausgelöst hat, aber warum macht es das, wenn ich in einem früheren Lauf in die Datei geschrieben habe? Nochmals vielen Dank für die Hilfe und Kritik! – maxcodes

+0

Haben Sie eine leere 'TreeMap' * wegen * einer' EOFException' bekommen? Wenn das der Fall war, haben Sie es immer noch nicht serialisiert, und NB: Sie sollten 'EOFException' in diesem Fall nicht abfangen und eine' neue TreeMap() 'ersetzen: sonst können Sie nicht sagen, was vor sich geht. Lassen Sie einfach die Ausnahme, wie oben mehrfach erwähnt, loslassen und lassen Sie den Anrufer damit umgehen. Sonst hast du es vielleicht leer gemacht, es gefüllt und es dann wieder serialisiert? Wenn ja, siehe 'ObjectOutputStream.writeUnshared()' und 'ObjectOutputStream.reset()'. – EJP

+0

Ja, ich mache das, was Sie gesagt haben, und fange die 'Exception'. Wenn sie ein 'EOF' wirft, mache ich eine' neue TreeMap() '. Ich muss die Methoden, die Sie vorgeschlagen haben, überprüfen, danke! – maxcodes

Verwandte Themen