Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/213.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java-等待流完成写入?_Java_Android_Sockets_Bytearray_Outputstream - Fatal编程技术网

Java-等待流完成写入?

Java-等待流完成写入?,java,android,sockets,bytearray,outputstream,Java,Android,Sockets,Bytearray,Outputstream,我有一个用java运行的“服务器”,我通过字节数组向“客户端”(android系统)发送文件。该功能工作正常,但我注意到,当我尝试发送较大的文件(1MB+)时,它在关闭之前没有成功写入所有字节(例如:尝试发送5mb,但只发送902字节)。有没有办法让代码在关闭流之前等待流完成写入?下面是代码和堆栈跟踪。本质上,在附加和发送文件时(在处理GUI的类中)调用send message方法。在本例中,我没有尝试从客户端接收数据,只是将数据发送到客户端 public void run() {

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

    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);
    }
}
编辑:我知道我现在只将字节数组设置为1MB。我用的是5MB,它仍然只写了第一个,JavaDoc的:

从输入流中读取一定数量的字节并将其存储到 缓冲区数组b。实际读取的字节数返回为 整数。此方法阻止,直到输入数据可用,结束 检测到文件,或引发异常

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

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

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 );

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

在完成读取之前,您将读取缓冲区设置为空:

 in = socket.getInputStream();
 while(mRun) {
     in.read(serverMessage);
     if(serverMessage != null && mMessageListener != null) {
         mMessageListener.messageReceived(new String(serverMessage));
     }
     serverMessage = null;
}

这将导致NullPointerException,您的代码将关闭套接字。

设置
socket。setSendBufferSize(1024)
(用于发送)也要确保在接收时读取
1024
字节。

当字节缓冲区只有1MB时,无法写入大于1MB的文件。您正在填充缓冲区、写入缓冲区并关闭输出流。也许试着用一个BufferedReader和一个循环来代替Readah是的,我确实改变了它,看看我能写的最大值是多少。我的手机是5MB的,但它还没有写出全部内容。即使是1MB,它也只写入了902字节。您的while循环是否不止一次运行?始终在带套接字的“读取”周围放置一个循环。不过,当我遇到异常时,我不会尝试接收任何数据,因此我不明白读取和接收字节是如何产生问题的?“由对等方重置”,原因在另一端。张贴另一方的代码。我的答案适用于客户端:套接字在网络传输数据时提供数据,而不是在一个块中。您必须循环“read”。@kaptaincooke-当InputStream是一个套接字时,read()几乎不会返回超过65K的任何内容;通常小于1600字节。这是因为操作系统将在调用时返回所接收和缓冲的数据,这通常不是您所需要的那么多-基本上,当没有任何缓冲时,进程将等待,但只要至少有一个字节,您就会返回已有的数据。循环获取消息的所有内容;另外,请修改您的协议以预先发送消息的长度。这似乎有效。我还更改了sendmessage函数,以1KB块的形式发送数据。它可以很好地接收这些块并将它们拼凑在一起(但是,对于4MB的文件,客户端在一段时间后崩溃了。我猜这与内存有关吧?)
 in = socket.getInputStream();
 while(mRun) {
     in.read(serverMessage);
     if(serverMessage != null && mMessageListener != null) {
         mMessageListener.messageReceived(new String(serverMessage));
     }
     serverMessage = null;
}