gpt4 book ai didi

Java - 等待流完成写入?

转载 作者:太空狗 更新时间:2023-10-29 13:30:46 27 4
gpt4 key购买 nike

我有一个在 java 中运行的“服务器”,我通过字节数组将文件发送到“客户端”(android 系统)。该功能运行良好,但我注意到当我尝试发送更大的文件 (1MB+) 时,它在关闭前没有成功写入所有字节(例如:尝试发送 5mb,但它只发送了 902 字节)。有没有办法让代码在关闭流之前等待流完成写入?下面是代码和堆栈跟踪。本质上,发送消息方法在附加和发送文件时被调用(在处理 GUI 的类中)。在这种情况下,我并没有尝试从客户端接收数据,只是将数据发送给客户端。

编辑:我知道我现在只有字节数组设置为 1MB。我有 5MB,它仍然只写 <1MB。即使是 1MB,它仍然只写入 902 字节。

EDIT2:我已经在客户端发布了一些处理接收数据的代码。

public void sendMessage(File file) {
if(mOut != null) {
try {
FileInputStream inStream = new FileInputStream(file);
byte[] message = new byte[1024 * 1024];
inStream.read(message);
mOut.write(message, 0, message.length);
mOut.flush();
inStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

public void run() {
super.run();
running = true;
try {
System.out.println("S: Connecting...");
ServerSocket serverSocket = new ServerSocket(SERVERPORT);
Socket client = serverSocket.accept();
linked = true;
System.out.println("S: Receiving...");

try {
mOut =client.getOutputStream();
InputStream in = client.getInputStream();
while(running) {
byte[] message = new byte[1024 * 1024];
in.read(message);
if(message != null && messageListener != null) {
messageListener.messageReceived(message);
}
}
} catch (Exception ex) {
System.out.println("S:Error");
ex.printStackTrace();
} finally {
client.close();
System.out.println("S:Done");
}
} catch (Exception ex) {
System.out.println("S: Error");
ex.printStackTrace();
}

}
---------------------------------------------------------------------------
java.net.SocketException: Connection reset by peer: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(Unknown Source)
at java.net.SocketOutputStream.write(Unknown Source)
at Server.sendMessage(Server.java:34)
at ServerBoard$2.actionPerformed(ServerBoard.java:57)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$000(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at Server.run(Server.java:58)

这是客户端的代码 fragment 。

    public void run() {
mRun = true;
serverMessage = new byte[1024 * 1024];
try {
InetAddress serverAddr = InetAddress.getByName(SERVERIP);
Log.e("TCP Client", "C:Connecting...");
Socket socket = new Socket(serverAddr, SERVERPORT);
try {
in = socket.getInputStream();
while(mRun) {
in.read(serverMessage);
if(serverMessage != null && mMessageListener != null) {
mMessageListener.messageReceived(new String(serverMessage));
}
serverMessage = null;
}

Log.e("RESPONSE FROM SERVER","S:Received Message: '" + serverMessage + "'");

} catch(Exception ex) {
Log.e("TCP","S: Error", ex);
} finally {
socket.close();
}
} catch(Exception ex) {
Log.e("TCP","C: Error", ex);
}
}

最佳答案

首先,read的JavaDoc :

Reads some number of bytes from the input stream and stores them into the buffer array b. The number of bytes actually read is returned as an integer. This method blocks until input data is available, end of file is detected, or an exception is thrown.

由于源是一个套接字,它可能返回比预期更少的字节,即使缓冲区大小为 1 MByte,返回 902 KBytes 也是可以的。您必须循环直到流结束。

以下方法读取所有字节,然后调用监听器:

byte[] message = new byte[0]; 
byte[] buffer = new byte[4096];
int len;
while(( len = is.read( buffer )) > -1 ) {
byte[] tmp = new byte[message.length+len];
System.arraycopy( message, 0, tmp, 0, message.length );
System.arraycopy( buffer , 0, tmp, message.length, len );
message = tmp;
}
messageListener.messageReceived( message );

如您所见,发生了很多重新分配:您必须重新设计协议(protocol)以先发送文件的大小,然后分配一次接收缓冲区。

关于Java - 等待流完成写入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15744898/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com