how do i deserialize Map with objects - java

i try to serialize Map. this is my function:
Map<Integer,Word> currentMap=new LinkedHashMap<Integer,Word>();
protected void serializeCM(){
try{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(bos);
os.writeObject(currentMap);
String SO = bos.toString();
os.flush();
os.close();
writeFile("serialized.txt",SO,false);
}
catch(Exception e){e.printStackTrace();}
}
after i try to deserialize currentMap
protected Map<Integer,Word> deserializeCM(String f){
Map<Integer,Word> map=new LinkedHashMap<Integer,Word>();
String path=System.getProperty("user.dir")+"\\";
try{
String str=new String(Files.readAllBytes(Paths.get(path+f)));
ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes());
ObjectInputStream is = new ObjectInputStream(bis);
map = (LinkedHashMap<Integer,Word>)is.readObject();
is.close();
return map;
}
catch(Exception e){e.printStackTrace();};
return null;
}
this is how word class looks:
public class Word implements Cloneable, Serializable{
public String l;
public String cap="";
public byte rPos;
public byte time;
public byte a_index;
public byte master = -1;
public Map<Integer,Word> enumerations = new HashMap<Integer,Word>();
public Map<Integer,Boolean> contrs = new HashMap<Integer,Boolean>();
public Object clone(){
try{return super.clone();}
catch(Exception e){e.printStackTrace();return this;}
}
}
and when i try to deserialize it it gets me this error
java.io.StreamCorruptedException: invalid stream header: EFBFBDEF
what am i doing wrong?
any help appriciated!

Write directly to file without using ByteArrayInputStream / ByteArrayOutputStream.
Serialization:
protected void serializeCM() {
try {
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("serialized.txt"));
os.writeObject(currentMap);
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Deserialization:
protected Map<Integer, Word> deserializeCM(String f) {
String path = System.getProperty("user.dir") + "\\" + f;
try {
Map<Integer, String> map = new LinkedHashMap<Integer, Word>();
ObjectInputStream is = new ObjectInputStream(new FileInputStream(path));
map = (LinkedHashMap<Integer, Word>) is.readObject();
is.close();
return map;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

Related

Strange EOFexception while do readObject() in deserialization

I am trying to process an object on the server with UDP. I serialize it, send it to the server. On the server, I deserialize, modify, then serialize back to send back to the client. On the client I get it, and when I try to readObject () I get an EOF exception. Please help, what could be the problem? I didn't find the answer anywhere.
This is client:
public class Client {
public static void main(String[] args) {
Help help = new Help("WTF");
try {
byte[] objByteArray = serialize(help);
DatagramSocket ds = new DatagramSocket();
InetAddress host = InetAddress.getLocalHost();
int port = 6789;
int objLength = objByteArray.length;
DatagramPacket dp = new DatagramPacket(objByteArray, objLength, host, port);
ds.send(dp);
dp = new DatagramPacket(objByteArray, objLength);
ds.receive(dp);
byte[] new_arr = objByteArray;
Help deserializedObj = (Help) deserialize(objByteArray);
System.out.println(deserializedObj.getData());
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (SocketException e) {
throw new RuntimeException(e);
} catch (UnknownHostException e) {
throw new RuntimeException(e);
} catch (IOException e) {
e.printStackTrace();
}
}
public static byte[] serialize(Object obj) {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)){
oos.writeObject(obj);
byte[] objByteArray = baos.toByteArray();
return objByteArray;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static Object deserialize(byte[] arr) throws IOException, ClassNotFoundException {
Object result = null;
try (ByteArrayInputStream bais = new ByteArrayInputStream(arr);
ObjectInputStream ois = new ObjectInputStream(bais)){
result = ois.readObject();
}
catch (IOException e){
}
return result;
}
}
And this is Server:
public class Server {
public static void main(String[] args) throws IOException {
String filepath = System.getProperty("user.dir") + "\\src\\Server\\Data\\Collection.json";
CollectionManager.setFilePath(filepath);
byte[] arr = new byte[100000];
DatagramSocket ds = new DatagramSocket(6789);
DatagramPacket dp = new DatagramPacket(arr, arr.length);
ds.receive(dp);
try {
Help deserializedObj = (Help) deserialize(arr);
deserializedObj.setData("Server finished work!");
System.out.println("Done!");
byte[] serializedObj = serialize(deserializedObj);
InetAddress host = dp.getAddress();
int port = dp.getPort();
dp = new DatagramPacket(serializedObj, serializedObj.length, host, port);
ds.send(dp);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
public static byte[] serialize(Object obj) {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)){
oos.writeObject(obj);
byte[] objByteArray = baos.toByteArray();
return objByteArray;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static Object deserialize(byte[] arr) throws IOException, ClassNotFoundException {
Object result = null;
try (ByteArrayInputStream bais = new ByteArrayInputStream(arr);
ObjectInputStream ois = new ObjectInputStream(bais)){
result = ois.readObject();
}
catch (IOException e){
}
return result;
}
}
And also the classes:
public class Help extends Command implements Serializable {
public Help(String name){
super.setName(name);
}
private String data;
public void setData(String s){
data = s;
}
public String getData(){
return data;
}
#Override
public void execute() {
}
}
The problem was that the packet sent from the server is larger than the original one, therefore, on the client, we must receive data into the buffer with a margin, and from there try to read the data.
This is an edited Client code:
byte[] buffer = new byte[1024];
dp = new DatagramPacket(buffer, buffer.length);
ds.receive(dp);

How to deserialize an object from byte[] where byte[] represents an object of a class that is loaded over a network?

How to deserialize an object from byte[] where byte[] represents an object of a class that is loaded over a network?
I have the following Hello.java file
import java.io.Serializable;
public class Hello implements Serializable {
public Integer hello = 5;
public static void main(String... args) {
System.out.println(sayHello());
}
public static String sayHello() {
return "Hello world";
}
}
Its compiled into Hello.class and stored at /tmp/test
Below is an example similar to the Application I am working on.
public class Util {
public static byte[] serializeObject(Object object) throws Exception {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(object);
objectOutputStream.close();
byteArrayOutputStream.close();
return byteArrayOutputStream.toByteArray();
}
public static Object deserializeObject1(byte[] serializedObject) throws Exception {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(serializedObject);
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
Object object = objectInputStream.readObject();
objectInputStream.close();
byteArrayInputStream.close();
return object;
}
public static Object deserializeObject2(byte[] byteArray) {
ByteArrayInputStream bis = new ByteArrayInputStream(byteArray);
ObjectInput input = null;
try {
input = new ObjectInputStream(bis){
#Override protected Class<?> resolveClass(final ObjectStreamClass desc) throws IOException, ClassNotFoundException {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if (cl == null) return super.resolveClass(desc);
return Class.forName(desc.getName(), false, cl);
}
};
return input.readObject();
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
return null;
} finally {
try {
bis.close();
if (input != null)
input.close();
} catch (IOException ex) {
ex.printStackTrace();
return null;
}
}
}
}
Here is my main application
public class Dynamic {
private ObjectMapper jsonMapper = new ObjectMapper();
public static void main(String[] args) {
File myFile=new File("/tmp/test/");
try {
URLClassLoader cl = new URLClassLoader(new URL[]{myFile.toURI().toURL()});
Class klazz = cl.loadClass("Hello");
Object object = klazz.getDeclaredConstructor().newInstance();
System.out.println(jsonMapper.writeValueAsString(object)); //works
byte[] serObjectbytes = Util.serializeObject(object);
System.out.println(Arrays.toString(serObjectbytes)); // works
Object deserializeObject = Util.deserializeObject1(serObjectbytes); //fails
Object deserializeObject2 = Util.deserializeObject2(serObjectbytes); // also fails
System.out.println(jsonMapper.writeValueAsString(deserializeObject));
} catch (ClassNotFoundException esx) {
esx.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
so both Util.deserializeObject1 and Util.deserializeObject1 fails with ClassNotFoundException ex I understand I am trying just deserialize bunch of bytes and Java class loader wouldn't have any idea of where the Hello.class unless I defineClass again, however, my goal here is to deserialize into a Hello object and repopulate to the same state as it was in before serialization. How do I do that?

Odd output from file

I have an issue with the input I am getting from reading a file.
The file is made in another activity and is very simple:
ArrayList stuff = new ArrayList();
stuff.add("1,2,3");
try{
String saveFile = "saveGamesTest1.csv";
FileOutputStream saveGames = openFileOutput(saveFile, getApplicationContext().MODE_APPEND);
ObjectOutputStream save = new ObjectOutputStream(saveGames);
save.writeObject(stuff);
save.close(); }
In the other activity it's being read via
try {
FileInputStream fileIn=openFileInput("saveGamesTest1.csv");
InputStreamReader InputRead = new InputStreamReader(fileIn);
Scanner s = new Scanner(InputRead).useDelimiter(",");
System.out.println(s.next());
System.out.println(s.next());
System.out.println(s.next());
}
I was expecting (and hoping) to get a result back like
1
2
3
However, the result I'm getting is this:
/storage/emulated/0/Android/data/ys.test/files/saveGamesTest1.csv����sr��java.util.ArrayListx����a���I��sizexp������w������t��1
2
3x
What am I doing wrong?
.
EDIT
I tried Serializable as suggested below, like follow:
public class Save implements java.io.Serializable {
public String name;
public String address;
public transient int SSN;
public int number;
}
public void save(){
Save e = new Save();
e.name = "Reyan Ali";
e.address = "Phokka Kuan, Ambehta Peer";
e.SSN = 11122333;
e.number = 101;
try {
String saveFile = "save.ser";
FileOutputStream saveGames = openFileOutput(saveFile, getApplicationContext().MODE_APPEND);
ObjectOutputStream out = new ObjectOutputStream(saveGames);
out.writeObject(e);
out.close();
saveGames.close();
System.out.printf("Serialized data is saved in save.csv");
}
catch(IOException i) {
i.printStackTrace();
out.println("Save exception gepakt");
}
}
However, out.writeObject(e); gives an error saying that this isn't Serializable
You are not storing object as csv but as serialize java object you have to read as an object not as a csv file
take a look here https://www.tutorialspoint.com/java/java_serialization.htm
at Serializing an Object part
You have to use
FileInputStream in = null;
ObjectInputStream ois = null;
ArrayList stuff2 = null;
try {
in = openFileInput("saveGamesTest1.csv");
ois = new ObjectInputStream(in);
stuff2 = (ArrayList) ois.readObject();
} catch(IOException e) {...}
catch(ClassNotFoundException c) {...}
finally {
if (ois != null) {
ois.close();
}
if (in != null) {
in.close();
}
}
If you want a csv file you have to build it for instance by iterate over your array and write one by one the value in your file and adding the separator or follow this
How to serialize object to CSV file?
EDIT :
An elegant way in Java 7 to serialize an object (here a list like in your example) and deserialize :
public class Main {
public static void main(String[] args) {
List<Integer> lists = new ArrayList<>();
List<Integer> readList = null;
String filename = "save.dat";
lists.add(1);
lists.add(2);
lists.add(3);
//serialize
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename))) {
oos.writeObject(lists);
} catch (IOException e) {
e.printStackTrace();
}
//don't need to close because ObjectOutputStream implement AutoCloseable interface
//deserialize
try (ObjectInputStream oos = new ObjectInputStream(new FileInputStream(filename))) {
readList = (List<Integer>) oos.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
//don't need to close because ObjectInputStream implement AutoCloseable interface
//test
if(!lists.equals(readList)) {
System.err.println("error list saved is not the same as the one read");
}
}
}

Read and Write text file from my own class in Android Studio

I have been trying to create a class called TextFileReaderWriter I want to use the getters and setters to read and write to a text file in such a way that I can call the class and the method from anywhere in the program by simply using setfileContents(somestring) and somestring = getfileContents() something like this
example:
TextFileReaderWriter trw = new TextFileReaderWriter();
trw.setfileContents(somestring); //this would write 'somestring' to the text file.
String somestring = trw.getfileContents(); //this would return 'somestring' from the text file.
Here's what I have so far but it writes nothing to the file:
public class TextFileReaderWriter extends Activity{
String fileContents;
Context context;
String TAG = "MYTAG";
public TextFileReaderWriter(String fileContents, Context context) {
this.fileContents = fileContents;
this.context = context;
}
public String getFileContents() {
return fileContents;
}
public void setFileContents(String fileContents) {
this.fileContents = fileContents;
FileOutputStream fos = null;
try {
fos = context.openFileOutput("UserInputStore", Context.MODE_PRIVATE);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
OutputStreamWriter osw = new OutputStreamWriter(fos);
try {
osw.write(fileContents);
Log.d(TAG, fileContents);
} catch (IOException e) {
e.printStackTrace();
}
}
}
You don't need the OutputStreamWriter--FileOutputStreamwill do the trick just fine.
//what you had before
FileOutputStream fos = null;
try {
fos = context.openFileOutput(filename, Context.MODE_PRIVATE);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//use just the file output stream to write the data
//data here is a String
if (fos != null) {
try {
fos.write(data.getBytes());
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Method to save data on disk :
protected static void saveDataOnDisk(String data) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try {
ObjectOutput objectOutput = new ObjectOutputStream(byteArrayOutputStream);
objectOutput.writeObject(data);
byte[] buffer = byteArrayOutputStream.toByteArray();
File loginDataFile = (new File(filePath)); // file path where you want to write your data
loginDataFile.createNewFile();
FileOutputStream fileOutputStream = new FileOutputStream(loginDataFile);
fileOutputStream.write(buffer);
fileOutputStream.close();
objectOutput.flush();
objectOutput.close();
byteArrayOutputStream.flush();
byteArrayOutputStream.close();
Log.i(“SAVE”, ”———————-DONE SAVING”);
} catch(IOException ioe) {
Log.i(“SAVE”, “———serializeObject|”+ioe);
}
}
Method to fetch data from disk:
private static Object getDataFromDisk() {
try {
FileInputStream fileInputeStream = new FileInputStream(FilePath);
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputeStream);
Object data = (Object) objectInputStream.readObject();
objectInputStream.close();
fileInputeStream.close();
return dataModel;
} catch (Exception error) {
Log.i(“FETCH”, ”—-getDataFromDisk———ERROR while reading|” + error);
}
return null;
}

Java Serializable Object to Byte Array

Let's say I have a serializable class AppMessage.
I would like to transmit it as byte[] over sockets to another machine where it is rebuilt from the bytes received.
How could I achieve this?
Prepare the byte array to send:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = null;
try {
out = new ObjectOutputStream(bos);
out.writeObject(yourObject);
out.flush();
byte[] yourBytes = bos.toByteArray();
...
} finally {
try {
bos.close();
} catch (IOException ex) {
// ignore close exception
}
}
Create an object from a byte array:
ByteArrayInputStream bis = new ByteArrayInputStream(yourBytes);
ObjectInput in = null;
try {
in = new ObjectInputStream(bis);
Object o = in.readObject();
...
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException ex) {
// ignore close exception
}
}
The best way to do it is to use SerializationUtils from Apache Commons Lang.
To serialize:
byte[] data = SerializationUtils.serialize(yourObject);
To deserialize:
YourObject yourObject = SerializationUtils.deserialize(data)
As mentioned, this requires Commons Lang library. It can be imported using Gradle:
compile 'org.apache.commons:commons-lang3:3.5'
Maven:
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
Jar file
And more ways mentioned here
Alternatively, the whole collection can be imported. Refer this link
If you use Java >= 7, you could improve the accepted solution using try with resources:
private byte[] convertToBytes(Object object) throws IOException {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos)) {
out.writeObject(object);
return bos.toByteArray();
}
}
And the other way around:
private Object convertFromBytes(byte[] bytes) throws IOException, ClassNotFoundException {
try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream in = new ObjectInputStream(bis)) {
return in.readObject();
}
}
Can be done by SerializationUtils, by serialize & deserialize method by ApacheUtils to convert object to byte[] and vice-versa , as stated in #uris answer.
To convert an object to byte[] by serializing:
byte[] data = SerializationUtils.serialize(object);
To convert byte[] to object by deserializing::
Object object = (Object) SerializationUtils.deserialize(byte[] data)
Click on the link to Download org-apache-commons-lang.jar
Integrate .jar file by clicking:
FileName -> Open Medule Settings -> Select your module -> Dependencies -> Add Jar file and you are done.
Hope this helps.
I also recommend to use SerializationUtils tool. I want to make a ajust on a wrong comment by #Abilash. The SerializationUtils.serialize() method is not restricted to 1024 bytes, contrary to another answer here.
public static byte[] serialize(Object object) {
if (object == null) {
return null;
}
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
try {
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
oos.flush();
}
catch (IOException ex) {
throw new IllegalArgumentException("Failed to serialize object of type: " + object.getClass(), ex);
}
return baos.toByteArray();
}
At first sight, you may think that new ByteArrayOutputStream(1024) will only allow a fixed size. But if you take a close look at the ByteArrayOutputStream, you will figure out the the stream will grow if necessary:
This class implements an output stream in which the data is
written into a byte array. The buffer automatically grows as data
is written to it.
The data can be retrieved using toByteArray() and
toString().
Another interesting method is from com.fasterxml.jackson.databind.ObjectMapper
byte[] data = new ObjectMapper().writeValueAsBytes(JAVA_OBJECT_HERE)
Maven Dependency
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
If you are using spring, there's a util class available in spring-core. You can simply do
import org.springframework.util.SerializationUtils;
byte[] bytes = SerializationUtils.serialize(anyObject);
Object object = SerializationUtils.deserialize(bytes);
I would like to transmit it as byte[] over sockets to another machine
// When you connect
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
// When you want to send it
oos.writeObject(appMessage);
where it is rebuilt from the bytes received.
// When you connect
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
// When you want to receive it
AppMessage appMessage = (AppMessage)ois.readObject();
Spring Framework org.springframework.util.SerializationUtils
byte[] data = SerializationUtils.serialize(obj);
In case you want a nice no dependencies copy-paste solution. Grab the code below.
Example
MyObject myObject = ...
byte[] bytes = SerializeUtils.serialize(myObject);
myObject = SerializeUtils.deserialize(bytes);
Source
import java.io.*;
public class SerializeUtils {
public static byte[] serialize(Serializable value) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try(ObjectOutputStream outputStream = new ObjectOutputStream(out)) {
outputStream.writeObject(value);
}
return out.toByteArray();
}
public static <T extends Serializable> T deserialize(byte[] data) throws IOException, ClassNotFoundException {
try(ByteArrayInputStream bis = new ByteArrayInputStream(data)) {
//noinspection unchecked
return (T) new ObjectInputStream(bis).readObject();
}
}
}
This is just an optimized code form of the accepted answer in case anyone wants to use this in production :
public static void byteArrayOps() throws IOException, ClassNotFoundException{
String str="123";
byte[] yourBytes = null;
// Convert to byte[]
try(ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos);) {
out.writeObject(str);
out.flush();
yourBytes = bos.toByteArray();
} finally {
}
// convert back to Object
try(ByteArrayInputStream bis = new ByteArrayInputStream(yourBytes);
ObjectInput in = new ObjectInputStream(bis);) {
Object o = in.readObject();
} finally {
}
}
code example with java 8+:
public class Person implements Serializable {
private String lastName;
private String firstName;
public Person() {
}
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#Override
public String toString() {
return "firstName: " + firstName + ", lastName: " + lastName;
}
}
public interface PersonMarshaller {
default Person fromStream(InputStream inputStream) {
try (ObjectInputStream objectInputStream = new ObjectInputStream(inputStream)) {
Person person= (Person) objectInputStream.readObject();
return person;
} catch (IOException | ClassNotFoundException e) {
System.err.println(e.getMessage());
return null;
}
}
default OutputStream toStream(Person person) {
try (OutputStream outputStream = new ByteArrayOutputStream()) {
ObjectOutput objectOutput = new ObjectOutputStream(outputStream);
objectOutput.writeObject(person);
objectOutput.flush();
return outputStream;
} catch (IOException e) {
System.err.println(e.getMessage());
return null;
}
}
}

Categories