简体   繁体   English

InputStream in.read()的行为与预期不同

[英]InputStream in.read() behaving differently than expected

I am trying to transfer a text file to another server using TCP and it is behaving differently than expected. 我正在尝试使用TCP将文本文件传输到另一台服务器,并且其行为与预期不同。 The code sending the data is: 发送数据的代码是:

        System.out.println("sending file name...");
        String outputFileNameWithDelimiter = outputFileName + "\r\n"; //These 4 lines send the fileName with the delimiter
        byte[] fileNameData = outputFileNameWithDelimiter.getBytes("US-ASCII");
        outToCompression.write(fileNameData, 0, fileNameData.length);
        outToCompression.flush();

        System.out.println("sending content...");
        System.out.println(new String(buffer, dataBegin, dataEnd-dataBegin));
        outToCompression.write(buffer, dataBegin, dataEnd-dataBegin); //send the content
        outToCompression.flush();

        System.out.println("sending magic String...");
        byte[] magicStringData = "--------MagicStringCSE283Miami".getBytes("US-ASCII"); //sends the magic string to tell Compression server the data being sent is done
        outToCompression.write(magicStringData, 0, magicStringData.length);
        outToCompression.flush();

Because this is TCP and you can't send discrete packets like in UDP, I expected all of the data to be in the input stream and I could just use delimiters to separate the file name, content, and ending string and then each in.read() would just give me the next subsequent amount of data. 因为这是TCP,并且不能像UDP中那样发送离散数据包,所以我希望所有数据都在输入流中,并且我可以使用定界符来分隔文件名,内容和结尾字符串,然后分别输入。 read()只会给我下一个后续的数据量。

Instead this is the data I am getting on each read: 相反,这是我每次读取时得到的数据:

On the first in.read() byteBuffer appears to only have "fileName\r\n". 
On the second in.read() byteBuffer still has the same information. 
On the third in.read() byteBuffer now holds the content I sent. 
On the fourth in.read() byteBuffer holds the content I sent minus a few letters.
On the fifth in.read() I get the magicString + part of  the message.

I am flushing on every send from the Webserver, but input streams don't seem to implement flushable. 我正在刷新来自Web服务器的每个发送,但是输入流似乎未实现可刷新。

Can anyone explain why this is happening? 谁能解释为什么会这样?

EDIT: This is how I am reading things in. Basically this in a loop then writing to a file. 编辑:这就是我在读东西的方式。基本上,这是在循环中然后写入文件。

 in.read(byteBuffer, 0, BUFSIZE);

If your expectation is that read will fill the buffer, or receive exactly what was sent by a single write() by the peer, it is your expectation that is at fault here, not read(). 如果您期望读取将填满缓冲区,或者恰好接收对等体通过单个write()发送的内容,那么您的期望是错误的,而不是read(). it isn't specified to transfer more than one byte at a time, and there is no guarantee about preserving write boundaries. 没有指定一次传输多个字节,并且不能保证保留写边界。

It is quite impossible to write correct code without storing the result of read() into a variable. 如果不将read()的结果存储到变量中,就不可能编写正确的代码。

When you read from an InputStream , you're giving it a byte array to write into (and optionally an offset and a maximum amount to read). InputStream读取时,将为其提供要写入的字节数组(以及可选的偏移量和最大读取量)。 InputStream makes no guarantees that the array will be filled with fresh data. InputStream不保证该数组将充满新数据。 The return value is the number of bytes that was actually read into it. 返回值是实际读入其中的字节数。

What's happening in your example is this: 您的示例中发生的事情是这样的:

  • The first TCP packet comes in with "fileName\\r\\n" , gets written into your buffer, everything fine so far. 第一个TCP数据包带有"fileName\\r\\n" ,被写入缓冲区,到目前为止一切正常。
  • You call read() again, but the next packet hasn't arrived yet. 您再次调用read() ,但是下一个数据包尚未到达。 read() will have returned 0 , because it didn't want to block until data arrived. read()将返回0 ,因为它不希望在数据到达之前阻塞。 So the buffer still contains "fileName\\r\\n" 因此缓冲区仍然包含"fileName\\r\\n" . Edit: as pointed out, read() always blocks until it reads at least one byte. 编辑:如前所述, read()始终阻塞,直到读取至少一个字节为止。 Don't really know why the buffer didn't change then. 真的不知道为什么那时缓冲区没有改变。
  • On the third read, the content has arrived. 在三读时,内容已到达。
  • The first bit of the content gets overwritten with the second part of the message, the last bit still contains part of the old message (I think that's what you meant). 内容的第一位被消息的第二部分覆盖,最后一位仍然包含旧消息的一部分(我想这就是您的意思)。
  • etc., you get the idea 等,你明白了

You need to check the return value, wait for the data to arrive, and only use as much of the buffer as was written by the last read() . 您需要检查返回值,等待数据到达,并且仅使用与上次read()写入的一样多的缓冲区。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM