Objects showing null when importing and deserializing - java

Currently passing a HashMap<byte[],byte[]> where both values are there prior serialization within the TMap, visible in the FILEPATH, whilst the program is running, shows the keys and values. I've tried changing it to a non static field but alas, when loading the TMap on the constructor of the object the Map holds null. Here's the code used to save and load the TMap. Has anyone got any suggestions?
public void loadTMap() {
HashMap<byte[], byte[]> TMap = new HashMap<>();
File f = new File("FILEPATH);
if(f.exists()) {
try {
FileInputStream fileIn = new FileInputStream("FILEPATH");
ObjectInputStream in = new ObjectInputStream(fileIn);
TMap = (HashMap<byte[], byte[]>) in.readObject();
in.close();
fileIn.close();
} catch (IOException i) {
} catch (ClassNotFoundException c) {
}
}
}
public void saveTMap(HashMap<byte[], byte[]> TMap) {
try {
FileOutputStream fileOut = new FileOutputStream(FILEPATH);
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(TMap);
out.close();
fileOut.close();
} catch (IOException i) {
i.printStackTrace();
}
}

In your code TMap is written and read correctly. The problem is that you can not use a byte array as key for the map as equals compares the reference of the byte array and not the contents.
Wrap your key in custom class and implement equals and hashCode like this:
public class ByteArrayKey implements Serializable {
private byte[] content;
public ByteArrayKey(byte[] content) {
this.content = content;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ByteArrayKey that = (ByteArrayKey) o;
return Arrays.equals(content, that.content);
}
#Override
public int hashCode() {
return Arrays.hashCode(content);
}
}
Then change you load and save methods like this:
public static HashMap<ByteArrayKey, byte[]> loadTMap() {
HashMap<ByteArrayKey, byte[]> TMap = new HashMap<>();
File f = new File(FILEPATH);
if (f.exists()) {
try {
FileInputStream fileIn = new FileInputStream(FILEPATH);
ObjectInputStream in = new ObjectInputStream(fileIn);
TMap = (HashMap<ByteArrayKey, byte[]>) in.readObject();
in.close();
fileIn.close();
} catch (IOException i) {
i.printStackTrace();
} catch (ClassNotFoundException c) {
c.printStackTrace();
}
}
return TMap;
}
public static void saveTMap(HashMap<ByteArrayKey, byte[]> TMap) {
try {
FileOutputStream fileOut = new FileOutputStream(FILEPATH);
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(TMap);
out.close();
fileOut.close();
} catch (IOException i) {
i.printStackTrace();
}
}

Related

Java read a file into an arraylist of objects and return that arraylist

I need to write a class that has two static methods: writeFile and readFile. However, after I do my readFile(), it returns nothing.
class writereadFile {
public static void writeFile(ArrayList<Object> list, File file){
try {
try (FileOutputStream fos = new FileOutputStream(file);ObjectOutputStream oos = new ObjectOutputStream(fos)) {
oos.writeObject(list);
oos.close();
}
}catch(IOException e){e.getMessage();}
}
public static ArrayList<Object> readFile(ArrayList<Object>list, File file){
try {
try (FileInputStream fis = new FileInputStream(file);ObjectInputStream ois = new ObjectInputStream(fis)) {
Object o = ois.readObject();
list = (ArrayList<Object>) o;
ois.close();
}
}catch(IOException | ClassNotFoundException e){e.getMessage();}
System.out.println(list);
return list;
}
}
EDIT:
This my class for testing. My object is an arraylist of custom objects if you need the custom object just comment.
class main {
public static void main(String[] args) {
Date date = new Date();
Book b1 = new Book("abc", "Phi", true, date, null);
Book b2 = new Book("cba", "Someone", true, date, null);
Books booklist = new Books();
booklist.add(b1);
booklist.add(b2);
File filetoDo = new File("book.txt");
//write arraylist into file
writereadFile.writeFile(booklist, filetoDo);
//clear the arraylist
booklist.clear();
//read book from file
writereadFile.readFile(booklist, filetoDo);
System.out.println(booklist);
}
}
Your test should read:
bookList = writereadFile.readFile(booklist, filetoDo);
and, by the way, you should really refactor your readFile method to simply:
public static ArrayList<Object> readFile(File file)
You can't modify the argument reference like that, since Java is always pass-by-value call semantics. (You could modify the list argument contents inside the function, but that's not what you are doing.)
If you are using Java 8 try using Streams:
public static readFile(String filePath) {
List<Object> list = new ArrayList<>();
try (Stream<String> stream = Files.lines(Paths.get(filePath))) {
stream.forEach(list::add);
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
I'm playing around this topic a bit on my own, so below you can find some code snippets that might help you.
Examples are very short and simple, so I hope you will not just use e.printStackTrace() in your code :)
public class ExternalIO {
private ExternalIO() {
}
public static ObjectOutputStream objectOutputStream(String basePath, String pathToFile) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream(createFileIfDoesNotExist(absolutePath(basePath, pathToFile)));
return new ObjectOutputStream(fileOutputStream);
}
public static ObjectInputStream objectInputStream(String basePath, String pathToFile) throws IOException {
FileInputStream fileInputStream = new FileInputStream(absolutePath(basePath, pathToFile));
return new ObjectInputStream(fileInputStream);
}
private static File createFileIfDoesNotExist(String absolutePath) throws IOException {
File file = new File(absolutePath);
if (file.exists()) {
return file;
}
file.getParentFile().mkdirs();
file.createNewFile();
return file;
}
private static String absolutePath(String basePath, String pathToFile) {
return Paths.get(basePath, pathToFile).toAbsolutePath().toString();
}
}
output usage:
List<ItemType> input = null; //create your input list here
try (ObjectOutputStream objectOutputStream = ExternalIO.objectOutputStream(CONFIG, FILENAME)) {
objectOutputStream.writeObject(input);
} catch (Exception e) {
e.printStackTrace();
}
input usage:
try (ObjectInputStream objectInputStream = ExternalIO.objectInputStream(CONFIG, FILENAME)) {
return (List<ItemType>) objectInputStream.readObject();
} catch (Exception e) {
e.printStackTrace();
}
hope that helps ; )

java howto load and save a ArrayList object

I've pair the code down to the methods I am having a problem, with. It 'seems' to work until I try to load the file again, and it comes up with nothing in it. (I have not fully understood how to clear the ArrayList before performing the 2nd load, but that is for later).
I am sorry if this is hidden somewhere under some other nomenclature I also have not learned yet, but this is a project that is due tomorrow and I am at my wit's end.
import java.util.*;
import java.io.*;
public class MainATM3 {
public static ArrayList<ClientAccount> accounts = new ArrayList<ClientAccount>();
public static ClientAccount editBankAccount = new ClientAccount("placeholder",1234,1);;
public static void main(String[] args) {
// Create ATM account ArrayList
ArrayList<ClientAccount> accounts = new ArrayList<ClientAccount>();
// Get Account data from files
initialLoadATMAccounts(accounts);
System.out.println("Loaded "+accounts.size());
System.out.println("before Array "+(accounts.size()));
accounts.add(0,new ClientAccount("Jess",500,1830));
accounts.add(1,new ClientAccount("Mary",1111.11,7890));
System.out.println("after Array "+(accounts.size()));
saveATMAccounts(accounts);
System.out.println("saved "+(accounts.size()));
initialLoadATMAccounts(accounts);
System.out.println("Loaded "+accounts.size());
System.out.println("Logged Out");
}
// Save ArrayList of ATM Objects //call by: saveATMAccounts(accounts);
public static void saveATMAccounts(ArrayList<ClientAccount> saveAccounts) {
FileOutputStream fout = null;
ObjectOutputStream oos = null;
try{
fout=new FileOutputStream("ATMAccounts.sav");
oos = new ObjectOutputStream(fout);
oos.writeObject(accounts);
System.out.println("objects written "+(accounts.size()));
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if (fout != null) {
try {
fout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// INITIAL Load ArrayList of ATM Objects //call by: initialLoadATMAccounts(accounts);
public static void initialLoadATMAccounts(ArrayList<ClientAccount> loadAccounts){
FileInputStream fIS = null;
ObjectInputStream oIS = null;
try{
fIS=new FileInputStream("ATMAccounts.sav");
oIS = new ObjectInputStream(fIS);
ArrayList<ClientAccount> loadAccounts = (ArrayList<ClientAccount>) oIS.readObject();
oIS.close();
fIS.close();
}
catch(Exception exc){
exc.printStackTrace();
}
}
}
import java.io.Serializable;
public class ClientAccount implements Serializable {
public String accountName;
public double accountBalance;
public int accountPIN;
public ClientAccount(String accountName, double accountBalance, int accountPIN){
this.accountName=accountName;
this.accountBalance=accountBalance;
this.accountPIN=accountPIN;
}
// Account Name Methods
public String getAccountName() {
return accountName;
}
public void setAccountName(String name) {
accountName = name;
}
// Account Balance Methods
public double getAccountBalance() {
return accountBalance;
}
public void setAccountBalance(double balance) {
accountBalance = balance;
}
// PIN Methods
public int getAccountPIN() {
return accountPIN;
}
public void setAccountPIN(int newPIN) {
accountPIN = newPIN;
}
}
Instead of passing the desired array to initialLoadATMAccounts as param you should return the new, loaded array:
public static List<ClientAccount> initialLoadATMAccounts(){
FileInputStream fIS = null;
ObjectInputStream oIS = null;
try{
fIS=new FileInputStream("ATMAccounts.sav");
oIS = new ObjectInputStream(fIS);
ArrayList<ClientAccount> loadAccounts = (ArrayList<ClientAccount>) oIS.readObject();
oIS.close();
fIS.close();
return loadAccounts;
}
catch(Exception exc){
exc.printStackTrace();
}
}
BTW: A IDE like eclipse would have issued a warning where you overwrite the param loadAccounts.

Java 1.8 FileOutputStream Creating a Directory

I seem to be having a problem with the 1.8 JDK this project was built using the 1.7 JDK but i'm having a problem i can't quite understand.
So i have a ConfigReader Class.
public class ConfigReader {
private static ConfigReader _inst;
public static ConfigReader GetInstance(){
if(_inst == null){
_inst = new ConfigReader();
}
return _inst;
}
private String basePath = "Config/";
public <T extends Serializable> void Write(T in, String filename)
{
String path = basePath+filename+".bin";
try
{
File f = new File(path);
f.mkdirs();
FileOutputStream fileOut =
new FileOutputStream(path);
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(in);
out.close();
fileOut.close();
System.out.println("Saved config file '"+path+"'");
}catch(IOException i)
{
System.out.println("Failed to create config file '"+path+"'");
}
}
public boolean ConfigExists(String filename)
{
String path = basePath+filename+".bin";
File finfo = new File(path);
return finfo.exists();
}
public <T extends Serializable> T Read(T readin, String filename)
{
String path = basePath+filename+".bin";
try
{
FileInputStream fileIn = new FileInputStream(path);
ObjectInputStream in = new ObjectInputStream(fileIn);
readin = (T) in.readObject();
in.close();
fileIn.close();
return readin;
}catch(IOException i)
{
System.out.println("Failed to read '"+path+"'");
return null;
}catch(ClassNotFoundException c)
{
System.out.println("Failed to unserialize '"+path+"'");
c.printStackTrace();
return null;
}
}
}
But for some reason when the Write Method is called it's creating directories E.G
Reading a file:
boolean cfgExists = ConfigReader.GetInstance().ConfigExists("Global.cfg");
if(_inst == null && !cfgExists){
_inst = new Global();
}else if(cfgExists){
_inst = ConfigReader.GetInstance().Read(_inst, "Global.cfg");
}
Writing a file:
ConfigReader.GetInstance().Write(this, "Global.cfg");
I end up with the empty directory "Global.cfg.bin" not a file. i'm slightly confused why this is now happening...
Your call to f.mkdirs() is creating the directory with a path that is identical to your intended file path. Call f.getParentFile().mkdirs() instead and that should clear it up.

ObjectInputStream[Java]

i'm new to file i/o so i'm sorry if this is a pretty bad question.
Currently I have an add method/main method and a person class my outputstream is working fine in the add method: This is at the top of the method
FileOutputStream myFile = null;
try {
myFile = new FileOutputStream("txt123.txt");
} catch (FileNotFoundException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(myFile);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
And I then have this twice because there are two types of people that can be added
oos.writeObject(person);
oos.close();
System.out.println("Done");
So my question, how do i get the input working and finally where do i put it, in the add method or the main method, I read how to do what i done here: http://www.mkyong.com/java/how-to-write-an-object-to-file-in-java/
He also has a guide on reading in the objects but I cant seem to get it working
Thanks!
You would be reading the file you just created like this:
ObjectInputStream in =
new ObjectInputStream(new FileInputStream("txt123.txt"));
// terrible file name, because this is binary data, not text
try{
Person person = (Person) in.readObject();
finally{
in.close();
}
You can combine the ObjectOutputStream with the FileOutputStream as follows. I'm also guessing you need to place the read/write code in one place to allow re-use. Here's a simple example with the read/write in a DAO.
public static class Person implements Serializable {
private String name;
public Person(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
#Override
public String toString() {
return name;
}
}
public static class PersonDao {
public void write(Person person, File file) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream(file));
oos.writeObject(person);
oos.close();
}
public Person read(File file) throws IOException,
ClassNotFoundException {
ObjectInputStream oos = new ObjectInputStream(new FileInputStream(
file));
Person returnValue = (Person) oos.readObject();
oos.close();
return returnValue;
}
}
public static void main(String[] args) throws IOException,
ClassNotFoundException {
PersonDao personDao = new PersonDao();
Person alice = new Person("alice");
personDao.write(alice, new File("alice.bin"));
Person bob = new Person("bob");
personDao.write(bob, new File("bob.bin"));
System.out.println(personDao.read(new File("alice.bin")));
System.out.println(personDao.read(new File("bob.bin")));
}

Load/Store Objects in file in Java

I want to store an object from my class in file, and after that to be able to load the object from this file. But somewhere I am making a mistake(s) and cannot figure out where. May I receive some help?
public class GameManagerSystem implements GameManager, Serializable {
private static final long serialVersionUID = -5966618586666474164L;
HashMap<Game, GameStatus> games;
HashMap<Ticket, ArrayList<Object>> baggage;
HashSet<Ticket> bookedTickets;
Place place;
public GameManagerSystem(Place place) {
super();
this.games = new HashMap<Game, GameStatus>();
this.baggage = new HashMap<Ticket, ArrayList<Object>>();
this.bookedTickets = new HashSet<Ticket>();
this.place = place;
}
public static GameManager createManagerSystem(Game at) {
return new GameManagerSystem(at);
}
public boolean store(File f) {
try {
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(games);
oos.writeObject(bookedTickets);
oos.writeObject(baggage);
oos.close();
fos.close();
} catch (IOException ex) {
return false;
}
return true;
}
public boolean load(File f) {
try {
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis);
this.games = (HashMap<Game,GameStatus>)ois.readObject();
this.bookedTickets = (HashSet<Ticket>)ois.readObject();
this.baggage = (HashMap<Ticket,ArrayList<Object>>)ois.readObject();
ois.close();
fis.close();
} catch (IOException e) {
return false;
} catch (ClassNotFoundException e) {
return false;
}
return true;
}
.
.
.
}
public class JUnitDemo {
GameManager manager;
#Before
public void setUp() {
manager = GameManagerSystem.createManagerSystem(Place.ENG);
}
#Test
public void testStore() {
Game g = new Game(new Date(), Teams.LIONS, Teams.SHARKS);
manager.registerGame(g);
File file = new File("file.ser");
assertTrue(airport.store(file));
}
}
The solution of this problem is that when you are using other objects, let say class A, into a collection like HashMap and want to serialize the HashMap object, then implement the interface Serializable for class A like this:
class A implements Serializable {
}
...
HashMap<Integer,A> hmap;
...
Otherwise that object will not be serializable.
I hope it will solve this problem now.
Try oos.flush() before you close it.
Please remenber that the whole object graph is persisted during serialize. If you have some references to GUI classes for example, you either have to make them serializable, too, or tag them as "transient", so Java won't serialize them.

Categories

Resources