I'm trying to serialize objects of big size in Java using Externalizable interface.
Code:
public class ResultsData implements Externalizable{
private static final long serialVersionUID = 1L;
private ArrayList<ALotOfResults1> results1;
private ArrayList<ALotOfResults2> results2;
private ArrayList<ALotOfResults3> results3;
private int selection;
public ResultsData(){
results1=new ArrayList<ALotOfResults1>();
results2=new ArrayList<ALotOfResults2>();
results3=new ArrayList<ALotOfResults3>();
}
//Getter and setter omited
#Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(results1);
out.writeObject(results2);
out.writeObject(results3);
}
#Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
switch(selection) {
case 0:
results1 = (ArrayList)in.readObject();
break;
case 1:
in.readObject();
results2 = (ArrayList)in.readObject();
break;
case 2:
in.readObject();
in.readObject();
results3 = (ArrayList)in.readObject();
break;
}
}
Those three arrayLists filled up during program execution have very big size (14 MB each one).
Code(load/save proccess):
public class ResultsManagement {
public static ResultsData loadResultsData(String path,ResultsData resultsData) {
try {
FileInputStream fisProd = new FileInputStream(path+".res");
ObjectInputStream oisProd = new ObjectInputStream(fisProd);
resultsData.readExternal(oisProd);
fisProd.close();
} catch (IOException ioe) {
System.out.println("Error de IO: " + ioe.getMessage());
} catch (ClassNotFoundException cnfe) {
System.out.println("Error de clase no encontrada: " + cnfe.getMessage());
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
return resultsData;
}
public static void saveResultsData(ResultsData resultsData,String path) {
try {
FileOutputStream fosProd = new FileOutputStream(path+".res");
ObjectOutputStream oosProd = new ObjectOutputStream(fosProd);
resultsData.writeExternal(oosProd);
fosProd.close();
} catch (IOException ioe) {
System.out.println("Error de IO: " + ioe.getMessage());
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
}
The unbreakable condition is that I want to have only one File, for example, Documents/Project/project1.res
How can I load some parts of the object without loading the other parts? Is it possible?
For example, I don't need to load the two first arrayList's (results1 and results2) when I only need to load the third one (results3), but the only way i know to get access to results3 is reading results1 and results2.
Code for the answer of Tinke:
In the ResultsData class:
public static byte[] serialize(Object obj) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(out);
os.writeObject(obj);
return out.toByteArray();
}
public static Object deserialize(byte[] data) throws IOException, ClassNotFoundException {
ByteArrayInputStream in = new ByteArrayInputStream(data);
ObjectInputStream is = new ObjectInputStream(in);
return is.readObject();
}
#Override
public void writeExternal(ObjectOutput out) throws IOException {
byte[] r1 = serialize(results1);
System.out.println("Bytes in r1: "+r1.length);//42392 Bytes
out.write(r1);
byte[] r2 = serialize(results2);
System.out.println("Bytes in r2: "+r2.length);//19268558 Bytes (a lot of results here)
out.write(r2);
out.close();
}
#Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
switch(selection) {
case 0:
byte[] arrayBytes=new byte[42392];
in.read(arrayBytes);
results1 = (ArrayList)deserialize(arrayBytes);
break;
case 1:
in.skipBytes(42392);
byte[] arrayBytes2=new byte[19268558];
in.read(arrayBytes2);
results2 = (ArrayList)deserialize(arrayBytes2);
break;
}
}
As a generic solution, while inserting the data, insert the size (in bytes) of each list. then while reading, read the size in and skip those many bytes for each list you wish to skip. The solution could be optimized more depending on your use case and how you insert/access the data in the lists.
Related
I have a view object that needs to be serialized to store in a database, and then retrieved later
public class MachineView extends View implements Serializable {
String name;
int age;
public MachineView(String name, int age, Context context) {
super(context);
this.name = name;
this.age = age;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int x = getWidth();
int y = getHeight();
int radius;
radius = 50;
Paint paint = new Paint();
//paint.setStyle(Paint.Style.FILL);
paint.setTextSize(x / 2);
...
}
}
The only problem is that the methods I am using to serialize objects only work for simple objects( i.e. objects that can be condensed to key value pairs )
below are serialize and read object methods:
//Serialize object
public static byte[] getSerializedObject(Serializable s) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(baos);
oos.writeObject(s);
} catch (IOException e) {
return null;
} finally {
try {
oos.close();
} catch (IOException e) {}
}
byte[] result = baos.toByteArray();
return result;
}
//read object
public static Object readSerializedObject(byte[] in) {
Object result = null;
ByteArrayInputStream bais = new ByteArrayInputStream(in);
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(bais);
result = ois.readObject();
} catch (Exception e) {
result = null;
} finally {
try {
ois.close();
} catch (Throwable e) {
}
}
return result;
}
It seems that i can convert the object into a byte array, but every time i read the object back it returns null
your code works fine for me:
import java.io.*;
class Foo implements Serializable {
#Override public String toString() {
return "Foo [x="+x+"]";
}
int x;
}
class Bar implements Serializable {
#Override public String toString() {
return "Bar [foo="+foo+"]";
}
Foo foo;
}
public class Soxx {
public static byte[] getSerializedObject(Serializable s) {
ByteArrayOutputStream baos=new ByteArrayOutputStream();
ObjectOutputStream oos=null;
try {
oos=new ObjectOutputStream(baos);
oos.writeObject(s);
} catch(IOException e) {
return null;
} finally {
try {
oos.close();
} catch(IOException e) {}
}
byte[] result=baos.toByteArray();
return result;
}
//read object
public static Object readSerializedObject(byte[] in) {
Object result=null;
ByteArrayInputStream bais=new ByteArrayInputStream(in);
ObjectInputStream ois=null;
try {
ois=new ObjectInputStream(bais);
result=ois.readObject();
} catch(Exception e) {
result=null;
} finally {
try {
ois.close();
} catch(Throwable e) {}
}
return result;
}
public static void main(String[] args) {
Foo foo=new Foo();
foo.x=42;
Bar bar=new Bar();
bar.foo=foo;
byte[] bytes=getSerializedObject(bar);
Object object=readSerializedObject(bytes);
System.out.println(object);
}
}
outputs: Bar [foo=Foo [x=42]]
I would like to write serializer for Ehcache of Optional class. I know, that optional member is seriazizable, so I write:
#Override
public ByteBuffer serialize(Optional object) throws SerializerException {
if( object.isPresent() ) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
return ByteBuffer.wrap(baos.toByteArray()); // excess copying
} catch (IOException e) {
throw new AssertionError(e);
}
}
else {
return ByteBuffer.wrap(new byte[] {});
}
}
#Override
public Optional read(ByteBuffer binary) throws ClassNotFoundException, SerializerException {
if( binary.array().length > 0 ) {
try {
byte[] buf = binary.array();
ByteArrayInputStream bais = new ByteArrayInputStream(buf);
ObjectInputStream ois = new ObjectInputStream(bais);
Object object = ois.readObject();
return Optional.of(object);
} catch (IOException e) {
throw new AssertionError(e);
}
}
else {
return Optional.empty();
}
}
I confused by commented line, which includes excess copying of data. Can I avoid it and serialize directly with ByteBuffer?
While does Ehcache seriazliers based of ByteBuffer?
ByteBuffer.wrap() doesn't actually copy data. As the name implies it wraps the array, so any changes to the original array would also be reflected in the buffer.
Sadly, you can't do Java serialization on a ByteBuffer. You are doing the same thing as the built-in PlainJavaSerializer of Ehcache.
By the way, you could remove a lot of code by doing this:
public class OptionalSerializer<T> implements Serializer<Optional<T>> {
private final PlainJavaSerializer<T> serializer;
public OptionalSerializer(ClassLoader classLoader) {
serializer = new PlainJavaSerializer<>(classLoader);
}
#Override
public ByteBuffer serialize(Optional<T> object) throws SerializerException {
return object.map(serializer::serialize).orElse(ByteBuffer.allocate(0));
}
#Override
public Optional<T> read (ByteBuffer binary) throws ClassNotFoundException, SerializerException {
if(binary.array().length > 0) {
return Optional.of(serializer.read(binary));
}
return Optional.empty();
}
#Override
public boolean equals(Optional<T> object, ByteBuffer binary) throws ClassNotFoundException, SerializerException {
return object.equals(read(binary));
}
}
I have a problem with creation of AudioInputStream from Socket.
Here are the important parts:
public class SoundStream extends Thread {
private int port;
private String IP;
private Socket socket;
private SoundObject soundObject;
private OpenAL openAL;
private Source source;
private boolean run = true;
public SoundStream(int port, String IP, SoundObject soundObject) {
this.soundObject = soundObject;
this.port = port;
this.IP = IP;
}
public void run() {
try {
this.socket = new Socket(this.IP, this.port);
this.openAL = new OpenAL();
} catch (Exception e) {
e.printStackTrace();
}
this.mainCycleMethod();
}
private void mainCycleMethod() {
while (run) {
this.soundObject.blockAndWait();
switch (this.soundObject.getAndResetEvent()) {
case 0:
this.run = false;
this.close();
break;
case 1:
this.setPitch();
break;
case 2:
this.closeSource();
this.play();
break;
case 3:
this.pause(true);
break;
case 4:
this.pause(false);
break;
}
}
}
private BufferedInputStream getInputStream() throws Exception {
return new BufferedInputStream(socket.getInputStream());
}
private void setPitch() {
if(this.source != null) {
try {
this.source.setPitch(this.soundObject.getPitch());
} catch (ALException e) {
e.printStackTrace();
}
}
}
private void play() {
try {
AudioInputStream audioInputStream = new AudioInputStream(this.getInputStream(), this.soundObject.getAudioFormat(), AudioSystem.NOT_SPECIFIED);
// AudioInputStream audioInputStream_tmp = AudioSystem.getAudioInputStream(this.getInputStream());
// AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(this.soundObject.getAudioFormat(), audioInputStream_tmp);
this.source = openAL.createSource(audioInputStream);
this.source.setGain(1f);
this.source.play();
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void close() {
this.closeSource();
this.openAL.close();
try {
this.socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void closeSource() {
if(this.source!=null) {
this.source.close();
}
}
private void pause(boolean pause) {
if(this.source != null) {
try {
if (pause) {
this.source.pause();
} else {
this.source.play();
}
} catch (ALException ex) {
ex.printStackTrace();
}
}
}
}
public class SoundObject extends AbstractEventObject {
public AudioFormat getAudioFormat() {
boolean signed = false;
//true,false
boolean bigEndian = false;
//true,false
return new AudioFormat(this.frequency, this.bits, this.channels, signed, bigEndian);
}
.
.
.
.
}
This code throws UnsupportedAudioFileException at this line:
AudioInputStream audioInputStream_tmp = AudioSystem.getAudioInputStream(this.getInputStream());
However when I use this code:
AudioInputStream audioInputStream = new AudioInputStream(this.getInputStream(), this.soundObject.getAudioFormat(), 100000);
it plays the sound but only after it loads those 100000 sample frames to the audioinputstream. After it plays all the 100000 frames it finishes.
I guess that I would solve this issue if I could pass the AudioFormat directly as a parameter during the first AudioInputStream inicialization, but it doesn't seem to be possible.
I'm receiving the audio format specifications from server.
I think that one possible solution would be to create a dataline which I can pass as a parametr to AudioInputStream constructor. However I'm not sure how to get the data from the socket directly to dataline. I know of a solution that uses infinite loop, in which it reads the data and writes them to the dataline. But it seems to be wasteful. Is there a more direct approach?
I hope it's possible to solve using java-openAL library, because I need to change the speed and I hope I won't have to do it myself.
Thanks
I've finally solved the issue. As it turned out java-openAL has streaming support built in, but it wasn't in the documentation on GitHub so I didn't notice at first. There is a createOutputStream method in the Source class, which returns the OutputStream. You can write the bytes directly to the OutputStream.
Here is my code:
In this snippet I initialize OpenAL:
public void run() {
try {
this.socket = new Socket(this.IP, this.port);
this.openAL = new OpenAL();
} catch (Exception ex) {
Log.severe(ex.toString());
}
this.mainCycleMethod();
}
Here is my play method which is called when the InputStream is available:
private void play() {
try {
this.source = openAL.createSource();
this.outputWriter = new OutputWriter(this.socket.getInputStream(), this.source, this.soundObject.getAudioFormat());
this.source.setGain(1f);
this.outputWriter.start();
} catch (Exception ex) {
Log.severe(ex.toString());
}
}
You have to use createSource method without parameters, it returns new instance of Source. Don't call the play method on source, it's handled by the SourceOutputStream class which instance is returned by the createOutputStream method. There is nothing wrong with calling the play method manually but I had a bad experience doing so when the buffers are empty. Basically it doesn't start playing later on when you begin streaming the data to OpenAL.
Here is my OutputWriter code which takes care of passing the bytes from InputStream to OutputStream:
package cz.speechtech.sound;
import org.urish.openal.ALException;
import org.urish.openal.Source;
import javax.sound.sampled.AudioFormat;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Created by honza on 16.12.15.
*/
public class OutputWriter extends Thread {
private InputStream inputStream;
private OutputStream outputStream;
private int STREAMING_BUFFER_SIZE = 24000;
private int NUMBER_OF_BUFFERS = 4;
private boolean run = true;
public OutputWriter(InputStream inputStream, Source source, AudioFormat audioFormat) {
this.inputStream = inputStream;
try {
this.outputStream = source.createOutputStream(audioFormat, this.NUMBER_OF_BUFFERS, 1024);
} catch (ALException e) {
e.printStackTrace();
}
}
public void run() {
byte[] buffer = new byte[this.STREAMING_BUFFER_SIZE];
int i;
try {
Thread.sleep(1000); // Might cause problems
while (this.run) {
i = this.inputStream.read(buffer);
if (i == -1) break;
outputStream.write(buffer, 0, i);
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void stopRunning() {
this.run = false;
try {
this.outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Have a nice day.
I got a very strange behaviour by reading bytes from the input stream of a socket.
In my project clients does requests to a service. For each request a new connection will be established.
At first the bytes are send that tells the service what kind of request will follow.
Then the request itself is send.
The service receives the bytes and proceeds the request. This does work for at least 95% of all request. For the remaining 5% there is a strange behaviour that i can not figure out.
The bytes are not all the bytes that got sended. But the most strange matter on this topic is that the missing bytes are not at the start or at the end of the stream. They are spread through the entire stream.
Sadly i can not provide the full code here cause it is work related. But i can provide the test code that shows the issue itself.
To figure out what is going on i wrote 2 classes. One derives from java.net.Socket and the other one from java.net.ServerSocket.
Here the code:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class DebugSocket extends Socket
{
private class InputStreamWrapper extends InputStream
{
private int
availables,
closes,
marksupporteds,
resets;
private List<Integer>
marks = new ArrayList<Integer>(),
reads = new ArrayList<Integer>();
private List<Long>
skips = new ArrayList<Long>();
#Override
public int available() throws IOException
{
availables++;
return DebugSocket.this.origininput.available();
}
#Override
public void close() throws IOException
{
closes++;
DebugSocket.this.origininput.close();
}
#Override
public synchronized void mark(int readlimit)
{
marks.add(readlimit);
DebugSocket.this.origininput.mark(readlimit);
}
#Override
public boolean markSupported()
{
marksupporteds++;
return DebugSocket.this.origininput.markSupported();
}
#Override
public synchronized void reset() throws IOException
{
resets++;
DebugSocket.this.origininput.reset();
}
#Override
public int read() throws IOException
{
int read = DebugSocket.this.origininput.read();
reads.add(read);
if ( read != -1 )
{
DebugSocket.this.inputdebugbuffer.write(read);
}
return read;
}
#Override
public int read(byte[] b) throws IOException
{
int read = DebugSocket.this.origininput.read(b);
DebugSocket.this.inputdebugbuffer.write(b, 0, read);
return read;
}
#Override
public int read(byte[] b, int off, int len) throws IOException
{
int read = DebugSocket.this.origininput.read(b, off, len);
DebugSocket.this.inputdebugbuffer.write(b, off, read);
return read;
}
#Override
public long skip(long n) throws IOException
{
long skipped = DebugSocket.this.origininput.skip(n);
skips.add(skipped);
return skipped;
}
}
private class OutputStreamWrapper extends OutputStream
{
private int
flushes,
closes;
#Override
public void close() throws IOException
{
closes++;
DebugSocket.this.originoutput.close();
}
#Override
public void flush() throws IOException
{
flushes++;
DebugSocket.this.originoutput.flush();
}
#Override
public void write(int b) throws IOException
{
DebugSocket.this.outputdebugbuffer.write(b);
DebugSocket.this.originoutput.write(b);
DebugSocket.this.originoutput.flush();
}
#Override
public void write(byte[] b) throws IOException
{
DebugSocket.this.outputdebugbuffer.write(b);
DebugSocket.this.originoutput.write(b);
DebugSocket.this.originoutput.flush();
}
#Override
public void write(byte[] b, int off, int len) throws IOException
{
DebugSocket.this.outputdebugbuffer.write(b, off, len);
DebugSocket.this.originoutput.write(b, off, len);
DebugSocket.this.originoutput.flush();
}
}
private static final Object
staticsynch = new Object();
private static long
idcounter = 0;
private final long
id;
private final ByteArrayOutputStream
inputdebugbuffer,
outputdebugbuffer;
private final InputStream
inputwrapper;
private final OutputStream
outputwrapper;
private InputStream
origininput;
private OutputStream
originoutput;
public InputStream getInputStream() throws IOException
{
if ( origininput == null )
{
synchronized ( inputdebugbuffer )
{
if ( origininput == null )
{
origininput = super.getInputStream();
}
}
}
return inputwrapper;
}
public OutputStream getOutputStream() throws IOException
{
if ( originoutput == null )
{
synchronized ( outputdebugbuffer )
{
if ( originoutput == null )
{
originoutput = super.getOutputStream();
}
}
}
return outputwrapper;
}
public DebugSocket()
{
id = getNextId();
inputwrapper = new InputStreamWrapper();
outputwrapper = new OutputStreamWrapper();
inputdebugbuffer = new ByteArrayOutputStream();
outputdebugbuffer = new ByteArrayOutputStream();
}
private static long getNextId()
{
synchronized ( staticsynch )
{
return ++idcounter;
}
}
}
import java.io.IOException;
import java.net.ServerSocket;
public class DebugServerSocket extends ServerSocket
{
public DebugServerSocket() throws IOException
{
super();
}
public DebugSocket accept() throws IOException
{
DebugSocket s = new DebugSocket();
implAccept(s);
return s;
}
}
The class DebugSocket takes notification of each interaction with the InputStream as well as OutputStream
Now when the issue occurs i always can see that bytes are missing.
Here an example:
The client send 1758 bytes. I got the 23 top bytes from the member outputdebugbuffer in the DebugSocket.
Bytes: 0,0,0,0,0,0,0,2,0,0,6,-46,31,-117,8,0,0,0,0,0,0,0,-83
The server received 227 Bytes. For debug issues i always do read the input stream till i get a -1, so that all bytes got proceeded. Now the 16 leading bytes on serverside that i got from the member inputdebugbuffer in the DebugSocket.
Bytes: 0,0,0,6,-46,31,-117,8,0,0,0,0,0,0,0,-83
As shown there are 7 bytes missing. the first 8 bytes are a long value this one i changed to a byte value for debugging. So i figured that the first byte is always correct.
If it were a failure in the code no request would be proceeded but as i said before this happens only to 5% of all connections at best.
Got anyone an idea whats going on here?
I also used the DataInputStream and DataOutputStream to send the data. I always flush after each write operation as you can see in the OutputStreamWrapper of the DebugSocket.
Do i miss something here?
If some other code is required i will try to post it.
P.S. The service is multi threaded and processes 100 request parallel. Also the clients are multi threaded and do 20 requests parallel. As said each request uses its one connection and closes this one right after the request got proceeded.
I hope someone got an idea on this matter.
Edit:
There is no main method to show that does anything like asked in the comments but here the the code blocks of the client and the server that are used.
Client: (Run parallel in 20 threads)
public void sendRequest(long _requesttype, byte[] _bytes)
{
Socket socket = null;
DataInputStream input = null;
DataOutputStream output = null;
InputStream sinput = null;
OutputStream soutput = null;
try
{
socket = new DebugSocket();
socket.connect(serveraddress);
sinput = socket.getInputStream();
soutput = socket.getOutputStream();
input = new DataInputStream(sinput);
output = new DataOutputStream(soutput);
output.writeLong(_requesttype);
output.flush();
soutput.flush();
output.write(_bytes);
output.flush();
soutput.flush();
// wait for notification byte that service had received all data.
input.readByte();
}
catch (IOException ex)
{
LogHelper.log(ex);
}
catch (Error err)
{
throw err;
}
finally
{
output.flush();
soutput.flush();
input.close();
output.close();
finishSocket(socket);
}
}
Server: (Run in a thread for each request. Up to 100 threads)
public void proceedRequest(DebugSocket _socket)
{
DataInputStream input = null;
DataOutputStream output = null;
InputStream sinput = null;
OutputStream soutput = null;
try
{
sinput = _socket.getInputStream();
soutput = _socket.getOutputStream();
input = new DataInputStream(sinput);
output = new DataOutputStream(soutput);
RequestHelper.proceed(input.readLong(), input, output);
// send notification byte to the client.
output.writeByte(1);
output.flush();
soutput.flush();
}
catch (IOException ex)
{
LogHelper.log(ex);
}
catch (Error err)
{
throw err;
}
finally
{
output.flush();
soutput.flush();
input.close();
output.close();
}
}
In the server code the readLong() already fails cause of the missing bytes.
Ok im done with all possible ways to locate the cause. From my experience with socket programming and parallel processing i can say that there is no bug in the code itself. Sniffers as well tell me that. Something on my machine is messing with the transmission.
I deactivated all i could think of (firewall/antivir/malware scanner) but no effect.
Got someone an idea what else could mess with tcp packages?
Edit:
Ok i got it. AVG 2014 is messing. Jetzt deactivating the components did not work. In Options->Settings there is a menu point were you can deactivate the AVG-Protection.
Got someone knowledge on this topic?
My guess is there is a bug somewhere else in the code. I copied the DebugSocket class from the question and created a MCVE (see below). It works fine, I was unable to reproduce the "server cannot read long-value" problem. Try modifying the code below to include more of the your own code until you can reproduce the problem, that should give you an idea where to look for the underlying cause.
import java.io.*;
import java.net.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
public class TestDebugSocket implements Runnable, Closeable {
public static void main(String[] args) {
TestDebugSocket m = new TestDebugSocket();
try {
m.run();
} catch (Exception e) {
e.printStackTrace();
} finally {
m.close();
}
}
final int clients = 20;
final boolean useDebugSocket = true;
final byte[] someBytes = new byte[1758];
final ThreadPoolExecutor tp = (ThreadPoolExecutor) Executors.newCachedThreadPool();
final AtomicLong clientId = new AtomicLong();
final ConcurrentLinkedQueue<Closeable> closeables = new ConcurrentLinkedQueue<Closeable>();
final long maxWait = 5_000L;
final CountDownLatch serversReady = new CountDownLatch(clients);
final CountDownLatch clientsDone = new CountDownLatch(clients);
ServerSocket ss;
int port;
#Override public void run() {
try {
ss = useDebugSocket ? new DebugServerSocket() : new ServerSocket();
ss.bind(null);
port = ss.getLocalPort();
tp.execute(new SocketAccept());
for (int i = 0; i < clients; i++) {
ClientSideSocket css = new ClientSideSocket();
closeables.add(css);
tp.execute(css);
}
if (!clientsDone.await(maxWait, TimeUnit.MILLISECONDS)) {
System.out.println("CLIENTS DID NOT FINISH");
} else {
System.out.println("Finished");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
close();
}
}
#Override public void close() {
try { if (ss != null) ss.close(); } catch (Exception ignored) {}
Closeable c = null;
while ((c = closeables.poll()) != null) {
try { c.close(); } catch (Exception ignored) {}
}
tp.shutdownNow();
}
class DebugServerSocket extends ServerSocket {
public DebugServerSocket() throws IOException {
super();
}
#Override public DebugSocket accept() throws IOException {
DebugSocket s = new DebugSocket();
implAccept(s);
return s;
}
}
class SocketAccept implements Runnable {
#Override public void run() {
try {
for (int i = 0; i < clients; i++) {
SeverSideSocket sss = new SeverSideSocket(ss.accept());
closeables.add(sss);
tp.execute(sss);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class SeverSideSocket implements Runnable, Closeable {
Socket s;
public SeverSideSocket(Socket s) {
this.s = s;
}
#Override public void run() {
Long l = -1L;
byte[] received = new byte[someBytes.length];
try {
DataInputStream in = new DataInputStream(s.getInputStream());
DataOutputStream out = new DataOutputStream(s.getOutputStream());
serversReady.countDown();
if (!serversReady.await(maxWait, TimeUnit.MILLISECONDS)) {
System.out.println("CLIENTS DID NOT CONNECT ON TIME TO SERVER");
}
l = in.readLong();
in.readFully(received);
out.writeByte(1);
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
// write to console at end to prevent synchronized socket I/O
System.out.println("received long: " + l);
close();
}
}
#Override public void close() {
TestDebugSocket.close(s);
s = null;
}
}
class ClientSideSocket implements Runnable, Closeable {
Socket s;
#SuppressWarnings("resource")
#Override public void run() {
Long l = -1L;
Byte b = -1;
try {
s = useDebugSocket ? new DebugSocket() : new Socket();
s.connect(new InetSocketAddress(port));
DataInputStream in = new DataInputStream(s.getInputStream());
DataOutputStream out = new DataOutputStream(s.getOutputStream());
l = clientId.incrementAndGet();
out.writeLong(l);
out.write(someBytes);
out.flush();
b = in.readByte();
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("long send: " + l + ", result: " + b);
close();
clientsDone.countDown();
}
}
#Override public void close() {
TestDebugSocket.close(s);
s = null;
}
}
static void close(Socket s) {
try { if (s != null) s.close(); } catch (Exception ignored) {}
}
}
I'm trying to use a function to open an arraylist of objects with fileIO but right now i'm stuck. I think there is something wrong with my setter function. (The file test.txt already exists)
The following classes I'm using to get the fileio function to work
Paslijst
public class Paslijst implements Serializable {
private ArrayList<Pas> paslijst;
public ArrayList<Pas> setPaslijst(ArrayList<Pas> paslijst){
this.paslijst = paslijst;
return paslijst;
}
FileIOPas
// This function opens a file
public Paslijst openen(String filenaam)
throws IOException, ClassNotFoundException {
FileInputStream fileInputStream = new FileInputStream(filenaam);
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
return (Paslijst) objectInputStream.readObject();
}
Main
public static void main(String[] args) {
FileIOPas fileiopas = new FileIOPas();
Paslijst paslijst = new Paslijst();
try {
paslijst.setPaslijst(fileiopas.openen("test.txt"));
}
catch (IOException e) {
System.out.println(" IO openen mislukt, want: " + e.toString());
}
catch (ClassNotFoundException e) {
System.out.println("class not found: " + e.toString());
}
}
You were passing wrong arguments in paslijst.setPaslijst().I have edited your class may this could Help.
public class Main {
public static void main(String[] args) {
FileIOPas fileiopas = new FileIOPas();
Paslijst paslijst = new Paslijst();
paslijst.setPaslijst(fileiopas.openen("test.txt"));
}
}
public class FileIOPas {
public ArrayList<Pas> openen(String filenaam) {
try (FileInputStream fileInputStream = new FileInputStream(filenaam);
ObjectInputStream objectInputStream = new ObjectInputStream(
fileInputStream);) {
return (ArrayList<Pas>) objectInputStream.readObject();
} catch (Exception exception) {
exception.printStackTrace();
}
return null;
}
}
public class Paslijst implements Serializable {
private ArrayList<Pas> paslijst;
public ArrayList<Pas> getPaslijst() {
return paslijst;
}
public void setPaslijst(ArrayList<Pas> paslijst) {
this.paslijst = paslijst;
}
}