How to create a inputStream with test data - java

I am trying write a unit test. In the class I am testing, I am passing a java.net.Socket object through the constructor. The variable of this is called connection. In that class, there is a line:
ObjectInputStream in = new ObjectInputStream(connection.getInputStream());
Now in my unit test I am passing a mocked Socket object when creating an instance of that class.
In my unit test I am writing the following:
when(socket.getInputStream()).thenReturn(getInputStream());
private InputStream getInputStream() throws IOException
{
InputStream d = new ReaderInputStream(new StringReader("test data"));
ObjectInputStream o = new ObjectInputStream(d);
return d;
}
but when running that, i get the following error:
java.io.StreamCorruptedException: invalid stream header: 64666466
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:783)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:278)
Not sure how to overcome this. The error is stemming from ObjectInputStream o = new ObjectInputStream(d);

ObjectInputStream validates header by checking input stream. In you are case, you are streaming data which supported by ObjectInputStream.
So, you have to use stream which can be understandable by ObjectInputStream i.e generated input data from ObjectOutputStream.
Here is one sample example;
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeUTF("Hello World");
InputStream d = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
ObjectInputStream o = new ObjectInputStream(d);

Related

SEVERE: null java.io.EOFException Can't read values twice from ObjectInputStream in Java

I'm trying to read values send from client on server. First time it works fine but reading again gives an Exception.
client code:
String extension=getFileExtension(file);
OutputStream out;
out = socket.getOutputStream();
ObjectOutputStream oout = new ObjectOutputStream(out);
oout.writeObject(extension);
Server Code
String extension="";
InputStream in;
in = socket.getInputStream();
ObjectInputStream iin = new ObjectInputStream(in);//It gives exception here second time in same running the program
extension = (String)iin.readObject();

OutputSteam is abstract

as the title says, getting the error "outputsteam is abstract". I'm new to Java so not quite sure how to go about solving it. My program is trying to send an arraylist of connections over a socket to a client, using this code;
public void sendList(Socket clientSocket, ArrayList connections) throws IOException
{
OutputStream outputStream = new OutputStream(clientSocket.getOutputStream(), true);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(connections);
System.out.println("List sent");
}
Thanks in advance!
The error message is telling you exactly what is wrong: You can't call a constructor on an abstract class, and instead will have to initiate one of the concrete subclasses of OutputStream. Perhaps a BufferedOutputStream that wraps your clientSocket OutputStream.
Why do you even have this line?
OutputStream outputStream = new OutputStream(clientSocket.getOutputStream(),
true);
Why not simply use directly use the OutputStream from the clientSocket?

Invalid stream header 434B0005 from client to server

I've serialized some objects so I can convert them to byte arrays for a TCP packet. When I send the objects from the server program to the client program, there are no issues and it works fine. However, even though the code between the server and client is identical, when I try to send objects from the client to the server I get an invalid header.
Here are the objects I'm serializing:
public static byte[] serialize(Hand c) throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(c);
return baos.toByteArray();
}
public static Hand deserialize(byte[] bytes) throws IOException, ClassNotFoundException
{
ByteArrayInputStream b = new ByteArrayInputStream(bytes);
ObjectInputStream o = new ObjectInputStream(b);
return (Hand) o.readObject();
}
and
public static byte[] serialize(Card c) throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(c);
return baos.toByteArray();
}
public static Card deserialize(byte[] bytes) throws IOException, ClassNotFoundException
{
ByteArrayInputStream b = new ByteArrayInputStream(bytes);
ObjectInputStream o = new ObjectInputStream(b);
return (Card) o.readObject();
}
Those are both taken from the Server program, but the code for the serialization is identical between the server and the client; I important the Card class and the Hand class from the Server to the Client precisely to make sure errors like this wouldn't occur.
The server can convert a Card or a Hand to a byte[] and write it over a DataOutputStream to the client, and the client can receive the Card or Hand through a DataInputStream, deserialize it, and read it with no problem. When I try to send a Card or a Hand from the Client to the Server, however, very rarely it works and usually I get a
Exception in thread "main" java.io.StreamCorruptedException: invalid stream header: 434B0005
at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
at java.io.ObjectInputStream.<init>(Unknown Source)
at Hand.deserialize(Hand.java:29)
at KoiKoi_TCP_Server.takeClientTurn(KoiKoi_TCP_Server.java:321)
at KoiKoi_TCP_Server.main(KoiKoi_TCP_Server.java:380)
where Hand.java.29 points at the line
ObjectInputStream o = new ObjectInputStream(b);
in the Hand deserialization method.
I understand that it's telling me that the header is invalid. I'm not sure how to fix it, because it only breaks going one direction and the code is identical. Suggestions?
I'm only sending a solitary object at a time, so I'm not initializing multiple ObjectInputStreams or anything.
I'm not initializing multiple ObjectOutputStreams or anything.
Yes you are. You are initializing a new ObjectOutputStream for every object, and then you're giving yourself the additional problem of knowing how many bytes to read in order to receive each object, and you're getting that wrong, so you're getting out of sync.
Get rid of all this. You don't need it. It is just adding problems. Just use a single ObjectOutputStream and ObjectInputStream, directly, for the life of the socket, constructed directly over the socket streams, and call writeObject() when you want to send an object, and readObject() when you want to read one. Two lines of code. Forget about the byte arrays and the ByteArray/DataInput/OutputStreams altogether.

StreamCorruptedException when de-serializing through ObjectInputStream

I am trying to test a program and for that I need to access ReadExternal function but I am getting StreamCorrupted exception on ObjectInputStream.
I know I need to use the object written by WriteObject but dont know how to do it...
ObjectOutputStream out=new ObjectOutputStream(new ByteArrayOutputStream());
out.writeObject(ss3);
ss3.writeExternal(out);
try{
ByteInputStream bi=new ByteInputStream();
bi.setBuf(bb);
out.write(bb);
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bb));
String s1=(String) in.readObject();
}
catch(Exception e){
e.printStackTrace();
}
Apparently, you are trying to write the same object twice to the output stream:
out.writeObject(ss3);
ss3.writeExternal(out); // <-- Remove this!
The second write makes wrong use of the writeExternal() method, which should never be called explicitly but will be called by the ObjectOutputStream.
And: out.write(bb); tries to write the content of bb to the ObjectOutputStream. That's probably not what you want.
Try it like this:
// Create a buffer for the data generated:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out=new ObjectOutputStream( bos );
out.writeObject(ss3);
// This makes sure the stream is written completely ('flushed'):
out.close();
// Retrieve the raw data written through the ObjectOutputStream:
byte[] data = bos.toByteArray();
// Wrap the raw data in an ObjectInputStream to read from:
ByteArrayInputStream bis = new ByteArrayInputStream( data );
ObjectInputStream in = new ObjectInputStream( bis );
// Read object(s) re-created from the raw data:
SomeClass obj = (SomeClass) in.readObject();
assert obj.equals( ss3 ); // optional ;-)
ss3.writeExternal(out);
You shouldn't be calling that method directly. You should be calling
out.writeObject(ss3);

Can I change the type of stream I'm using without closing and reopening the socket in Java?

I'm doing some socket programming in Java and I'd like to be able to change between using the ObjectOutputStream, the DataOutputStream, and the PrintWriter all within the same socket/connection. Is this possible and what is the best way to do it?
I've tried just creating both types of objects, for example ObjectOutputStream and DataOutputStream, but that doesn't seem to work.
The reason I want to switch between them is to, for example, send a text command "INFO" that signals I'm about to send an object with information or a command "DATA" signalling that I'm about to send data. Any advice on the best way to do this is appreciated.
You can only use one underlying stream type however you can get that data from anywhere.
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(s.getOutputStream()));
public static void writeObject(DataOutputStream dos, Serializable obj) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
oos.close();
dos.writeUTF("OBJECT");
byte[] bytes = baos.toByteArray();
dos.writeInt(bytes.length);
dos.write(bytes);
dos.flush();
}
public static void writeBytes(DataOutputStream dos, byte[] bytes) {
dos.writeUTF("BYTES");
dos.writeInt(bytes.length);
dos.write(bytes);
dos.flush();
}
public static void writeText(DataOutputStream dos, String text) {
dos.writeUTF("TEXT");
dos.writeUTF(text);
dos.flush();
}
Why do you want the *Stream to convert to the *Writer.
You can do what you want to do with *Stream.
Socket s = new Socket();
DataOutputStream stream = new DataOutputStream( s.getOutputStream() );
byte[] bytes = "INFO".getBytes();
stream.write(bytes);
//....
bytes = "DATA".getBytes();
stream.write(bytes);

Categories

Resources