从文件读取和写入对象的ArrayList的问题

时间:2017-03-21 12:18:01

标签: java serialization arraylist deserialization

我遇到了将对象的ArrayList保存到文件并且读取它的问题。我在StackOverflow中搜索,我找不到我的错误......

我有和Classnotfound问题或读取空值......

有人帮助我吗?看起来写作对我很有用。

这就是代码:

// calls using the CLASS

        // Lets save distribution IFF asked to
        if (shouldSavePoiDistribution){

            List<POInode> listOfPOIs = new ArrayList<POInode>();
            for(Node n : Runtime.nodes) {   
                if (n instanceof POInode){
                    listOfPOIs.add((POInode) n);

                }
            }

            GlobalWriteAndLoadPositions saver = new GlobalWriteAndLoadPositions();
            saver.write(Global.distributionFolder,listOfPOIs);

        }

        // lets load a distribution IFF asked to
        if (shouldLoadPoiDistribution){

            Global.lastPOIloaded = 0;
            GlobalWriteAndLoadPositions loader = new GlobalWriteAndLoadPositions();
            Global.listOfLoadedPOIs = loader.load(Global.distributionFile);

        }


/////  CLASS to read and write object in file.

// The file look be correct its is created and the size varies...
// reading returns the corret size of the arraylist, but only wrong values IFF I try/catch "ois.readObject();" for ClassNotFound, otherwise, it raises an exception

package sinalgo.runtime;

import java.io.FileInputStream;
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;
import projects.nodes.nodeImplementations.POInode;


public class GlobalWriteAndLoadPositions {


    public GlobalWriteAndLoadPositions(){   
    }
    public void write(String folder, List<POInode> POIlist)  throws IOException {   
        int nextFileItarator = (int) Files.list(Paths.get(folder)).count();
        nextFileItarator++;
        FileOutputStream fout= new FileOutputStream (folder + nextFileItarator + ".txt");
        System.out.print("\n[Global] Trying SAVE a distribution on " + folder + nextFileItarator + ".txt" + ": ");
        ObjectOutputStream oos = new ObjectOutputStream(fout);      
        oos.writeObject(POIlist);
        oos.close();
        fout.close();
        POIlist.forEach((a)->System.out.print("POI " + a.ID + " @ (" + a.getPosition().xCoord +" , " + a.getPosition().yCoord + ") | " ));
        System.out.println("\n");
    }
    public ArrayList<POInode> load(String file)  throws IOException{
        System.out.print("\n[Global] Trying LOAD a distribution: " + Global.distributionFile + " ||>  ");
        FileInputStream fin = new FileInputStream(file);
        ObjectInputStream ois = new ObjectInputStream(fin);
        List<POInode> listOfLoadedPOIs = new ArrayList<POInode>();

        listOfLoadedPOIs = (ArrayList<POInode>) ois.readObject(); // THIS LOOK WRONG, I MEAN, Does not find the class POInode

        ois.close();    
        fin.close();
        listOfLoadedPOIs.forEach((a)->System.out.print("POI " + a.ID + " @ (" + a.getPosition().xCoord +" , " + a.getPosition().yCoord + ") | " ));
        System.out.println("\n");
        return (ArrayList<POInode>) listOfLoadedPOIs;   
    }
}

请问,如何解决这个问题?

2 个答案:

答案 0 :(得分:0)

根据你自己的评论

listOfLoadedPOIs = (ArrayList<POInode>) ois.readObject();
   // readObject() throws ClassnotFound or empty values.

我们可以扣除发生的事情。

有两种情况:

  1. 您事先致电撰写方法 - 使用了列表。然后你的阅读代码工作正常;但令你惊讶的是,你写的空名单。
  2. 您之前致电方法 - 使用非空列表。但是运行“读取”代码的JVM ...不知道该列表中存储的对象的类。
  3. 所以你真正的问题归结为:“当java告诉我关于ClassNotFound时,这是什么意思”;并且可以找到答案here

    长话短说:测试“阅读”部分时的类路径设置不完整;因为java找不到存储在这些文件中的对象类型的.class文件。

    您的代码的另一个问题:当您在彼此“构建”这些流时,例如

    WhateverStream inner = ...
    SomeOtherStream outer = new SomeOtherStream(inner);
    

    然后你只需要在外部上调用close()/ ...,而不是在内部调用。实际上甚至可能是你的代码中的另一个错误,你做的是inner.close(),然后是outer.close()!

答案 1 :(得分:0)

首先, 您如何使用这些方法

主要的麻烦就在那里。

另外,可以看到POInode类。

BTW 一个小小的建议是使用try with resources而不是像你一样关闭流:

// writing looks fine
public void write(String folder, ArrayList<POInode> POIlist) throws IOException {
    int nextFileItarator = (int) Files.list(Paths.get(folder)).count();
    nextFileItarator++;

    try (FileOutputStream fout = new FileOutputStream(folder + nextFileItarator + ".txt");
         ObjectOutputStream oos = new ObjectOutputStream(fout)) {

        oos.writeObject(POIlist);
    }
}

// I read the quantity OK, but empty or wrong values...
public ArrayList<POInode> load(String file) throws IOException {
    ArrayList<POInode> listOfLoadedPOIs = new ArrayList<POInode>();

    try (FileInputStream fin = new FileInputStream(file);
         ObjectInputStream ois = new ObjectInputStream(fin)) {

        // readObject() throws ClassnotFound or empty values.
        listOfLoadedPOIs = (ArrayList<POInode>) ois.readObject();
    }
    return (ArrayList<POInode>) listOfLoadedPOIs;
}

更好地遵循您的代码样式将从close()块调用final 但是,正如我之前所说,更好的想法是使用try with resources。约书亚布洛赫在他的Effective Java中提出了建议,第9项:首先尝试使用资源进行尝试。