我想问一下社区您对以下情况有何看法?任务是将对象写入文件。这可以通过将一个对象列表写入我稍后可以阅读的文件来完成,这样我就可以再次使用我的对象了。在这里,我几乎只会写一个对象到文件,即列表(可能包含更多对象)。
但是,任务接缝是将单独的对象写入文件,该方法从列表中接收。对象可以是任何东西。 (当然,它们必须是可序列化的)
所以我做了:
public class TaskStream {
public static void saveObjects(ArrayList<Object> al) {
try {
FileOutputStream fos = new FileOutputStream("outputFile", true);
try {
ObjectOutputStream oos = new ObjectOutputStream(fos);
for (Object o : al){
try {
oos.writeObject(o);
System.out.println("saved");
} catch (NotSerializableException e) {
System.out.println("An object was not serializable, it has not been saved.");
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
这很好用。
但是现在,我想读它们。我关于它的第一个概念是一种方法,在文件有对象之前读取对象,我可以将它们中的每一个再次保存到列表中(这就是任务)。就像伪代码一样:
for(Object o : fileToRead){ list.add(o) }
怎么可能?我开始使用ObjectInputStream的readObject方法,但它似乎导致了很多错误。
你知道吗?或者这项任务的最佳实践是什么?谢谢!
我尝试了你的想法。确切的实施:
public static ArrayList<Object> readObjects(){
ArrayList<Object> al = new ArrayList<Object>();
boolean cont = true;
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("outputFile"));
while(cont){
Object obj=null;
try {
obj = ois.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if(obj != null)
al.add(obj);
else
cont = false;
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return al;
}
为了测试程序,我将把两个对象写入文件。 我从文件中读取对象并将它们添加到列表中。 我遍历此列表并打印出内容。
如果我运行该程序,则会发生以下情况(我删除了outputFile,因此程序可以 重新创建并从头开始做任何事情。)
结果:
列表中的两个对象将成功打印。 但我收到了这个:
java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2598)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1318)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
...
我没有改变任何东西,我再次运行程序。结果:
列表中的两个对象将成功打印。 但我收到了这个:
java.io.StreamCorruptedException: invalid type code: AC
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1377)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
从现在开始,任何重新运行都会带来相同的结果。
如果我从头开始重复整个过程(从删除outputFile开始),一切都完全相同(如预期的那样)。
你有想法如何解决它吗?非常感谢您的帮助!
答案 0 :(得分:2)
您将要使用FileInputStream和ObjectInputStream。
FileInputStream fis = new FileInputStream("outputFile");
ArrayList<Object> objectsList = new ArrayList<Object>();
boolean cont = true;
try{
ObjectInputStream input = new ObjectInputStream(fis);
while(cont){
Object obj = input.readObject();
if(obj != null)
objectsList.add(obj);
else
cont = false;
}
}catch(Exception e){
//System.out.println(e.printStackTrace());
}
答案 1 :(得分:0)
我们要使用FileInputStream类方法“可用”方法检查给定的流是否有数据或字节要读取,如果数据不存在则此方法将返回0;
public static ArrayList<Object> getObjects(){
ArrayList<Object> objects = new ArrayList<Object>();
FileInputStream fis = new FileInputStream("outputFile");
ObjectInputStream ois = new ObjectInputStream(fis);
Object obj =null;
boolean isExist = true;
while(isExist){
if(fis.available() != 0){
obj = (A) ois.readObject();
objects.add(obj);
}
else{
isExist =false;
}
}
return objects;
}
答案 2 :(得分:0)
我们可以在列表中添加所有对象,然后序列化列表。我们可以再次反序列化列表,我们可以迭代列表以获取我们正在寻找的对象。它需要使用以下类。 FileOutputStream中 的FileInputStream ObjectInputStream的 的ObjectOutputStream
["Form1"]
答案 3 :(得分:0)
我知道这个话题很老,但是我知道我的解决办法。 您得到
的原因`'invalid type code: AC'`
是因为在编写一个对象并尝试读取它之后, ObjectInputStream 试图读取您的 ObjectOutputStream 编写的信息。这就是序列化通常的工作方式。 您的代码上的问题是正在创建新的 ObjectInputStream 并尝试从旧的 ObjectOutputStream 读回,并且发现它们没有相同的序列号因此您会收到此错误。
我在不久前发布的另一个主题中找到了解决方案,请点击此处:stackoverflow solution
他正在做的是,他超越了 streamWriter ,它“欺骗”了 ObjectInputStream ,以为他可以阅读 ObjectOutputStream 。
希望对您有所帮助。 和平!
答案 4 :(得分:0)
import java.io.*;
import java.util.*;
class ObjectReadWrite implements Serializable, Comparable <ObjectReadWrite>
{
int no;
String name;
ObjectReadWrite(int i,String s)
{
this.no=i;
this.name=s;
}
public String toString()
{
return "TP Data : "+this.no+":"+this.name;
}
public int compareTo(ObjectReadWrite a1)
{
return this.name.compareTo(a1.name);
}
public static void main(String args[]) throws Exception
{
TreeSet<ObjectReadWrite> aw = new TreeSet<ObjectReadWrite>();
aw.add(new ObjectReadWrite(1,"ABC"));
aw.add(new ObjectReadWrite(2,"DDF"));
aw.add(new ObjectReadWrite(3,"DAF"));
aw.add(new ObjectReadWrite(4,"DCF"));
//Writing Objects From TreeSet
ObjectOutputStream os=new ObjectOutputStream(
new FileOutputStream(
new File("Test.dat")));
os.writeObject(aw);
os.close();
//Reading Objects into TreeSet
TreeSet ar = new TreeSet();
ObjectInputStream is=new ObjectInputStream(
new FileInputStream(
new File("Test.dat")));
ar=(TreeSet)is.readObject();
is.close();
Iterator ir = ar.iterator();
while(ir.hasNext())
{
System.out.println((ObjectReadWrite)ir.next());
}
}
}
答案 5 :(得分:0)
解决方案非常简单。在这里,您必须处理EOFException
。为此,您必须按如下所示修改代码-
try {
obj = ois.readObject();
} catch (EOFException e) {
break;
}
答案 6 :(得分:0)
'content'
答案 7 :(得分:0)
我试图编写其中的一些代码片段,但其中大多数对我来说并不奏效。但是@pushkars的代码运行良好,而不是进行while循环来获取许多对象,您只需编写和读取单个对象列表并直接处理该列表即可,而不是读取或编写许多对象。
请参阅我的静态IOMannager类的代码:
public static class IOMannager {
private static List<Produto> lista_produtos = new ArrayList<Produto>();
public static void ler() {
ObjectInputStream in = null;
try{
in = new ObjectInputStream(new FileInputStream("produtos.txt"));
Object obj = in.readObject();
in.close();
lista_produtos = (ArrayList<Produto>) obj;
}
//catches goes here....
}
}
现在我将所有对象都放入列表lista_produtos
中,并可以根据需要处理它们。
感谢@pushkars
答案 8 :(得分:0)
这个对我有用:
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f));
listeSolutions.clear();
Solution s;
while (true) {
try {
s = (Solution) ois.readObject();
listeSolutions.add(s);
} catch (Exception e) {
break; }
}
ois.close();
} catch (Exception e) {
e.printStackTrace();
}