0

I am having problems to save an ArrayList of a object to a file and them read that. I am searching in StackOverflow and I cannot find my error...

Either I have and Classnotfound issue OR a read empty values...

Does anybody help me? Looks that writing is working well to me.

That is the code:

// 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;   
    }
}

Please, how to solve this?

bruno
  • 15
  • 5
  • what about file content - does it looks ok at file itself after writing? – catch23 Mar 21 '17 at 12:22
  • 1
    Add the part that calls the write and the part that calls the read. They may not be using the file names correctly, or maybe you call the read before you call the write. It's impossible to know from the methods themselves. – RealSkeptic Mar 21 '17 at 12:27
  • 1
    And hint: you expect us to spend our time to help you; so you should spent the 1 minute it takes to properly format/indent your code. That preview function exists for a reason! – GhostCat Mar 21 '17 at 12:29
  • Ok, thanks, my first spot. I updated that. – bruno Mar 21 '17 at 13:26
  • The content of the files looks goog, at least the correct list size varies. Values are not availble to read. – bruno Mar 21 '17 at 13:33

2 Answers2

0

Given your own comment from

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

we can deduct what is going on.

There are two cases:

  1. Your prior call to your write method - used an empty list. And then your read code works fine; but gives you, surprise, the empty list you wrote.
  2. Your prior call to your write method - used an NON empty list. But the JVM that is running your "read" code ... doesn't know the class of the objects stored in that list.

So your real problem boils down to: "what does it mean when java tells me about ClassNotFound"; and the answer to that could be found here.

Long story short: your classpath setup when you test your "read" part is incomplete; as java can't find the .class file for the kinds of objects you stored in those files.

The other issue with your code: when you "build" those streams on each other, like

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

then you only need to call close()/... on outer, but not on inner. Actually it might even be another bug in your code that you do inner.close() followed by outer.close()!

Community
  • 1
  • 1
GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • Thanks for your comments. I really wish that would be the first case, but I print the list and looks fine... The size in stored file look to be correct, I my read returns at least the correct size of the Arraylist. Regarding Second possibility, that really looks the problem. I mean, my Eclipse asks for try/catch operation regarding "ois.readObject()" or the load() throws ClassNotfound. – bruno Mar 21 '17 at 13:15
  • Then it seems that you dont understand exceptions yet. The point is: many methods might *potentially* throw certain exceptions (for example to indicate that at runtime, some file was really not there). That helps you to understand the errors that *might* occur at runtime; and add precautions to your code. – GhostCat Mar 21 '17 at 13:21
  • Sure, but I mean, I think you possibility "2" is correct. readObject() is not finding POInode class... – bruno Mar 21 '17 at 13:28
  • Stupid question: how I accept those text suggestions? #noob – bruno Mar 21 '17 at 13:53
  • btw, I still have the problem... I can save and read the ArrayList. – bruno Mar 21 '17 at 13:54
  • 1
    You accept answers by clicking that "check mark" icon next to an answer. But I have to admit; I dont get your last comment. You say: "problem still there. i can read write the list". So what is your current problem? – GhostCat Mar 21 '17 at 14:03
  • The code still not working. I cannot read the Arraylist from the file. – bruno Mar 21 '17 at 23:33
0

Firstly, how do you use those methods?

The main trouble goes there.

Also, not bad will be to see POInode class.

BTW A Smal suggestion is with using try with resources instead of closing streams as you did:

// 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;
}

Following your code style much better will be called close() from final block.
However, as I said earlier a much better idea is to use try with resources. It is suggested by Joshua Bloch in his Effective Java, Item 9: Prefer try-with-resources to try-finally.

catch23
  • 17,519
  • 42
  • 144
  • 217
  • Regarding the usage: – bruno Mar 21 '17 at 13:03
  • regarding the usage for write: 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); regarding the usage for reading: GlobalWriteAndLoadPositions loader = new GlobalWriteAndLoadPositions(); Global.listOfLoadedPOIs = loader.load(Global.distributionFile); – bruno Mar 21 '17 at 13:08
  • @bruno please update the question. and show the code snippet there. – catch23 Mar 21 '17 at 13:09
  • Sorry, I updated that. Now should be correct on the question. – bruno Mar 21 '17 at 13:26