【问题标题】:Problems with read and write an ArrayList of Objects from a file从文件中读取和写入对象的 ArrayList 的问题
【发布时间】:2017-08-13 02:37:23
【问题描述】:

我在将对象的 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;   
    }
}

请问这个怎么解决?

【问题讨论】:

  • 文件内容怎么样 - 写入后文件本身看起来还可以吗?
  • 添加调用写的部分和调用读的部分。他们可能没有正确使用文件名,或者您在调用写入之前调用了读取。从方法本身是不可能知道的。
  • 并提示:您希望我们花时间帮助您;所以你应该花 1 分钟来正确格式化/缩进你的代码。预览功能的存在是有原因的!
  • 好的,谢谢,我的第一个位置。我更新了。
  • 文件的内容看起来很糟糕,至少正确的列表大小会有所不同。值无法读取。

标签: java serialization arraylist deserialization


【解决方案1】:

给出你自己的评论

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

我们可以推断出发生了什么。

有两种情况:

  1. 您之前对 write 方法的调用 - 使用了 empty 列表。然后你的阅读代码工作正常;但令人惊讶的是,给你的是你写的空列表。
  2. 您之前对 write 方法的调用 - 使用了 NON empty 列表。但是运行“读取”代码的 JVM 不知道存储在该列表中的对象的类。

所以你真正的问题归结为:“当 java 告诉我 ClassNotFound 是什么意思”;可以在here找到答案。

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

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

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

那么你只需要在outer上调用close()/...,而不是inner。实际上,您执行 inner.close() 后跟 outer.close() 甚至可能是代码中的另一个错误!

【讨论】:

  • 感谢您的 cmets。我真的希望这是第一种情况,但是我打印了列表并且看起来很好......存储文件中的大小看起来是正确的,我的读取至少返回了正确大小的 Arraylist。关于第二种可能性,这确实看起来有问题。我的意思是,我的 Eclipse 要求对“ois.readObject()”进行 try/catch 操作,否则 load() 会抛出 ClassNotfound。
  • 那你好像还不了解异常。关键是:许多方法可能可能抛出某些异常(例如,表明在运行时,某些文件确实不存在)。这有助于您了解在运行时可能发生的错误;并为您的代码添加预防措施。
  • 当然,但我的意思是,我认为您的可能性“2”是正确的。 readObject() 没有找到 POInode 类...
  • 愚蠢的问题:我如何接受那些文字建议? #菜鸟
  • 您可以通过单击答案旁边的“复选标记”图标来接受答案。但我不得不承认;我没有得到你的最后评论。你说:“问题仍然存在。我可以读写列表”。那么你目前的问题是什么?
【解决方案2】:

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

主要问题出在那儿。

另外,看POInode类也不错。

顺便说一句一个小建议是使用 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;
}

更好地遵循您的代码样式将从final 块中调用close()
然而,正如我之前所说,一个更好的主意是使用try with resources。这是由 Joshua Bloch 在他的 Effective Java,第 9 项中建议的:Prefer try-with-resources to try-finally。

【讨论】:

  • 关于用法:
  • 关于写入的用法: List listOfPOIs = new ArrayList(); for(Node n : Runtime.nodes) { if (n instanceof POInode){ listOfPOIs.add((POInode) n); } } GlobalWriteAndLoadPositions saver = new GlobalWriteAndLoadPositions saver.write(Global.distributionFolder,listOfPOIs);关于阅读的用法: GlobalWriteAndLoadPositions loader = new GlobalWriteAndLoadPositions(); Global.listOfLoadedPOIs = loader.load(Global.distributionFile);
  • @bruno 请更新问题。并在此处显示代码 sn-p。
  • 对不起,我更新了。现在应该是正确的问题。
猜你喜欢
  • 2017-04-25
  • 1970-01-01
  • 2017-01-01
  • 2013-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-26
  • 1970-01-01
相关资源
最近更新 更多