java - 从文件中读取多个对象,就像它们在数组中一样

时间:2014-12-10 19:55:54

标签: java object

我想问一下社区您对以下情况有何看法?任务是将对象写入文件。这可以通过将一个对象列表写入我稍后可以阅读的文件来完成,这样我就可以再次使用我的对象了。在这里,我几乎只会写一个对象到文件,即列表(可能包含更多对象)。

但是,任务接缝是将单独的对象写入文件,该方法从列表中接收。对象可以是任何东西。 (当然,它们必须是可序列化的)

所以我做了:

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开始),一切都完全相同(如预期的那样)。

你有想法如何解决它吗?非常感谢您的帮助!

9 个答案:

答案 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(); 
}