Getting error NullPointerException while trying to identify if serialized object is available and receive it using socket. How to identify if ObjectInputStream has available object?
Firs off I try to read a text then try to read from the same socket Lot object ()which may not be there.
public class ThreadIn extends Thread{
BufferedReader in;
PrintStream outConsole;
Socket socket;
ObjectInputStream ois;
String str;
Lot lot;
ThreadIn(BufferedReader input, PrintStream inOutput, Socket s){
str = "";
in= input;
socket= s;
try {
ois = new ObjectInputStream(socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
outConsole = inOutput;
}
public void run() {
while(!EXIT_THREAD){
try {
if(in.ready()){
try {
str= in.readLine();
Thread.sleep(100);
} catch (IOException e) {
EXIT_THREAD= true;
break;
} catch (InterruptedException e) {
e.printStackTrace();
}
outConsole.println("Received:"+str);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if((Lot)ois.readObject() != null){
lot = (Lot)ois.readObject();
if (lot!=null){outConsole.println(lot.toString());}
outConsole.println((String)ois.readObject());
}
} catch (Exception e) {
e.printStackTrace();
}
}
if((Lot)ois.readObject() != null)
this part itself reads the object from Socket., So you are reading 3 times the object from Socket in your code. If you have only one Object coming in the socket, or more, you can read the object and catch the exception!.
Just like below
//..loop start
try {
lot = (Lot)ois.readObject();
}
catch (Exception e)
{
// do some handling, skip the object! put a continue: or something
}
//do what ever you want to do with `lot`
//..loop end
and now, as per your code, you have not initialized your ObjectInputStream Object.
Do a ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
If you omitted the code here, well my mistake, else pls do initialize the socket also!
As per the other answers, including the deleted ones, you are calling readObject() twice and throwing the first result away. You should reorganize your code so it can block in readObject().
You have other problems. You are testing the result of readObject() for null?, but it only returns null if you wrote a null at the sender. I suspect you are using this as an EOS test, but it is invalid. readObject() throws EOFException at EOS. You should reorganize your code so it can block in readObject().
Related
I am trying to create a new .ser file to store objects if there is not one already present. When this is ran, it throws an EOFException. What exactly is an EOFException and is this method correctly written to create and read a .ser file? Thanks for any feedback.
public void readDatabase() throws IOException {
File dataFile = new File("database.ser");
// If data file does not exist, create it.
if (!dataFile.exists()) {
System.out.println("database.ser does not exist, creating one now . . .");
// if the file doesn't exists, create it
dataFile.createNewFile();
return; // No need to try to read anything from an empty file, so return.
}
ObjectInputStream objectinputstream = null;
boolean cont = true;
try {
FileInputStream streamIn = new FileInputStream(dataFile);
objectinputstream = new ObjectInputStream(streamIn);
while (cont) {
Item obj = null;
try {
obj = (Item) objectinputstream.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (obj != null)
itemList.add(obj);
else
cont = false;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (objectinputstream != null) {
objectinputstream.close();
}
}
}
EOFException:
java.io.EOFException
at java.base/java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2758)
at java.base/java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:3253)
at java.base/java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:866)
at java.base/java.io.ObjectInputStream.<init>(ObjectInputStream.java:343)
at hardwarestore.HardwareStore.readDatabase(HardwareStore.java:254)
at hardwarestore.HardwareStore.<init>(HardwareStore.java:33)
at hardwarestore.MainApp.<init>(MainApp.java:24)
at hardwarestore.MainApp.main(MainApp.java:259)
EOFException stands for:
End of File Exception
This typically occurs when you try to read data from a file where the FileReader has reached the end of the file. In other words, no more data to read.
You should catch the exception and close your stream. as it indicates that you have read all the objects in the file. Referring to the answer in this question:
while (true) {
try {
// Read the next object from the stream. If there is none, the
// EOFException will be thrown.
Item obj = (Item) objectinputstream.readObject();
itemList.add(obj);
} catch (EOFException e) {
// If there are no more objects to read, return what we have.
return contactMap;
} finally {
// Close the stream.
in.close();
}
}
So I am creating a server that I am trying to get to handle ASCII data. While I can get the Streams to work and call the methods. However the listening thread to add items to a Queue (ArrayBlockingQueue), and it will loop until the queue is full with null data.
Server code, Client Handler (compressed, let me know if I left something out.):
class ClientThread extends Thread {
// ASCII commands defined here (byte NUL=0x00; byte SOH=0x01; etc.)
private Socket socket;
private InputStream sInput;
private OutputStream sOutput;
BlockingQueue<byte[]> queueIn = new ArrayBlockingQueue<>(30, true);
private boolean goodToGo = false;
ClientThread(Socket socket){
id = ++Server.uniqueId; /* To be replaced with UIDs */
this.socket = socket;
/* Create Data Streams */
try {
sInput = (socket.getInputStream());
sOutput= (socket.getOutputStream());
goodToGo = true;
} catch (IOException ex) {
ServerInit.logger.log(Level.WARNING, "Error Openning Streams!", ex);
}
}
#Override
public void run(){
boolean keepGoing = true;
System.out.println("Client thread started.");
/* Start listening thread */
new Thread() {
#Override
public void run(){
while(goodToGo) {
System.out.println("Listening thread looping.");
try {
byte[] temp = IOUtils.toByteArray(sInput); // read client input using Apache Commons IO.
// Add the result to the queue.
queueIn.put(temp);
} catch (EOFException eof){
ServerInit.logger.log(Level.INFO,"Remote client closed connection.");
close();
}
catch (IOException ex) {
ServerInit.logger.log(Level.WARNING, "Error Reading Stream!", ex);
close();
}
}
}
}.start();
while (keepGoing && goodToGo){
System.out.println("Main thread looping.");
try{
byte[] message = queueIn.take();
if (message.length >= 4){
/* Message picked apart and worked with here */
} else if (message.length == 0 ){
// Do nothing.
} else {
ServerInit.logger.log(Level.WARNING, "Unable to process item from queue.");
}
} catch (Exception e) {
/* Here just for completeness, I don't catch Exceptions this way. :) */
}
}
}
protected void close(){
// try to close the conection
goodToGo = false;
try {
if (sOutput != null) {
sOutput.close();
}
if (sInput != null) {
sInput.close();
}
if (socket != null) {
socket.close();
}
ServerInit.SERVER.remove(id);
} catch (Exception e){
ServerInit.logger.log(Level.FINER, "Error closing client connections.", e);
}
}
}
And client code:
public class TestClient{
public static void main(String args[]){
try{
Socket socket = new Socket("localhost", 5525);
OutputStream outputStream = socket.getOutputStream();
byte[] buffer = { 0x02, 0x05, 0x07, 0x04 };
outputStream.write(buffer);
outputStream.flush();
outputStream.close();
} catch (Exception e) {
/* Again, I don't catch exceptions like normally. */
}
}
}
My Questions: What is causing the "listening" thread to loop and add null data to queue indefinitely?
And While I know this is not the Code Review exchange, if anyone can think of better classes to utilize, If they could just mention it.
EDIT:
Following a suggestion, I changed the queue from an ArrayList<> to an ArrayBlockingQueue.
IOUtils.toByteArray() is not appropriate for this usage. It will read to end of stream and return you one big byte array, not a sequence of messages. So there is certainly no point in calling it twice, or in a loop. After the initial result, all you can get is an infinity of empty byte arrays.
I've not used IOUtils.toByteArray but my suspicion is that if there is no data in the stream when you call it then it either returns null or an empty array.
This makes sense if you think about it since otherwise it has no idea how many bytes to read. It has no way to know if you are sending an array containing 1, 4 or 1000 bytes so it just reads everything that is ready when you call it.
You need to somehow sleep between each call to toByteArray and ignore any empty responses. A better way would be to see if you can sleep until more data arrives on the socket.
i have this code to do chatting
but it did not work , but somebody told me that i should use byte array and a string but i did not understand i hope you can help me to fix this problem , this code belongs to the server...
public void run() {
try {
ServerSocket= new ServerSocket(44444);//inside there is the port mumber which will be gain later from firstscreen
ClientSocket= ServerSocket.accept();
OUT= new ObjectOutputStream(ClientSocket.getOutputStream());
IN=new ObjectInputStream(ClientSocket.getInputStream());
while (true){
Object input =IN.readObject();
textArea.setText(textArea.getText()+"Client:"+(String)input+"\n");//update the textarea
}//loop end
}catch (IOException e){
//joptionpane
e.printStackTrace();
} catch (ClassNotFoundException e) {
//joptionpane
e.printStackTrace();
}
}//end of try
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("Send")|| e.getSource() instanceof JTextField){
try {
if(textField.getText().isEmpty()) {
OUT.writeObject(textField.getText());
textArea.setText(textArea.getText()+"Assistant:"+textField.getText()+"\n");}
}
catch (IOException c){
c.printStackTrace();
}
}
I hope you understand that you are only letting just a SINGLE client connect to the server, since there cannot happen any other serverSocket.accept()
First, you are only sending the information if the textfield text is empty at if(textField.getText().isEmpty()) which is quite a nonsense, otherwise there is no call to send through socket any data.
Apart from this, I do not see the code for the actionPerformed block, which I assume you have coded it before with a JButton or so and implementing the jbutton.addActionListener()
Also, I hope ClientSocket is a class of your own, because a client is represented as a Socket, not ClientSocket.
On the other hand, I would suggest the following API writeUTF and forget about needing to cast the string into bytes or otherways, with the help of DataInput and DataOutputStreams.
The code would be left as:
public void run() {
try {
ServerSocket serverSocket= new ServerSocket(44444);//inside there is the port mumber which will be gain later from firstscreen
Socket clientSocket= serverSocket.accept();
DataOutputStream OUT = new DataOutputStream(clientSocket.getOutputStream());
DataInputStream IN = new DataInputStream(clientSocket.getInputStream());
while (true){
String input = IN.readUTF();
textArea.append(input+"\n"); //update the textarea
}//loop end
}catch (IOException e){
//joptionpane
e.printStackTrace();
} catch (ClassNotFoundException e) {
//joptionpane
e.printStackTrace();
}
}//end of try
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("Send")|| e.getSource() instanceof JTextField) {
try {
if(!textField.getText().isEmpty()) { //Do not forget to include the ! (NOT)
OUT.writeUTF(textField.getText());
textArea.setText(textArea.getText()+"Assistant:"+textField.getText()+"\n");
}
}
catch (IOException c){
c.printStackTrace();
}
}
}
I hope to have been able to have helped you.
I'm taking over an existing JAVA project which containing the following code:
class ConnectionHandler extends Thread {
private Socket socket;
public ConnectionHandler(Socket s) {
this.socket = s;
}
private void doSthForRequest(ObjectInputStream in, ObjectOutputStream out) throws Exception {
// Do something and write output to out:
// out.writeObject(someOutput);
}
public void run() {
ObjectOutputStream out = null;
ObjectInputStream in = null;
try {
in = new ObjectInputStream(socket.getInputStream());
out = new ObjectOutputStream(socket.getOutputStream());
while (true) {
out.reset();
doSthForRequest(in, out);
}
} catch (Exception ex) {
if (out != null && !socket.isOutputShutdown()) {
try {
out.writeObject(ex);
out.flush();
} catch (Exception ex2) {}
}
} finally {
if (out != null) {
try {
out.reset(); // any reason for this?
} catch (Exception ee) {}
}
if (out != null) {
try {
out.close();
} catch (Exception ee) {}
}
try {
socket.close();
} catch (Exception e) {}
}
socket = null;
}
}
There are ConnectionHandler threads which serving request and producing output on a socket. And my question is:
Does the reset() call still make any sense if there is a close() call immediately after it?
The original author just leaves one line comment // clear outputstream cache which makes me confused...
Appreciate your help!
No. reset() sends a tag over the wire that tells the peer to clear its handle table. As you're about to close the stream anyway, the reset operation has no meaning, and it's an extra network operation to go wrong. Just close it.
As for other problems:
Construct the ObjectOutputStream before the ObjectInputStream. Otherwise a deadlock can occur.
Use the try-with-resources syntax here. It will simplify the code a lot.
I'm trying to read an object from client program over tcp. As you can see in this line I created objectInput:
ObjectInputStream objectInput = new ObjectInputStream(incoming.getInputStream());
And then read my input from the other program. It used to work fine until i made minor changes to clean up the program. Personally Assume I added
objectInput.clsoe();
My question is, After reading the object should I close the objectInputStream or Keep remain without close? Should I close it straight away after using it or at the end of if block or at the end of program? What are the effect of the close? By the way I have read the close documentation.
Here is the error:
java.io.EOFException
at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2280)
at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:2749)
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:779)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:279)
at Server.ClientWorker.run(MyCollectionServer.java:116)
at java.lang.Thread.run(Thread.java:680)
Here is my code:
public static void main(String[] args) {
ServerSocket serverSocket = null;
try
{
serverSocket = new ServerSocket(port);
}
catch (IOException e)
{
e.printStackTrace();
}
while(true)
{
ClientWorker w;
try
{
w = new ClientWorker(serverSocket.accept());
Thread t = new Thread(w);
t.start();
}
catch(IOException e)
{
e.printStackTrace();
break;
}
}
}
}
class ClientWorker implements Runnable
{
.....
private Socket incoming;
public ClientWorker(Socket incoming)
{
myList = new ArrayList<PureAlbum>();
loadList();
this.incoming = incoming;
}
.....
public synchronized void run()
{
else if(request.compareTo("AddAlbum")==0)
{
try
{
ObjectInputStream objectInput = new ObjectInputStream(incoming.getInputStream()); //This is the line mentioned in the error
PureAlbum object = (PureAlbum) objectInput.readObject();
if(object instanceof CDAlbum)
{
CDAlbum a = (CDAlbum) object;
myList.add(a);
System.out.println("Artist = " + a.getArtist());
}
else if(object instanceof Client.au.edu.uow.Collection.DVDAlbum)
{
myList.add((DVDAlbum) object);
}
else
{
System.err.println("Warning : The object to add to database is unknown! "+ object.getClass() + "*");
System.exit(0);
}
}
catch (UnknownHostException e)
{
System.err.println("Can not read the host name");
e.printStackTrace();
}
catch (IOException e)
{
System.err.println("Can not read the FILE name"); //This exception has been called
e.printStackTrace();
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
Your code fragment is pretty long, so I will try to give you a general answer and it will hopefully help you.
The typical patterns of usage of stream.close() prior to java 7 are:
InputStream in = null;
try {
InputStream in = .....; // create your input stream;
// use input stream
} catch (IOException e) {
// do what you need here
} finally {
if (in != null) {
in.close();
}
}
or simply declare the method as throws IOException and then write:
InputStream in = null;
try {
InputStream in = .....; // create your input stream;
// use input stream
} finally {
if (in != null) {
in.close();
}
}
Pay atention that this example does not contain catch section.
Starting from java 7 we can enjoy the new facilities of the language:
try (
InputStream in = .....; // create your input stream;
) {
// use input stream
}
You even do not have to call close() at all. All resources defined into header of try block that implement interface Closable will be closed automatically.
This line of stack trace shows that the exception is occurring when you are initializing the ObjectInputStream, not when you are closing.
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:279)
The most likely cause is that the remote client did not open an ObjectOutputStream. It might have written some other kind of data, or it might have closed its output stream or simply exited.
You should close the Stream when you have completed your reading or writing.
here in this case , you should close the InputStream when you have read the file completely and you no longer require to read file from stream.
In Short , You should close the Stream when its work is over.
It may be in the end of program or after if loop....depends on your use case.
Hope this will help.
I am doing it this way (different example):
private void readFile() throws Exception {
FileInputStream fis = null;
ObjectInputStream ois = null;
Object aux = null;
try {
fis = new FileInputStream("lib.dat");
ois = new ObjectInputStream(fis);
do {
aux = ois.readObject();
if (aux instanceof MyObject)
this.myObjectInstance.add((MyObject) aux);
} while (true);
} catch (EOFException e) {
ois.close();
}
}
This way I am sending any relevant "Error" Exception upstairs to be handled, and once the EndOfFileException is launched this is specifically captured to close the stream properly.
The object has to be defined outside the Try block to be accessible from the Catch block.
The close() method could as well throw an IOException and this can't be caught by our Try block, this would have to be passed by the generic "throw Exception" of readFile() method.