2017-11-23 4 views
0

저는 Java 초보자이고 텍스트 파일에 대한 읽기/쓰기 문제가 있습니다.직렬화 - readObject가 전체 파일을 읽지 않는 이유는 무엇입니까?

과정 :

  • 읽기 및 텍스트 파일 표시 :에서 System.out.println (차고);
  • 첫 번째 차량을 추가하십시오 : garage.addVoiture (lag1);
  • 두 번째 차량 추가 : garage.addVoiture (A300B_2); 여기

가 main.java입니다 :

import fr.ocr.vehicule2.*; 

public class Main { 
    public static void main(String[] args) { 
    Garage garage = new Garage(); 
    System.out.println(garage); 

    Vehicule lag1 = new Lagouna(); 
    lag1.setMoteur(new MoteurEssence("150 Chevaux", 10256d)); 
    lag1.addOption(new GPS()); 
    lag1.addOption(new SiegeChauffant()); 
    lag1.addOption(new VitreElectrique()); 
    garage.addVoiture(lag1); 

    Vehicule A300B_2 = new A300B(); 
    A300B_2.setMoteur(new MoteurElectrique("1500 W", 1234d)); 
    A300B_2.addOption(new Climatisation()); 
    A300B_2.addOption(new BarreDeToit()); 
    A300B_2.addOption(new SiegeChauffant()); 
    garage.addVoiture(A300B_2); 
} 

여기 garage.java

package fr.ocr.vehicule2; 

import java.io.BufferedOutputStream; 
import java.io.EOFException; 
import java.io.BufferedInputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.nio.file.Files; 
import java.nio.file.Paths; 
import java.util.ArrayList; 
import java.util.List; 


public class Garage { 

    private List<Vehicule> voitures = new ArrayList<Vehicule>();; 
    ObjectInputStream ois; 
    ObjectOutputStream oos; 

    public Garage(){ 
    } 

    public String toString() { 
    System.out.println("DEBUG start toString"); 

    String str = ""; 
    // Vérification de l'existence du fichier de sauvegarde 
    if(Files.notExists(Paths.get("garage.txt"))) str += "Aucune voiture sauvegardée !\n"; 

    str += "*************************\n" 
     + "* Garage OpenClassrooms *\n" 
     + "*************************\n"; 

    // Lecture du fichier texte 
    if(Files.exists(Paths.get("garage.txt"))) { 
     try { 
     ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream(new File("garage.txt")))); 
      str += ((Vehicule)ois.readObject()).toString(); 
     ois.close(); 
     } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
     } catch (ClassNotFoundException e) { 
     e.printStackTrace(); 
     } catch (EOFException e) { 
     e.printStackTrace(); 
     } catch (IOException e) { 
     e.printStackTrace(); 
     } 
    } 
    System.out.println("DEBUG end toString"); 
    return str; 
    } 

    public void addVoiture(Vehicule voit) { 

    System.out.println("DEBUG start addVoiture" + voit); 

    voitures.add(voit); 

    // écriture du fichier texte 
    try { 
     oos = new ObjectOutputStream(
      new BufferedOutputStream(
      new FileOutputStream(
       new File("garage.txt")))); 

//  for(Vehicule V:voitures){ 
//    oos.writeObject(V); 
//   } 
     oos.writeObject(voit); 
     oos.close(); 

    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    System.out.println("DEBUG end addVoiture"); 
    } 
} 

main.java의 첫 번째 실행, 난 수 (텍스트 파일이 존재하지 않습니다) 콘솔에서 :

  • Aucune voiture sauvegardée!

    • 차고 OpenClassrooms *

  • 시작 addVoiture
  • 최종 addVoiture
  • 시작 addVoiture
  • 최종 addVoiture

그게 내가 처음 출시 할 때 콘솔에 보여주고 싶은 내용입니다.

그러나 main.java의 두 번째 실행 (텍스트 파일이 존재), 내가 콘솔에서 얻을 :

  • DEBUG 시작 toString
  • DEBUG 끝 toString

    • 주차장 OpenClassrooms *
  • 0125178949 22,398,581,088,243,210
    • Voiture PIGEOT : Lagouna MOTEUR ELECTRIQUE 1,500 W (1234.0)의 Climatisation (347.3 €) 바레 드 TOIT (29.9 €) 공성 chauffant (562.9 €)] 디 UNE valeur 토탈 데 2174.1 €
  • DEBUG addVoiture + Voiture 리노를 시작 Lagouna MOTEUR 에센스 150 Chevaux (10256.0) GPS (113.5 €) 공성 chauffant (562.9 €)를 Vitres ELECTRIQUE (212.35 €)] 디 UNE valeur 토탈 데 11144.75 €
  • DEBUG end addVoiture
  • DEBUG 시작 addVoiture + Voiture PIGEOT : Lagouna Moteur ELECTRIQUE 1500 W (1234.0)) [Climatisation (347.3 €), Barre de toit (29.9 €), Siège chauffant (562.9 €)] 총액 2174.1 €
  • DEBUG end addVoiture 두 번째 자동차 (+ Voiture PIGEOT) 만 콘솔에 표시됩니다.

내가 그들 모두, 내가 그들을 추가 같은 방식으로 정렬되어 원하는 결과 :


  • _ * 차고 OpenClassrooms * _ ***********을 **************
    • Voiture RENO : Lagouna MOTEUR 에센스 150 Chevaux (10256.0) GPS (113.5 €) 공성 chauffant (562.9 €) Vitres ELECTRIQUE (212.35 €)] 총액 11144.75 €
    • ,
    • Voiture PIGEOT : Lagouna MOTEUR ELECTRIQUE 1,500 W (1234.0)의 Climatisation (347.3 €) 바레 드 TOIT (29.9 €) 공성 chauffant (562.9 €)] 디 UNE valeur 토탈 데 2174.1 €
    • 내가 제대로 양쪽 차를 쓰지 않기 때문에

나는이 문제에 대한 해결책을 찾을 수없는, 그것을인가 : oos.writeObject (voit를); 또는 올바르게 읽지 않았기 때문에 str + = ((Vehicule) ois.readObject()). toString(); ?

stackoverflow에서도 많은 부분을 검색했지만 코드가 정확하다고 보입니다. 그래서 파일을 쓰는 방식에 문제가있을 수 있습니까?

누군가가 도울 수 있으면 고마워, 나는 많은 시간을 보내고 있지만 돌아 서.


추가 된 후 @Kevin 앤더슨 정보 : 도움을 다시


감사합니다 많이!

스크립트로 readObject를 변경했지만 여전히 마지막으로 추가 된 차량 만 얻습니다.

이 게시물 (java.io.StreamCorruptedException: invalid type code: AC)을 보았지만 해결할 수 없었습니다. 그래서 writeObject (ObjectOutputStream에 객체를 추가하는 것을 중단했습니다) 방식을 변경하고 거의 좋은 결과를 얻었습니다.

이제 나의 궁극적 인 문제는 readObject()의 "유형 안전 : 체크되지 않은 객체 간 변환"입니다.

내가 생각하기에 (확실하지 않습니까?) 단지 IDE 정보이므로 올바른 방법을 사용하는 것이 더 좋을 것이라고 생각합니다. 그래서 (public @ String (@SuppressWarnings ("unchecked")) toString() {) 그리고 그것을 최선의 방법으로하지만 Stackoverflow에서 찾은 모든 솔루션을 적용 할 수 없었습니다.

아이디어가 있다면 정말 완벽 할 것입니다.

새 차고입니다.자바 :

public class Garage { 

    private List<Vehicule> voitures = new ArrayList<Vehicule>(); 
    private ObjectInputStream ois; 
    protected static ObjectOutputStream oos; 

    public Garage(){} 

    public String toString() { 

    String str = ""; 

    // Vérification de l'existence du fichier de sauvegarde 
    if(Files.notExists(Paths.get("garage.txt"))) { 
     str += "Aucune voiture sauvegardée !\n"; 
    } 

    str += "*************************\n" 
     + "* Garage OpenClassrooms *\n" 
     + "*************************\n"; 

    // Lecture du fichier texte 
    if(Files.exists(Paths.get("garage.txt"))) { 
     try { 
     ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream(new File("garage.txt")))); 

     // garage loading during instanciation : 
       // Information Eclipse : 
       // Type safety: Unchecked cast from Object to List<Vehicule> 
       this.voitures = (List<Vehicule>)ois.readObject(); 

     // Affichage des voitures enregistrées dans le fichier texte 
     for(Vehicule V : this.voitures){ 
      str += V; 
     } 


       // To avoid "Type safety: Unchecked cast from Object to List<Vehicule>" : 
     // those 2 solutions show identical information "Type safety: Unchecked cast from Object to List<Vehicule>" 

     // First tried solution : 
     // this.voitures = new new ArrayList<Vehicule>((List<Vehicule>)ois.readObject()); 

       // Second tried solution : 
//    if(ois.readObject() instanceof List<?>){ 
//     List<?> list = (ArrayList<?>)ois.readObject(); 
//     for(Object e : list){ 
//      if(e instanceof Vehicule){ 
//      this.voitures = (List<Vehicule>)e; 
//      } 
//     } 
//    } 


     ois.close(); 
     } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
     } catch (ClassNotFoundException e) { 
     e.printStackTrace(); 
     } catch (EOFException e) { 
     e.printStackTrace(); 
     } catch (IOException e) { 
     e.printStackTrace(); 
     } 
    } 
    return str; 
    } 

    public void addVoiture(Vehicule voit) { 

    voitures.add(voit); 

    // écriture du fichier texte 
    try { 
     oos = new ObjectOutputStream(
      new BufferedOutputStream(
      new FileOutputStream(
       new File("garage.txt")))); 

     // Enregistrement detoutes les voitures dans le fichier texte 
     oos.writeObject(voitures); 

     oos.close(); 
    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    } 
} 

유형의 안전을 위해

추가 솔루션 : 검사되지 않은이 게시물에


감사 목록에 Object에서 주연 : Type safety: Unchecked cast

텍스트 파일이 목록 개체를 포함 Garage()를 실행하면이 List 객체를 기존 List voitures에 추가해야했습니다. 내 방법 ("선택 해제") @SuppressWarnings를하지만, 내가하지 않는이 방법을 수행하는 더 나은 외모 : 체크되지는

을 목록에 Object에서 캐스팅 내가 사용할 수 있습니다 유형 안전 :

이클립스 보여주는데 경고를 무시하십시오 :

List<?> list = (List<?>) ois.readObject(); 
    for(int i = 0; i < list.size(); i++) { 
     this.voitures.add((Vehicule) list.get(i)); // instanciation 
     str += (Vehicule) list.get(i);// Added to console message 
    }  

희망, 내 초보자 실수로 인해 유감스럽게 생각합니다. ^^ 도움을 주신 모든 분들께 감사드립니다!

+0

당신은'텍스트 파일이 존재합니다'를 쓰지 만'ObjectOutputStream'은 텍스트가 아닌 바이너리를 씁니다. – Kayaman

답변

1

addVoiture으로 전화 할 때마다 데이터 파일을 덮어 쓰지 않고 덮어 쓰게됩니다. new FileOutputStream에 추가 인수 true가 추가 대신 새 빈 파일마다 시간을 만들기 위해 기존 파일을 여는

oos = new ObjectOutputStream(
     new BufferedOutputStream(
     new FileOutputStream(
      new File("garage.txt"), true))); 

에 파일 개방 코드를 변경합니다. 문서보기 here

또한 파일에 여러 개의 Vehicule 개체를 쓰고 있으므로 복수의 readObject 호출을 모두 실행해야만 다시 읽을 수 있습니다. readObject 한 번만 전화하기 때문에 한 대의 자동차 만 본 이유가 있습니다. 당신이 EOFException 얻을 때까지 당신은 루프에서 readObject를 계속 전화해야이 변경으로

try { 
     ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream(new File("garage.txt")))); 
     for(;;){ 
      try { 
       str += ((Vehicule)ois.readObject()).toString(); 
      } catch (EOFException eofe) { 
       break; 
      } 
     } 
     ois.close(); 
     } 
} catch .... 

을, 당신은 내부 try 지금을 처리하기 때문에 더 이상 외부 try 블록과 EOFException를 잡을 필요가 없습니다.

+0

정보를 모두 덮어 쓰셔서 고마워. 하지만 FileOutputStream에 "true"매개 변수를 추가하여 추가하고 (str + = ((Vehicule) ois.readObject()). toString();) 여전히 마지막으로 추가 된 차량 만 반환합니다 (Voiture PIGEOT : Lagouna Moteur ELECTRIQUE) . 파일에 마지막으로 추가 된 차량 만 포함되었다고 가정합니다. 확실히 또 다른 문제가 있습니다 : /? – kobano

+0

당신은 또한 단지 1 대의 차를 읽고 있습니다; 업데이트 된 답변보기 –

+0

다시 한 번 감사드립니다. 코드는 업데이트되었지만 마침내 writeObject를 변경하고 다른 정보를 얻습니다. 업데이트 된 게시물을 참조하십시오. – kobano

1

이름은 당신이해야 할 것을 알려줍니다 : 을 읽으십시오. 그것은 명명되지

파일를 참조하십시오.

즉, 객체 스트림을 사용할 때 코드는 어떤 객체가 어떤 순서로 작성되는지 정의합니다. 그리고 나서, 다른면에서, 비슷한 코드는 과 같은 순서로을 읽어야합니다.

이것이 전부입니다.

현재 코드 은 기존 파일을 덮어 씁니다. 파일 내용을 "보존"하려면 먼저 이전에 저장 한 객체를 읽어야합니다.

관련 문제