Java 文件结束异常
Java End of File Exception
我正在使用 JavaFX 编写一个简单的即时消息传递程序,遇到了文件结束异常,经过数小时的调试我找不到解决方案。
我的程序分两部分编写,客户端和服务器端。它们相互发送序列化对象,其中包含完成所需操作所需的所有必要信息。当我开始在服务器中收到此错误时,我正在向我的程序添加其他功能。我已经删除了所有附加代码,但仍然收到此错误消息。我不明白为什么我会收到此错误,因为客户端和服务器都没有发送消息,这意味着没有文件可以到达结尾??
我注释掉调用方法 "sendMessage()" 的行,这似乎解决了问题,但我需要此方法才能工作。
下面是服务器的副本class
package instachatfx.server;
public class ServerMain {
private static HashSet<ObjectOutputStream> writers;
private static ArrayList<User> users = new ArrayList<>();
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
writers = new HashSet<>();
try (ServerSocket listener = new ServerSocket(Constants.
while (true) {
new Handler(listener.accept()).start();
}
} catch (IOException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
private static class Handler extends Thread {
private Socket socket;
private ObjectInputStream input;
private OutputStream os;
private ObjectOutputStream output;
private InputStream is;
private User user;
private String code;
public Handler(Socket socket) throws IOException {
this.socket = socket;
}
@Override
public void run() {
try {
is = socket.getInputStream();
input = new ObjectInputStream(is);
os = socket.getOutputStream();
output = new ObjectOutputStream(os);
while (socket.isConnected()) {
System.out.println("Waiting for packet...");
Packet inputmsg = (Packet) input.readObject();
if (inputmsg != null) {
switch (inputmsg.getHeader()) {
case REGISTER:
System.out.println("Case: REGISTER");
registerUser((User) inputmsg.getContent());
break;
case LOGIN:
System.out.println("Case: LOGIN");
loginUser((User) inputmsg.getContent());
break;
case CODE:
System.out.println("Case: CODE");
if (((String) inputmsg.getContent()).equalsIgnoreCase(code)) {
Constants.getDBManager().createNewUser(user);
loginUser(user);
} else {
sendMessage(PacketHeader.INCORRECT_CODE, "Incorrect code");
}
break;
case MESSAGE:
System.out.println("Case: MESSAGE");
sendToAll(inputmsg);
System.out.println(((Message) inputmsg.getContent()).getUser().toString() + ": " + ((Message) inputmsg.getContent()).getContent());
break;
default:
throw new HeaderNotFoundException("Server has no case for: " + inputmsg.getHeader().name());
}
}
}
} catch (SocketException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
} catch (HeaderNotFoundException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
} catch (EOFException ex)
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
} finally {
closeConnections();
}
}
private void sendToAll(Packet msg) throws IOException {
System.out.println("Send to all: " + msg.getHeader());
((Message) msg.getContent()).setUsers(users);
for (ObjectOutputStream writer : writers) {
writer.writeObject(msg);
writer.flush();
writer.reset();
}
}
private void sendToOthers(Packet msg) throws IOException {
System.out.println("Send to others: " + msg.getHeader());
((Message) msg.getContent()).setUsers(users);
for (ObjectOutputStream writer : writers) {
if (output != writer) {
writer.writeObject(msg);
writer.flush();
writer.reset();
}
}
}
/**
* Logs in a user
* @param u the user to be logged in
*/
private void loginUser(User u) {
try {
User us;
if ((us = Constants.getDBManager().loginUser(u)) != null) {
System.out.println("User found in database");
user = us;
writers.add(output);
users.add(user);
LoginMsg msg = new LoginMsg(user, users);
sendMessage(PacketHeader.LOGIN_SUCCESSFUL,
sendToOthers(new Packet(PacketHeader.MESSAGE, new Message(user.toString() + " has joined the chat", new User("SERVER", null))));
} else {
sendMessage(PacketHeader.LOGIN_FAIL, "Please check email and password");
}
} catch (IOException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void registerUser(User u) throws IOException{
user = u;
if (Constants.getDBManager().checkDeuplicateEmail(u.getEmail())) {
sendMessage(PacketHeader.EMAIL_ALREADY_USED, "The email address " + u.getEmail() + " has already been used to make an account");
System.out.println("Email already exists");
return;
} else if ((code = sendVerificationEmail(u)) == null) {
sendMessage(PacketHeader.EMAIL_NOT_VALID, "There was an error sending the email to "
+ u.getEmail() + ". Please make sure the email is correct");
System.out.println("email failed sending");
return;
}
sendMessage(PacketHeader.WAIT_FOR_CODE, "Type in code in email");
}
/**
* Sends an email to the user to verify that it is correct
*
* @param u The user to send the email to
* @return null - the email failed sending <br>
* random sting - the email successfully sent using this verification
* code
*/
private String sendVerificationEmail(User u) {
String code = RandomString.getAlphaNumericString(10);
if (Constants.getSendEmail().sendEmail(u, code)) {
return code;
}
return null;
}
/**
* Sends a packet to only the client
*
* @param packetHeader for the client to tell how to read in the message
* @param msg the message for the client
*/
private void sendMessage(PacketHeader packetHeader, Object msg) throws IOException {
System.out.println("Send to client: " + packetHeader);
Packet message = new Packet(packetHeader, msg);
//ERROR OCCURS HERE
output.writeObject(message);
output.flush();
}
private void closeConnections() {
if (user != null){
users.remove(user);
}
try {
sendToAll(new Packet(PacketHeader.MESSAGE, new Message(user.toString() + " has left the chat", new User("SERVER", null))));
} catch (IOException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
}
if (output != null){
writers.remove(output);
}
if (is != null) {
try {
is.close();
} catch (IOException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
if (os != null){
try {
os.close();
} catch (IOException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
if (input != null) {
try {
input.close();
} catch (IOException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
编辑:这里是堆栈跟踪
2019 年 11 月 11 日 12:44:21 下午 instachatfx.server.ServerMain$Handler 运行
严重:无
java.io.EOFException
在 java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2950)
在 java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1534)
在 java.io.ObjectInputStream.readObject(ObjectInputStream.java:427)
在 instachatfx.server.ServerMain$Handler.run(ServerMain.java:83)
I don't understand why I'm getting this error ...
您收到错误是因为一端已关闭其输出流...或整个套接字。这可能是显式关闭的结果,也可能是因为应用程序已退出。
... as neither the client nor the server are sending a message ...
应用程序(客户端或服务器)正在尝试读取一条消息,但不会收到任何消息,因为另一端已关闭该端正在尝试读取的流来自.
... meaning there's no file to reach the end of.
你的逻辑不正确。所指的"file"就是上面所指的流。如果关闭写入端,如果读取端尝试继续读取,则读取端会看到流结束/文件结束。
伪匿名评论者似乎发现了一个错误,可能可以解释您的问题。 Socket.isConnected()
方法不能用于测试套接字是否仍处于连接状态。 javadoc 状态:
public boolean isConnected()
Returns the connection state of the socket.
Note: Closing a socket doesn't clear its connection state, which means
this method will return true for a closed socket (see isClosed()
) if
it was successfully connected prior to being closed.
Returns:
true
if the socket was successfully connected to a server
(重点添加...)
如果您需要更多帮助,请提供适当的 minimal reproducible example,并确保包括异常的完整堆栈跟踪。
我正在使用 JavaFX 编写一个简单的即时消息传递程序,遇到了文件结束异常,经过数小时的调试我找不到解决方案。
我的程序分两部分编写,客户端和服务器端。它们相互发送序列化对象,其中包含完成所需操作所需的所有必要信息。当我开始在服务器中收到此错误时,我正在向我的程序添加其他功能。我已经删除了所有附加代码,但仍然收到此错误消息。我不明白为什么我会收到此错误,因为客户端和服务器都没有发送消息,这意味着没有文件可以到达结尾??
我注释掉调用方法 "sendMessage()" 的行,这似乎解决了问题,但我需要此方法才能工作。
下面是服务器的副本class
package instachatfx.server;
public class ServerMain {
private static HashSet<ObjectOutputStream> writers;
private static ArrayList<User> users = new ArrayList<>();
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
writers = new HashSet<>();
try (ServerSocket listener = new ServerSocket(Constants.
while (true) {
new Handler(listener.accept()).start();
}
} catch (IOException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
private static class Handler extends Thread {
private Socket socket;
private ObjectInputStream input;
private OutputStream os;
private ObjectOutputStream output;
private InputStream is;
private User user;
private String code;
public Handler(Socket socket) throws IOException {
this.socket = socket;
}
@Override
public void run() {
try {
is = socket.getInputStream();
input = new ObjectInputStream(is);
os = socket.getOutputStream();
output = new ObjectOutputStream(os);
while (socket.isConnected()) {
System.out.println("Waiting for packet...");
Packet inputmsg = (Packet) input.readObject();
if (inputmsg != null) {
switch (inputmsg.getHeader()) {
case REGISTER:
System.out.println("Case: REGISTER");
registerUser((User) inputmsg.getContent());
break;
case LOGIN:
System.out.println("Case: LOGIN");
loginUser((User) inputmsg.getContent());
break;
case CODE:
System.out.println("Case: CODE");
if (((String) inputmsg.getContent()).equalsIgnoreCase(code)) {
Constants.getDBManager().createNewUser(user);
loginUser(user);
} else {
sendMessage(PacketHeader.INCORRECT_CODE, "Incorrect code");
}
break;
case MESSAGE:
System.out.println("Case: MESSAGE");
sendToAll(inputmsg);
System.out.println(((Message) inputmsg.getContent()).getUser().toString() + ": " + ((Message) inputmsg.getContent()).getContent());
break;
default:
throw new HeaderNotFoundException("Server has no case for: " + inputmsg.getHeader().name());
}
}
}
} catch (SocketException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
} catch (HeaderNotFoundException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
} catch (EOFException ex)
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
} finally {
closeConnections();
}
}
private void sendToAll(Packet msg) throws IOException {
System.out.println("Send to all: " + msg.getHeader());
((Message) msg.getContent()).setUsers(users);
for (ObjectOutputStream writer : writers) {
writer.writeObject(msg);
writer.flush();
writer.reset();
}
}
private void sendToOthers(Packet msg) throws IOException {
System.out.println("Send to others: " + msg.getHeader());
((Message) msg.getContent()).setUsers(users);
for (ObjectOutputStream writer : writers) {
if (output != writer) {
writer.writeObject(msg);
writer.flush();
writer.reset();
}
}
}
/**
* Logs in a user
* @param u the user to be logged in
*/
private void loginUser(User u) {
try {
User us;
if ((us = Constants.getDBManager().loginUser(u)) != null) {
System.out.println("User found in database");
user = us;
writers.add(output);
users.add(user);
LoginMsg msg = new LoginMsg(user, users);
sendMessage(PacketHeader.LOGIN_SUCCESSFUL,
sendToOthers(new Packet(PacketHeader.MESSAGE, new Message(user.toString() + " has joined the chat", new User("SERVER", null))));
} else {
sendMessage(PacketHeader.LOGIN_FAIL, "Please check email and password");
}
} catch (IOException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void registerUser(User u) throws IOException{
user = u;
if (Constants.getDBManager().checkDeuplicateEmail(u.getEmail())) {
sendMessage(PacketHeader.EMAIL_ALREADY_USED, "The email address " + u.getEmail() + " has already been used to make an account");
System.out.println("Email already exists");
return;
} else if ((code = sendVerificationEmail(u)) == null) {
sendMessage(PacketHeader.EMAIL_NOT_VALID, "There was an error sending the email to "
+ u.getEmail() + ". Please make sure the email is correct");
System.out.println("email failed sending");
return;
}
sendMessage(PacketHeader.WAIT_FOR_CODE, "Type in code in email");
}
/**
* Sends an email to the user to verify that it is correct
*
* @param u The user to send the email to
* @return null - the email failed sending <br>
* random sting - the email successfully sent using this verification
* code
*/
private String sendVerificationEmail(User u) {
String code = RandomString.getAlphaNumericString(10);
if (Constants.getSendEmail().sendEmail(u, code)) {
return code;
}
return null;
}
/**
* Sends a packet to only the client
*
* @param packetHeader for the client to tell how to read in the message
* @param msg the message for the client
*/
private void sendMessage(PacketHeader packetHeader, Object msg) throws IOException {
System.out.println("Send to client: " + packetHeader);
Packet message = new Packet(packetHeader, msg);
//ERROR OCCURS HERE
output.writeObject(message);
output.flush();
}
private void closeConnections() {
if (user != null){
users.remove(user);
}
try {
sendToAll(new Packet(PacketHeader.MESSAGE, new Message(user.toString() + " has left the chat", new User("SERVER", null))));
} catch (IOException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
}
if (output != null){
writers.remove(output);
}
if (is != null) {
try {
is.close();
} catch (IOException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
if (os != null){
try {
os.close();
} catch (IOException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
if (input != null) {
try {
input.close();
} catch (IOException ex) {
Logger.getLogger(ServerMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
编辑:这里是堆栈跟踪
2019 年 11 月 11 日 12:44:21 下午 instachatfx.server.ServerMain$Handler 运行 严重:无 java.io.EOFException 在 java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2950) 在 java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1534) 在 java.io.ObjectInputStream.readObject(ObjectInputStream.java:427) 在 instachatfx.server.ServerMain$Handler.run(ServerMain.java:83)
I don't understand why I'm getting this error ...
您收到错误是因为一端已关闭其输出流...或整个套接字。这可能是显式关闭的结果,也可能是因为应用程序已退出。
... as neither the client nor the server are sending a message ...
应用程序(客户端或服务器)正在尝试读取一条消息,但不会收到任何消息,因为另一端已关闭该端正在尝试读取的流来自.
... meaning there's no file to reach the end of.
你的逻辑不正确。所指的"file"就是上面所指的流。如果关闭写入端,如果读取端尝试继续读取,则读取端会看到流结束/文件结束。
伪匿名评论者似乎发现了一个错误,可能可以解释您的问题。 Socket.isConnected()
方法不能用于测试套接字是否仍处于连接状态。 javadoc 状态:
public boolean isConnected()
Returns the connection state of the socket.
Note: Closing a socket doesn't clear its connection state, which means this method will return true for a closed socket (see
isClosed()
) if it was successfully connected prior to being closed.Returns:
true
if the socket was successfully connected to a server
(重点添加...)
如果您需要更多帮助,请提供适当的 minimal reproducible example,并确保包括异常的完整堆栈跟踪。