P2P network and serialization - java

Greeting,
I am working on a program that depends on p2p local network ,i create new peers by pressing run on the IDE , i want an array list to be shared between all the threads so i can modify on it.
the problem i have faced that if the first thread write on the serialization file the newly created threads can read this modification on the list, but if the last thread modify the list the first threads can't see this modification since they desesrialize the file once on the run button press.
is there any solution for this ?(Java)
code:
Peer peer = Peer.getInstance(portName, portNumber, "localhost", peers);
new Thread(peer::startHost).start();
peers.put(peer.getPort(), peer);
waitASecond();
serializePeers();
return peer;
Serialize :
private static void serializePeers() {
try {
FileOutputStream fos = new
FileOutputStream("peersList.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(peers);
oos.close();
fos.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
Desirialize:
private static void deserializePeers() {
try {
FileInputStream fis = new FileInputStream("peersList.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
peers = (LinkedHashMap<Integer, Peer>) ois.readObject();
ois.close();
fis.close();
} catch (Exception e) {
System.out.println("This is the first peer connected to the network"); }
}

Related

How to appends objects in byte stream using ObjectOutputStream

I want to append multiple object at the end to the same binary file using ObjectOutputStream
But when I run the following code more than one time I get the exception
java.io.StreamCorruptedException: invalid type code: AC
The question is
Is there any headers things that I should know to APPEND OBJECTS at the end of the file in java?
package sourcepackage;
import sourcepackage.persons.Person;
import sourcepackage.persons.Student;
import java.io.*;
public class MainClass {
public static void main(String[] args) {
Person mahmoud_kanbar = new Student(21, 224466, "Mahmoud Kanbar", "ITE");
try {
FileOutputStream out = new FileOutputStream("Hello.dat", true);
ObjectOutputStream objectOut = new ObjectOutputStream(out);
objectOut.writeObject(mahmoud_kanbar);
objectOut.close();
out.close();
FileInputStream in = new FileInputStream("Hello.dat");
ObjectInputStream objectIn = new ObjectInputStream(in);
while (in.available() != 0) {
Person hi = (Person) objectIn.readObject();
hi.printInfo();
}
objectIn.close();
in.close();
} catch (Exception e) {
System.out.println(e);
}
}
}
I was searching for decades about a solution to this problem and I couldn't find anything
I want to append objects just like the c++ do
You can append objects to the same ObjectOutputStream with writeObject() method. When reading, they are read in the same order they were written. Also, you may be getting that error because your stream is buffered and not written. You should use flush() method to make sure the buffer has been written to the file.
Let's write two objects to the same file and read them:
Person mahmoud_kanbar = new Student(21, 224466, "Mahmoud Kanbar", "ITE");
Person omid = new Student(18, 200000, "Omid Nejadabbasi", "ITE");
try {
FileOutputStream out = new FileOutputStream("Hello.dat", true);
ObjectOutputStream objectOut = new ObjectOutputStream(out);
objectOut.writeObject(mahmoud_kanbar);
objectOut.writeObject(omid);
objectOut.flush();
objectOut.close();
out.close();
FileInputStream in = new FileInputStream("Hello.dat");
ObjectInputStream objectIn = new ObjectInputStream(in);
Person newPerson= (Person) objectIn.readObject();
newPerson.printInfo();
newPerson= (Person) objectIn.readObject();
newPerson.printInfo();
objectIn.close();
in.close();
} catch (Exception e) {
System.out.println(e);
}
readObject() deserializes the next Object serialized into the stream.

Saving and loading an Arraylist of classes via ObjectInputStream

I'm currently trying to save and load multiple instances of a class of type 'Player' via serialization. (This is for an assignment as an fyi).
The way the process currently works is I run the class via an ObjectOutputStream.writeObject(Player), this seems to work as I get the text file with what appears to be class data.
The problem I'm currently having is when I reverse and load the class, I'm unable to cast the object back to a player object, it is throwing an exception, however I'm not currently knowledgeable enough to figure out the exact exception.
Please find below the functions.
Save function:
public void savePlayers(ArrayList<Player> p)
{
FileOutputStream fout = null;
ObjectOutputStream oos = null;
try
{
fout = new FileOutputStream("Player.txt");
oos = new ObjectOutputStream(fout);
for(Player player: p)
{
oos.writeObject(p);
}
fout.close();
oos.close();
}
catch(Exception e)
{
System.out.println("Error is: " + e);
}
finally
{
closeStreams(fout, oos);
}
}
Load Function:
public ArrayList<Player> loadPlayers()
{
ArrayList<Player> loadedList = new ArrayList<Player>();
FileInputStream fis;
ObjectInputStream ois;
try
{
fis = new FileInputStream("Player.txt");
ois = new ObjectInputStream(fis);
while(true)
{
System.out.println("Entered loop"); //testing
Object obj = ois.readObject();
System.out.println("Read object done"); //testing
Player p = (Player)obj;
System.out.println("Casted player"); //The line here doesn't run, prints out error from exception instead and exits loop
loadedList.add(p);
System.out.println("Loop iterated");
}
}
catch(EOFException eof)
{
}
catch(Exception e)
{
System.out.println("Exception here");
}
}
Is there a better way to save the classes? Am I doing something wrong when casting?
change to
oos.writeObject(player);
and the moment you are writing the whole ArrayList multiple times

Saving Class Type info to file for later use

As you know, passing class types is important when programming Android applications.
One simple example is using an Intent.
Intent i = new Intent(this, MyActivity.class);
So it'll be kind of useful in some situations if I can save the class type info to a file for later use, for instance, after reboot.
void saveClassTypeInfo(Class<?> classType, String filename) {
String str = null;
// Some job with classType
FileOutputStream fos = null;
try {
fos = new FileOutputStream(filename);
fos.write(str.getBytes());
fos.close();
} catch (Exception e) {
}
}
If I could save in a certain way like above, then I would be able to put it back to an Intent like this in the future.
Intent i = new Intent(this, restoredClassInfoFromFile);
How I can achieve this kind of job? Because Class<?> is not an object, I don't know where to start at all.
[EDIT]
.class is an object too, so we can save it just like saving an object.
This is possible using ObjectOutputStream here SaveState is your Custom class
public static void saveData(SaveState instance){
ObjectOutput out;
try {
File outFile = new File(Environment.getExternalStorageDirectory(), "appSaveState.ser");
out = new ObjectOutputStream(new FileOutputStream(outFile));
out.writeObject(instance);
out.close();
} catch (Exception e) {e.printStackTrace();}
}
public static SaveState loadData(){
ObjectInput in;
SaveState ss=null;
try {
in = new ObjectInputStream(new FileInputStream("appSaveState.ser"));
ss=(SaveState) in.readObject();
in.close();
} catch (Exception e) {e.printStackTrace();}
return ss;
}
Full Tutorial write to File available here
And Read Object from File here

How to write and read java serialized objects into a file

I am going to write multiple objects to a file and then retrieve them in another part of my code. My code has no error, but it is not working properly. Could you please help me find what is wrong about my code.
I read different codes from different websites, but none of them worked for me!
Here is my code to write my objects to a file:
MyClassList is an arraylist which includes objects of my class (which must be written to a file).
for (int cnt = 0; cnt < MyClassList.size(); cnt++) {
FileOutputStream fout = new FileOutputStream("G:\\address.ser", true);
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(MyClassList.get(cnt));
}
I added "true" to the constructor of the outputstream, because I want to add each object to end of the file. Is that correct?
And here is my code to read the objects from the file:
try {
streamIn = new FileInputStream("G:\\address.ser");
ObjectInputStream objectinputstream = new ObjectInputStream(streamIn);
MyClass readCase = (MyClass) objectinputstream.readObject();
recordList.add(readCase);
System.out.println(recordList.get(i));
} catch (Exception e) {
e.printStackTrace();
}
It finally prints out just one object. Now, I don't know if I am not writing correctly or reading correctly!
Why not serialize the whole list at once?
FileOutputStream fout = new FileOutputStream("G:\\address.ser");
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(MyClassList);
Assuming, of course, that MyClassList is an ArrayList or LinkedList, or another Serializable collection.
In the case of reading it back, in your code you ready only one item, there is no loop to gather all the item written.
As others suggested, you can serialize and deserialize the whole list at once, which is simpler and seems to comply perfectly with what you intend to do.
In that case the serialization code becomes
ObjectOutputStream oos = null;
FileOutputStream fout = null;
try{
fout = new FileOutputStream("G:\\address.ser", true);
oos = new ObjectOutputStream(fout);
oos.writeObject(myClassList);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if(oos != null){
oos.close();
}
}
And deserialization becomes (assuming that myClassList is a list and hoping you will use generics):
ObjectInputStream objectinputstream = null;
try {
FileInputStream streamIn = new FileInputStream("G:\\address.ser");
objectinputstream = new ObjectInputStream(streamIn);
List<MyClass> readCase = (List<MyClass>) objectinputstream.readObject();
recordList.add(readCase);
System.out.println(recordList.get(i));
} catch (Exception e) {
e.printStackTrace();
} finally {
if(objectinputstream != null){
objectinputstream .close();
}
}
You can also deserialize several objects from a file, as you intended to:
ObjectInputStream objectinputstream = null;
try {
streamIn = new FileInputStream("G:\\address.ser");
objectinputstream = new ObjectInputStream(streamIn);
MyClass readCase = null;
do {
readCase = (MyClass) objectinputstream.readObject();
if(readCase != null){
recordList.add(readCase);
}
} while (readCase != null)
System.out.println(recordList.get(i));
} catch (Exception e) {
e.printStackTrace();
} finally {
if(objectinputstream != null){
objectinputstream .close();
}
}
Please do not forget to close stream objects in a finally clause (note: it can throw exception).
EDIT
As suggested in the comments, it should be preferable to use try with resources and the code should get quite simpler.
Here is the list serialization :
try(
FileOutputStream fout = new FileOutputStream("G:\\address.ser", true);
ObjectOutputStream oos = new ObjectOutputStream(fout);
){
oos.writeObject(myClassList);
} catch (Exception ex) {
ex.printStackTrace();
}
Simple program to write objects to file and read objects from file.
package program;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class TempList {
public static void main(String[] args) throws Exception {
Counter counter = new Counter(10);
File f = new File("MyFile.txt");
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(counter);
oos.close();
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis);
Counter newCounter = (Counter) ois.readObject();
System.out.println(newCounter.count);
ois.close();
}
}
class Counter implements Serializable {
private static final long serialVersionUID = -628789568975888036 L;
int count;
Counter(int count) {
this.count = count;
}
}
After running the program the output in your console window will be 10 and you can find the file inside Test folder by clicking on the icon show in below image.
I think you have to write each object to an own File or you have to split the one when reading it.
You may also try to serialize your list and retrieve that when deserializing.
if you serialize the whole list you also have to de-serialize the file into a list when you read it back. This means that you will inevitably load in memory a big file. It can be expensive. If you have a big file, and need to chunk it line by line (-> object by object) just proceed with your initial idea.
Serialization:
LinkedList<YourObject> listOfObjects = <something>;
try {
FileOutputStream file = new FileOutputStream(<filePath>);
ObjectOutputStream writer = new ObjectOutputStream(file);
for (YourObject obj : listOfObjects) {
writer.writeObject(obj);
}
writer.close();
file.close();
} catch (Exception ex) {
System.err.println("failed to write " + filePath + ", "+ ex);
}
De-serialization:
try {
FileInputStream file = new FileInputStream(<filePath>);
ObjectInputStream reader = new ObjectInputStream(file);
while (true) {
try {
YourObject obj = (YourObject)reader.readObject();
System.out.println(obj)
} catch (Exception ex) {
System.err.println("end of reader file ");
break;
}
}
} catch (Exception ex) {
System.err.println("failed to read " + filePath + ", "+ ex);
}

How create servers and clients with socket?

I need to build an app where I have four servers running and one client send some packages to these servers, but these servers have to keep running all the time receiving something from the client(sender).
So I create the both classes, client and server:
public class Server {
public Event receive(int port) {
Evento event = null;
try {
ServerSocket ss = new ServerSocket(port);
Socket s = ss.accept();
InputStream is = s.getInputStream();
ObjectInputStream ois = new ObjectInputStream(is);
evento = (Evento) ois.readObject();
is.close();
s.close();
ss.close();
}catch(Exception e){
System.out.println(e);
}
return event;
}
}
public class Client {
public void send(Event event, int port) {
try {
Socket s = new Socket("localhost", 2002);
OutputStream os = s.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(event);
oos.close();
os.close();
s.close();
} catch (Exception e) {
System.out.println(e);
}
}
}
But as I said, I need these servers keep running all the time, if I test once, that's ok, but twice or more, don't.
How could I do that ?
The standard pattern is to create one thread for each connection. If you use one thread you can only read from one blocking connection.
just add a do while block around the readObject.
As a break condition you can check whether the message is something like "exit"..
cheers

Categories

Resources