ObjectInputStream 无法识别我的对象数据格式
ObjectInputStream is not able to recognize my Object Data format
我从以下代码中得到 EOFException
:
if (!(in.read() == -1))
{
CANDataInfo canData = (CANDataInfo) in.readObject();
System.out.println(canData.toString());
bw.write(canData.toString());
}
else
{
System.out.println("in.read() == -1 "+in.readObject());
jLab0x28.setText("No more bytes to read ");
}
我正在做一个套接字编程,其中服务器在某个时间间隔向客户端发送连续数据。通过套接字从服务器传递到客户端的数据是我开发的 CANDataInfo 对象类型。在客户端,当我打印数据时出现异常。由于对象的读取始终为 -1,因此我无法在某些文件上记录数据。
服务器端代码:
private ServerSocket server = null;
private Socket client = null;
private ObjectOutputStream out;
public static final String TAG = "APP1";
private void structureData(CANDataInfo canDataInfo)
{
try
{
if(server == null)
{
server = new ServerSocket(38301);
server.setSoTimeout(0);
}
client = server.accept();
Log.e("Server ", ""+client.isConnected());
Log.e("Data ", ""+canDataInfo.toString());
if(!client.isConnected())
{
Log.e("Server ", "client.isConnected() "+client.isConnected());
server.close();
}
out = new ObjectOutputStream(client.getOutputStream());
out.writeObject(canDataInfo);
out.close();
}
catch (Exception ex)
{
Log.e(CANManagerSetUp.TAG, "" + ex);
}
}
客户端代码 {不是一个干净的解决方案,请参考 EJP 的答案}
package com.cnh.socket.client;
import java.io.BufferedWriter;
import java.io.EOFException;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;
import javax.swing.JLabel;
import cantest.setup.CANDataInfo;
public class ThreadListener
{
Socket client = null;
ObjectInputStream in = null;
ListenFor0X28 runnableListenFor0X28 = null;
boolean continueMe;
public class ListenFor0X28 implements Runnable
{
JLabel jLab0x28;
public ListenFor0X28(){}
public ListenFor0X28(boolean stop, JLabel jLab0x28)
{
continueMe = stop;
this.jLab0x28 = jLab0x28;
}
public void run()
{
while(continueMe)
{
try
{
client = new Socket("localhost", 38301);
in = new ObjectInputStream(client.getInputStream());
if(client.isConnected())
{
jLab0x28.setText("Connected to Server");
appendFile(continueMe, jLab0x28, client);
}
else
{
System.out.println("Client is trying to connect");
jLab0x28.setText("Client is trying to connect");
}
}
catch(Exception ex)
{
ex.printStackTrace();
System.err.println("Before Append "+ex.toString());
}
}
}
}
BufferedWriter file = getFile("C:\ISSUE124_Resolved.txt");
private void appendFile(boolean continueMe, JLabel jLab0x28, Socket client)
{
try
{
if(!client.isClosed())
{
try
{
CANDataInfo canData = (CANDataInfo) in.readObject();
System.out.println(canData.toString());
file.write(canData.toString());
file.flush();
}
catch (EOFException exp)
{
continueMe = true;
System.out.println("A Stream has finished "+exp.toString()+"\n");
}
catch (ClassNotFoundException exp)
{
exp.printStackTrace();
System.err.println(exp.toString());
continueMe = false;
}
}
if(!continueMe)
{
file.close();
client.close();
in.close();
jLab0x28.setText("Socket is closed "+client.isClosed());
}
}
catch(IOException exp)
{
exp.printStackTrace();
System.err.println("Exception "+exp.toString());
jLab0x28.setText(exp.getMessage());
continueMe = false;
}
}
public BufferedWriter getFile(String path)
{
try
{
File file = new File(path);
if (!file.exists())
{
file.createNewFile();
}
FileWriter fw = new FileWriter(file.getAbsoluteFile());
return new BufferedWriter(fw);
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
}
}
异常堆栈:{解决之前}
java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at com.cnh.socket.client.ThreadListener.appendFile(ThreadListener.java:73)
at com.cnh.socket.client.ThreadListener.access[=13=](ThreadListener.java:65)
at com.cnh.socket.client.ThreadListener$ListenFor0X28.run(ThreadListener.java:48)
at java.lang.Thread.run(Unknown Source)
Data received in unknown format java.io.EOFException
在客户端
if (!(in.read() == -1))
{
CANDataInfo canData = (CANDataInfo) in.readObject();
System.out.println(canData.toString());
bw.write(canData.toString());
}
第一行从输入流中读取一个字节。这实际上是服务器写入的对象的第一个字节。因此,流不再正确对齐,因此以下 readObject()
失败。
您应该删除毫无意义且错误的 read()
调用,它会使您的对象流不同步。
同时,您还可以删除对 isConnected()
的所有冗余调用。他们什么也没做。您似乎热衷于调用通常不执行任何操作或试图预测未来的额外方法。尝试逐渐减少。
编辑 根据要求,我不仅要批评您的客户端,还要批评您的服务器代码。
服务器:
private void structureData(CANDataInfo canDataInfo)
{
try
{
if(server == null)
ServerSocket
应该已经在构造函数中创建和配置了。
{
server = new ServerSocket(38301);
server.setSoTimeout(0);
零是默认值。不要断言默认值。删除。
}
client = server.accept();
Log.e("Server ", ""+client.isConnected());
记录 isConnected()
是多余的。去掉。这将始终打印 true
。套接字 已连接 。你刚刚接受了它。如果你想记录一些有用的东西,记录客户端套接字的远程地址。
Log.e("Data ", ""+canDataInfo.toString());
没看过怎么会有数据?如果这是不变的服务器端数据,为什么要在每次接受时记录它?
if(!client.isConnected())
{
Log.e("Server ", "client.isConnected() "+client.isConnected());
server.close();
}
这个测试永远无法通过,代码块永远无法进入,如果奇迹般地进入,关闭服务器套接字是一个荒谬的反应。删除所有这些。
out = new ObjectOutputStream(client.getOutputStream());
out.writeObject(canDataInfo);
out.close();
}
catch (Exception ex)
不抓Exception
。抓住 IOException
.
{
Log.e(CANManagerSetUp.TAG, "" + ex);
您应该记录异常 class、它的消息和堆栈跟踪。 ""+ex
没有做到这一点。
}
}
客户:
public class ThreadListener
{
Socket client = null;
ObjectInputStream in = null;
ListenFor0X28 runnableListenFor0X28 = null;
boolean continueMe;
public class ListenFor0X28 implements Runnable
{
JLabel jLab0x28;
public ListenFor0X28(){}
public ListenFor0X28(boolean stop, JLabel jLab0x28)
{
continueMe = stop;
this.jLab0x28 = jLab0x28;
}
public void run()
{
while(continueMe)
{
try
{
client = new Socket("localhost", 38301);
in = new ObjectInputStream(client.getInputStream());
if(client.isConnected())
客户端已连接。当您构造 Socket
时,您只是连接了它。如果由于某种奇迹它没有连接,调用 getInputStream()
已经失败并返回 SocketException
。删除此测试。通常,在您的代码中对不可能为真或不能为假的事物进行了太多测试。
{
jLab0x28.setText("Connected to Server");
appendFile(continueMe, jLab0x28, client);
}
else
{
System.out.println("Client is trying to connect");
jLab0x28.setText("Client is trying to connect");
}
}
无法访问else
块,并且日志消息'Client is trying to connect'
不正确。删除整个块和 else
.
catch(Exception ex)
见上文。别抓Exception
。捕获编译器告诉您捕获的异常:在本例中 IOException
和与 DNS 相关的异常。
{
ex.printStackTrace();
System.err.println("Before Append "+ex.toString());
参见上文有关如何记录异常的信息。
}
}
}
}
BufferedWriter file = getFile("C:\ISSUE124_Resolved.txt");
private void appendFile(boolean continueMe, JLabel jLab0x28, Socket client)
{
try
{
if(!client.isClosed())
{
try
{
CANDataInfo canData = (CANDataInfo) in.readObject();
System.out.println(canData.toString());
file.write(canData.toString());
file.flush();
}
catch (EOFException exp)
{
continueMe = true;
System.out.println("A Stream has finished "+exp.toString()+"\n");
}
catch (ClassNotFoundException exp)
{
exp.printStackTrace();
System.err.println(exp.toString());
continueMe = false;
}
}
if(!continueMe)
{
file.close();
client.close();
in.close();
您不需要同时关闭输入流和套接字。两者都行。一般做法是关闭最外层的 writer/output 流(如果有的话),否则关闭输入流。
jLab0x28.setText("Socket is closed "+client.isClosed());
}
}
catch(IOException exp)
{
exp.printStackTrace();
System.err.println("Exception "+exp.toString());
jLab0x28.setText(exp.getMessage());
continueMe = false;
}
}
public BufferedWriter getFile(String path)
{
try
{
File file = new File(path);
if (!file.exists())
{
file.createNewFile();
}
您在这里 (1) 测试文件是否存在以及 (2) 创建新文件。
FileWriter fw = new FileWriter(file.getAbsoluteFile());
这里操作系统会创建一个新文件,不管你上面做了什么。因此 exists()/createNewFile()
部分完全是浪费时间:两个系统调用完全没有完成任何事情。删除它们。
return new BufferedWriter(fw);
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
练习不好。你应该让这个方法抛出 IOException
而不是在内部捕获它,或者 return null
。目前如果这个方法失败了,你去使用它的return值的时候会得到一个instrutableNullPointerException
}
}
我从以下代码中得到 EOFException
:
if (!(in.read() == -1))
{
CANDataInfo canData = (CANDataInfo) in.readObject();
System.out.println(canData.toString());
bw.write(canData.toString());
}
else
{
System.out.println("in.read() == -1 "+in.readObject());
jLab0x28.setText("No more bytes to read ");
}
我正在做一个套接字编程,其中服务器在某个时间间隔向客户端发送连续数据。通过套接字从服务器传递到客户端的数据是我开发的 CANDataInfo 对象类型。在客户端,当我打印数据时出现异常。由于对象的读取始终为 -1,因此我无法在某些文件上记录数据。
服务器端代码:
private ServerSocket server = null;
private Socket client = null;
private ObjectOutputStream out;
public static final String TAG = "APP1";
private void structureData(CANDataInfo canDataInfo)
{
try
{
if(server == null)
{
server = new ServerSocket(38301);
server.setSoTimeout(0);
}
client = server.accept();
Log.e("Server ", ""+client.isConnected());
Log.e("Data ", ""+canDataInfo.toString());
if(!client.isConnected())
{
Log.e("Server ", "client.isConnected() "+client.isConnected());
server.close();
}
out = new ObjectOutputStream(client.getOutputStream());
out.writeObject(canDataInfo);
out.close();
}
catch (Exception ex)
{
Log.e(CANManagerSetUp.TAG, "" + ex);
}
}
客户端代码 {不是一个干净的解决方案,请参考 EJP 的答案}
package com.cnh.socket.client;
import java.io.BufferedWriter;
import java.io.EOFException;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;
import javax.swing.JLabel;
import cantest.setup.CANDataInfo;
public class ThreadListener
{
Socket client = null;
ObjectInputStream in = null;
ListenFor0X28 runnableListenFor0X28 = null;
boolean continueMe;
public class ListenFor0X28 implements Runnable
{
JLabel jLab0x28;
public ListenFor0X28(){}
public ListenFor0X28(boolean stop, JLabel jLab0x28)
{
continueMe = stop;
this.jLab0x28 = jLab0x28;
}
public void run()
{
while(continueMe)
{
try
{
client = new Socket("localhost", 38301);
in = new ObjectInputStream(client.getInputStream());
if(client.isConnected())
{
jLab0x28.setText("Connected to Server");
appendFile(continueMe, jLab0x28, client);
}
else
{
System.out.println("Client is trying to connect");
jLab0x28.setText("Client is trying to connect");
}
}
catch(Exception ex)
{
ex.printStackTrace();
System.err.println("Before Append "+ex.toString());
}
}
}
}
BufferedWriter file = getFile("C:\ISSUE124_Resolved.txt");
private void appendFile(boolean continueMe, JLabel jLab0x28, Socket client)
{
try
{
if(!client.isClosed())
{
try
{
CANDataInfo canData = (CANDataInfo) in.readObject();
System.out.println(canData.toString());
file.write(canData.toString());
file.flush();
}
catch (EOFException exp)
{
continueMe = true;
System.out.println("A Stream has finished "+exp.toString()+"\n");
}
catch (ClassNotFoundException exp)
{
exp.printStackTrace();
System.err.println(exp.toString());
continueMe = false;
}
}
if(!continueMe)
{
file.close();
client.close();
in.close();
jLab0x28.setText("Socket is closed "+client.isClosed());
}
}
catch(IOException exp)
{
exp.printStackTrace();
System.err.println("Exception "+exp.toString());
jLab0x28.setText(exp.getMessage());
continueMe = false;
}
}
public BufferedWriter getFile(String path)
{
try
{
File file = new File(path);
if (!file.exists())
{
file.createNewFile();
}
FileWriter fw = new FileWriter(file.getAbsoluteFile());
return new BufferedWriter(fw);
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
}
}
异常堆栈:{解决之前}
java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at com.cnh.socket.client.ThreadListener.appendFile(ThreadListener.java:73)
at com.cnh.socket.client.ThreadListener.access[=13=](ThreadListener.java:65)
at com.cnh.socket.client.ThreadListener$ListenFor0X28.run(ThreadListener.java:48)
at java.lang.Thread.run(Unknown Source)
Data received in unknown format java.io.EOFException
在客户端
if (!(in.read() == -1))
{
CANDataInfo canData = (CANDataInfo) in.readObject();
System.out.println(canData.toString());
bw.write(canData.toString());
}
第一行从输入流中读取一个字节。这实际上是服务器写入的对象的第一个字节。因此,流不再正确对齐,因此以下 readObject()
失败。
您应该删除毫无意义且错误的 read()
调用,它会使您的对象流不同步。
同时,您还可以删除对 isConnected()
的所有冗余调用。他们什么也没做。您似乎热衷于调用通常不执行任何操作或试图预测未来的额外方法。尝试逐渐减少。
编辑 根据要求,我不仅要批评您的客户端,还要批评您的服务器代码。
服务器:
private void structureData(CANDataInfo canDataInfo)
{
try
{
if(server == null)
ServerSocket
应该已经在构造函数中创建和配置了。
{
server = new ServerSocket(38301);
server.setSoTimeout(0);
零是默认值。不要断言默认值。删除。
}
client = server.accept();
Log.e("Server ", ""+client.isConnected());
记录 isConnected()
是多余的。去掉。这将始终打印 true
。套接字 已连接 。你刚刚接受了它。如果你想记录一些有用的东西,记录客户端套接字的远程地址。
Log.e("Data ", ""+canDataInfo.toString());
没看过怎么会有数据?如果这是不变的服务器端数据,为什么要在每次接受时记录它?
if(!client.isConnected())
{
Log.e("Server ", "client.isConnected() "+client.isConnected());
server.close();
}
这个测试永远无法通过,代码块永远无法进入,如果奇迹般地进入,关闭服务器套接字是一个荒谬的反应。删除所有这些。
out = new ObjectOutputStream(client.getOutputStream());
out.writeObject(canDataInfo);
out.close();
}
catch (Exception ex)
不抓Exception
。抓住 IOException
.
{
Log.e(CANManagerSetUp.TAG, "" + ex);
您应该记录异常 class、它的消息和堆栈跟踪。 ""+ex
没有做到这一点。
}
}
客户:
public class ThreadListener
{
Socket client = null;
ObjectInputStream in = null;
ListenFor0X28 runnableListenFor0X28 = null;
boolean continueMe;
public class ListenFor0X28 implements Runnable
{
JLabel jLab0x28;
public ListenFor0X28(){}
public ListenFor0X28(boolean stop, JLabel jLab0x28)
{
continueMe = stop;
this.jLab0x28 = jLab0x28;
}
public void run()
{
while(continueMe)
{
try
{
client = new Socket("localhost", 38301);
in = new ObjectInputStream(client.getInputStream());
if(client.isConnected())
客户端已连接。当您构造 Socket
时,您只是连接了它。如果由于某种奇迹它没有连接,调用 getInputStream()
已经失败并返回 SocketException
。删除此测试。通常,在您的代码中对不可能为真或不能为假的事物进行了太多测试。
{
jLab0x28.setText("Connected to Server");
appendFile(continueMe, jLab0x28, client);
}
else
{
System.out.println("Client is trying to connect");
jLab0x28.setText("Client is trying to connect");
}
}
无法访问else
块,并且日志消息'Client is trying to connect'
不正确。删除整个块和 else
.
catch(Exception ex)
见上文。别抓Exception
。捕获编译器告诉您捕获的异常:在本例中 IOException
和与 DNS 相关的异常。
{
ex.printStackTrace();
System.err.println("Before Append "+ex.toString());
参见上文有关如何记录异常的信息。
}
}
}
}
BufferedWriter file = getFile("C:\ISSUE124_Resolved.txt");
private void appendFile(boolean continueMe, JLabel jLab0x28, Socket client)
{
try
{
if(!client.isClosed())
{
try
{
CANDataInfo canData = (CANDataInfo) in.readObject();
System.out.println(canData.toString());
file.write(canData.toString());
file.flush();
}
catch (EOFException exp)
{
continueMe = true;
System.out.println("A Stream has finished "+exp.toString()+"\n");
}
catch (ClassNotFoundException exp)
{
exp.printStackTrace();
System.err.println(exp.toString());
continueMe = false;
}
}
if(!continueMe)
{
file.close();
client.close();
in.close();
您不需要同时关闭输入流和套接字。两者都行。一般做法是关闭最外层的 writer/output 流(如果有的话),否则关闭输入流。
jLab0x28.setText("Socket is closed "+client.isClosed());
}
}
catch(IOException exp)
{
exp.printStackTrace();
System.err.println("Exception "+exp.toString());
jLab0x28.setText(exp.getMessage());
continueMe = false;
}
}
public BufferedWriter getFile(String path)
{
try
{
File file = new File(path);
if (!file.exists())
{
file.createNewFile();
}
您在这里 (1) 测试文件是否存在以及 (2) 创建新文件。
FileWriter fw = new FileWriter(file.getAbsoluteFile());
这里操作系统会创建一个新文件,不管你上面做了什么。因此 exists()/createNewFile()
部分完全是浪费时间:两个系统调用完全没有完成任何事情。删除它们。
return new BufferedWriter(fw);
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
练习不好。你应该让这个方法抛出 IOException
而不是在内部捕获它,或者 return null
。目前如果这个方法失败了,你去使用它的return值的时候会得到一个instrutableNullPointerException
}
}