反序列化多个Java对象

8

亲爱的同事们,你好:

我有一个Garden类,在其中序列化和反序列化多个Plant类对象。序列化是有效的,但如果我想将其分配给mein静态方法中的调用变量,则反序列化无法正常工作。

public void searilizePlant(ArrayList<Plant> _plants) {
    try {
        FileOutputStream fileOut = new FileOutputStream(fileName);
        ObjectOutputStream out = new ObjectOutputStream(fileOut);
        for (int i = 0; i < _plants.size(); i++) {
            out.writeObject(_plants.get(i));
        }
        out.close();
        fileOut.close();
    } catch (IOException ex) {
    }
}

反序列化代码:

public ArrayList<Plant> desearilizePlant() {
    ArrayList<Plant> plants = new ArrayList<Plant>();
    Plant _plant = null;
    try {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(fileName));
        Object object = in.readObject();

       // _plant = (Plant) object;


        // TODO: ITERATE OVER THE WHOLE STREAM
        while (object != null) {
            plants.add((Plant) object);
            object = in.readObject();
        }

        in.close();
    } catch (IOException i) {
        return null;
    } catch (ClassNotFoundException c) {
        System.out.println("Employee class not found");
        return null;
    }
    return plants;
}

我的调用代码:

ArrayList<Plant> plants = new ArrayList<Plant>();
plants.add(plant1);
Garden garden = new Garden();
garden.searilizePlant(plants);

// THIS IS THE PROBLEM HERE
ArrayList<Plant> dp = new ArrayList<Plant>();
dp = garden.desearilizePlant();

编辑
我遇到了空指针异常
@NilsH的解决方案很好用,谢谢!


“它不工作”是什么意思?代码是否编译?运行时是否出现错误?你具体得到了哪些错误? - Jesper
你好,你遇到了什么确切的问题?你说“如果我想将它分配给(主)静态方法中的调用变量,则无法正常工作”是什么意思?在调试器中,你是否看到plants数组被正确构建了? - wmorrison365
此外,您需要将IO关闭调用放在“finally”块中。而且,您不需要ArrayList<Plant> dp = new ArrayList<Plant>();。只需将ArrayList<Plant> dp = garden.desearilizePlant();作为数组创建在#deserializePlant中即可。 - wmorrison365
为什么你要在对象不等于null的情况下循环?如果你计划写入一个空值来表示EOS,那么这是多余的;如果你期望读取一个没有写入空值的空值,那么你是错误的。你应该捕获EOFException。 - user207421
3个回答

21

那么序列化整个列表怎么样?没有必要对列表中的每个对象进行序列化。

public void searilizePlant(ArrayList<Plant> _plants) {
    try {
        FileOutputStream fileOut = new FileOutputStream(fileName);
        ObjectOutputStream out = new ObjectOutputStream(fileOut);
        out.writeObject(_plants);
        out.close();
        fileOut.close();
    } catch (IOException ex) {
    }
}

public List<Plant> deserializePlant() {
    List<Plants> plants = null;
    try {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(fileName));
        plants = in.readObject(); 
        in.close();
    }
    catch(Exception e) {}
    return plants;
}

如果那无法解决您的问题,请发表有关您错误的更多详细信息。


@NilsH 非常感谢,它已经可以工作了。 更改:public List<Plant> deserializePlant(){....} - imalik8088

1

当涉及到大量对象的反序列化时(例如由于内存问题),将整个对象列表反序列化可能并不总是可行的。在这种情况下,请尝试:

    ObjectInputStream in = new ObjectInputStream(new FileInputStream(
            filename));

    while (true) {
        try {
            MyObject o = (MyObject) in.readObject();
            // Do something with the object
        } catch (EOFException e) {
            break;
        }
    }

    in.close();

或者使用Java SE 7的try-with-resources语句:

    try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(
            filename))) {
        while (true) {
            MyObject o = (MyObject) in.readObject();
            // Do something with the object
        }
    } catch (EOFException e) {
        return;
    }

这对我没有用。我得到了一个流损坏错误。请参见https://dev59.com/GYDaa4cB1Zd3GeqP_RLm - faizal
@faizal 需要修改如何创建outputstream。请参见https://dev59.com/q3M_5IYBdhLWcg3w3nNs - Tomasz
这是因为你的 while 条件。即使流已经被消耗掉了,你还会从中读取。 - throws_exceptions_at_you

0
如果您将其序列化为数组线性列表,则可以在反序列化时将其转换回数组线性列表 - 所有其他方法对我都无效:
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;

public class Program 
{
    public static void writeToFile(String fileName, Object obj, Boolean appendToFile) throws Exception
    {
        FileOutputStream fs = null;
        ObjectOutputStream os = null;
        try
        {
            fs = new FileOutputStream(fileName);
            os = new ObjectOutputStream(fs);

            //ObjectOutputStream.writeObject(object) inherently writes binary
            os.writeObject(obj); //this does not use .toString() & if you did, the read in would fail
        }
        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                os.close();
                fs.close();
            }
            catch(Exception e)
            {
                //if this fails, it's probably open, so just do nothing
            }
        }
    }


    @SuppressWarnings("unchecked")
    public static ArrayList<Person> readFromFile(String fileName)
    {
        FileInputStream fi = null;
        ObjectInputStream os = null;
        ArrayList<Person> peopleList = null;
        try
        {
            fi = new FileInputStream(fileName);
            os = new ObjectInputStream(fi);
            peopleList = ((ArrayList<Person>)os.readObject());  
        }
        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
        catch(EOFException e)
        {                     
            e.printStackTrace();
        }
        catch(ClassNotFoundException e) 
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                os.close();
                fi.close();
            }
            catch(Exception e)
            {
                //if this fails, it's probably open, so just do nothing
            }
        }
        return peopleList;
    }




    public static void main(String[] args) 
    {
        Person[] people = { new Person(1, 39, "Coleson"), new Person(2, 37, "May") };
        ArrayList<Person> peopleList = new ArrayList<Person>(Arrays.asList(people));

        System.out.println("Trying to write serializable object array: ");

        for(Person p : people)
        {
            System.out.println(p);
        }
        System.out.println(" to binary file");

        try
        {
            //writeToFile("output.bin", people, false); //serializes to file either way
            writeToFile("output.bin", peopleList, false); //but only successfully read back in using single cast
        }                                                // peopleList = (ArrayList<Person>)os.readObject();
                                                         // Person[] people = (Person[])os.readObject(); did not work
                                                        // trying to read one at a time did not work either (not even the 1st object) 
        catch (Exception e)
        {
            e.printStackTrace();
        }



        System.out.println("\r\n");




        System.out.println("Trying to read object from file. ");
        ArrayList<Person> foundPeople = null;
        try
        {
            foundPeople = readFromFile("input.bin");
        } 
        catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        if (foundPeople == null)
        {
            System.out.println("got null, hummm...");
        }
        else
        {
            System.out.println("found: ");

            for(int i = 0; i < foundPeople.size(); i++)
            {
                System.out.println(foundPeople.get(i));
            }

            //System.out.println(foundPeople); //implicitly calls .toString()
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接