我是Java的初学者,我遇到了对文本文件的读/写问题。
过程:
这是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,(文本文件不存在)我进入控制台:
这就是我想在首次发布时在控制台中显示的内容。
但是第二次执行main.java,(文本文件存在),我进入控制台:
我想要的结果是他们两个,按照我添加它们的方式排序:
我找不到解决这个问题的方法, 是因为我没有正确地写两辆车:oos.writeObject(voit); 或者因为我没有正确读取它:str + =((Vehicule)ois.readObject())。toString(); ?
我甚至在stackoverflow上搜索了很多,但代码似乎是正确的。所以这可能是我写的方式然后读取文件的问题?
如果有人能提供帮助,我会非常感谢,我会花很多时间转身。
在@Kevin Anderson信息之后添加:
再次感谢您的帮助!
我用你的脚本更改了readObject,但我仍然只添加了最后一辆车。
我也看过这篇文章(java.io.StreamCorruptedException: invalid type code: AC)但无法解决。所以我改变了writeObject的方式(停止将对象附加到ObjectOutputStream)并获得了几乎好的结果。
现在我的ultime问题是在readObject()上使用“类型安全:从对象到列表的未经检查的强制转换”。
我认为(不确定?)它只是一个IDE信息所以我认为最好采用正确的方式,所以我想避免使用(@SuppressWarnings(“unchecked”))(public String toString) (){)并以最好的方式做到但我无法应用我在Stackoverflow上找到的任何解决方案。
如果你有一个想法,那将是非常完美的!
这是新的garage.java:
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();
}
}
}
为类型安全添加了解决方案:取消选中从对象到列表的强制转换
感谢此帖:Type safety: Unchecked cast
文本文件包含List对象 当我启动Garage()时,我需要将此List对象添加到现有的List voitures。
Eclipse显示: 类型安全:从对象到列表的未选中转换
我可以使用:@SuppressWarnings(“unchecked”)到我的方法,但这样做看起来更好,所以我不会忽略任何警告:
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 :(得分:1)
该名称告诉您需要做什么:阅读 对象。
它未命名为 read 文件。
换句话说:当您使用对象流时,您的代码会定义哪些对象以哪种顺序写入。然后,另一方面,类似的代码必须以相同的顺序读取这些对象。
这就是全部。
您当前的代码会覆盖现有文件。当你想要&#34;保存&#34;文件内容 - 然后您首先必须读入先前存储的对象。
答案 1 :(得分:1)
每次调用addVoiture
时,您都会覆盖数据文件,而不是添加到数据文件中。将文件打开代码更改为
oos = new ObjectOutputStream(
new BufferedOutputStream(
new FileOutputStream(
new File("garage.txt"), true)));
true
上的额外arg new FileOutputStream
会打开现有文件以进行追加,而不是每次都创建新的空文件。请参阅文档here
此外,由于您正在向文件中写入多个Vehicule
个对象,因此必须执行多个readObject
调用才能再次读取所有这些对象。您只看到一辆车的原因是因为您只拨打readObject
一次。您需要继续调用readObject
,直到获得EOFException
:
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 ....
通过此更改,您不再需要使用外部EOFException
块捕获try
,因为内部try
现在可以处理它。