深入理解read(byte[] b)与readFully(byte[] b)

2023-05-16

要搞清楚read(byte[] b)和readFully(byte[] b)的区别,可以从以下方面着手分析:

1.代码的具体实现

2.方法何时返回

3.字节是以什么方式在网络上传输的


1.read(byte[] b)调用read(byte[] b,0,b.length),其中的部分关键代码如下

 

Java代码 复制代码  收藏代码
  1. int c = read();//读取字节流中的下一个字节  
  2.      if (c == -1) {   
  3.           return -1;   
  4.       }   
  5.       b[off] = (byte)c;   
  6.   
  7.       int i = 1;   
  8.       try {   
  9.           for (; i < len ; i++) {   
  10.               c = read();   
  11.               if (c == -1) {   
  12.                   break;   
  13.               }   
  14.               b[off + i] = (byte)c;   
  15.           }   
  16.       } catch (IOException ee) { }   
  17.       return i;  
  int c = read();//读取字节流中的下一个字节
       if (c == -1) {
            return -1;
        }
        b[off] = (byte)c;

        int i = 1;
        try {
            for (; i < len ; i++) {
                c = read();
                if (c == -1) {
                    break;
                }
                b[off + i] = (byte)c;
            }
        } catch (IOException ee) { }
        return i;
 

readFully(byte[] b)调用readFully(byte[] b,0,b.length),其中的部分关键代码如下

 

Java代码 复制代码  收藏代码
  1. int n = 0;   
  2.  while (n < len) {//该方法一直阻塞,直到读取到字节数据缓冲区装满  
  3.      int count = in.read(b, off + n, len - n);   
  4.      if (count < 0)   
  5.          throw new EOFException();   
  6.      n += count;   
  7.  }   
  8.   
  9. //read(bytes[] b,int off,int len)中的关键代码   
  10. int c = read();   
  11.  if (c == -1) {   
  12.      return -1;   
  13.  }   
  14.  b[off] = (byte)c;   
  15.   
  16.  int i = 1;   
  17.  try {   
  18.      for (; i < len ; i++) {   
  19.          c = read();   
  20.          if (c == -1) {   
  21.              break;   
  22.          }   
  23.          b[off + i] = (byte)c;   
  24.      }   
  25.  } catch (IOException ee) { }   
  26.  return i;  
       int n = 0;
        while (n < len) {//该方法一直阻塞,直到读取到字节数据缓冲区装满
            int count = in.read(b, off + n, len - n);
            if (count < 0)
                throw new EOFException();
            n += count;
        }

       //read(bytes[] b,int off,int len)中的关键代码
       int c = read();
        if (c == -1) {
            return -1;
        }
        b[off] = (byte)c;

        int i = 1;
        try {
            for (; i < len ; i++) {
                c = read();
                if (c == -1) {
                    break;
                }
                b[off + i] = (byte)c;
            }
        } catch (IOException ee) { }
        return i;
 

 


2.从以上代码,我们可以看到,read(byte[] b)一直阻塞等待读取字节,直到字节流中的数据已经全部读完(但这是可能对方还有数据正在传输过程中)。而readFully(byte[] b)是当数据缓冲区的空间还有剩余时会阻塞等待读取,直到装满。


3.下图反映了字节流数据是如何通过网络的

TCP报文传送图

应用程序用输出流将数据输入TCP的发送缓存中,这些数据被分割成TCP认为最适合发送的数据块(报文段或段)。报文段通过网络的传输到达指定地址(URL)的TCP接收缓存中,接收到的报文段很有可能不是顺序到达的,但TCP可以根据报文段的序号进行排序并存储在TCP接收缓存中。应用程序如果需要获得这些数据,需要通过输入流读取并解析这些报文段。



通过分析以上三个问题,我们可以解释以下代码存在的问题:

 

Java代码 复制代码  收藏代码
  1. //发送端:   
  2. OutputStream out = ......;//通过TCP连接得到输出流对象   
  3. String content = "...";   
  4. byte[] data = content.getBytes();   
  5. output.write(data);   
  6. int len = data.length;   
  7. while (len++ < 30) {   
  8.     output.writeByte('\0');//补够30个字节  
  9. }   
  10. //接收端:     
  11. InputStream in = ......;//通过TCP连接得到输入流对象   
  12. byte[] bytes = new byte[30];   
  13. in.read(bytes);  
//发送端:
OutputStream out = ......;//通过TCP连接得到输出流对象
String content = "...";
byte[] data = content.getBytes();
output.write(data);
int len = data.length;
while (len++ < 30) {
	output.writeByte('\0');//补够30个字节
}
//接收端:	
InputStream in = ......;//通过TCP连接得到输入流对象
byte[] bytes = new byte[30];
in.read(bytes);
 

由于字节数据是在网络中通过TCP连接进行传输,这些数据刚刚到达接收端(存储在TCP接收缓冲区)的可能只是其中的一部分数据,其他的数据可能还在传输中甚至在发送端的TCP缓存中。在调用read(byte[] b)读取数据时,b中得到的就是发出的30个字节的一部分。

要想完全获得这30个字节数据,合理的方法是用readFully(byte[] b)读取,因为该方法会一直阻塞等待,直到30个数据全部到达(数据缓冲区装满)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深入理解read(byte[] b)与readFully(byte[] b) 的相关文章

  • 在 Delphi 中如何位反映一个字节?

    在Delphi中是否有一种简单的方法来位反映字节变量 以便最高有效位 MSB 获得最低有效位 LSB 反之亦然 在代码中你可以这样做 function ReverseBits b Byte Byte var i Integer begin
  • Double 到 Byte 类型转换错误

    当执行转换时byte to double通过数学运算我得到了预期的结果 执行相同的数学运算来反转值的变化 只要我保持不变 就会得到正确的值double类型 但当最后我转变时double结果返回到bytevalue 转换结果不正确 1 这只是
  • 在 C/C++ 中读/写半字节(无位字段)

    有没有一种简单的方法可以在不使用位字段的情况下读取 写入字节中的半字节 我总是需要读取两个半字节 但需要单独写入每个半字节 Thanks 使用面膜 char byte byte byte 0xF0 nibble1 0xF write low
  • 撇号打印为 â\x80\x99

    import requests from bs4 import BeautifulSoup import re source url requests get http www nytimes com pages business inde
  • 将字节数组转换为十六进制字符串

    令人惊讶的是 对我来说 这段代码没有达到我想要的效果 fun ByteArray toHexString String return this joinToString it toString 16 事实证明Byte is signed 因
  • Erlang 中的大型可变字节数组

    当我在 Erlang 中编写一个简单的 Minecraft 服务器应用程序时 我现在关心的问题是如何有效地存储和修改块数据 对于那些不了解 Minecraft 内部结构的人 我需要在内存中存储大量高达 32kB 大小的二进制文件 100 1
  • 如何将单独的 int 值转换为十六进制字节数组

    我需要做一些 对我来说新的 int hex byte 工作 并且我正在努力使其正确 另一端的 tcp 服务器需要 Little Endian 我需要发送一个由十六进制值组成的字节数组 6000需要发送为 0x70 0x17 19需要发送为
  • 在 silverlight 中将对象(即任何对象,如人员、雇员)转换为 byte[]

    我有一个 person 对象 需要将其存储为 byte 并再次检索该 byte 并转换为 person 对象 并且 BinaryFormatter 在 silverlight 中不可用 由于 t0mm13b 提到的命名空间不是 Silver
  • C# 将字节转换为字符串并写入txt文件

    例如我该如何转换byte b new byte 1 b 1 255串起来 我需要一个值为 255 的字符串变量string text 255 然后将其存储在文本文件中 从字节开始 byte b new byte 255 string s E
  • Java NIO ByteBuffer,翻转后写入

    我是 Java ByteBuffers 的新手 想知道翻转后写入 ByteBuffer 的正确方法是什么 在我的用例中 我将一个输出缓冲区写入套接字 outBuffer flip Non blocking SocketChannel int
  • 使用十六进制数初始化无符号字节数组

    我知道无符号字节缺失于Java那么如何使用整数初始化字节数组0 到 255 十六进制 final byte assoc resp msg int new byte 0xe3 0x00 APDU CHOICE Type AareApdu 0x
  • 为什么java没有byte类型后缀? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 将位的字符串表示形式转换为字节

    我刚刚开始学习文件压缩 但遇到了一些障碍 我有一个应用程序将诸如 程序 之类的字符串编码为压缩的二进制表示形式 010100111111011000 请注意 这仍然存储为字符串 Encoding g 111 r 10 a 110 p 010
  • 使用 Cp500 编码陌生事物(LF 和 NEL)

    最近 在从字节转换为字符串 然后再从字符串转换为字节的过程中 我遇到了 Cp500 EBCDIC 编码的奇怪问题 问题在于一个特定的角色就是在这个转变过程中 被转变为这个角色 下面的代码验证了这一点 byte b25 0x25 byte b
  • c++ - 将“std::vector”的内容保存到文件

    我使用 writeFileBytes 下面的函数来写入a的内容std vector
  • 在 Go 中,如何将结构体转换为字节数组?

    我有一个我定义的结构实例 我想将其转换为字节数组 我尝试了 byte my struct 但这不起作用 另外 我还被指出二进制包 http golang org pkg encoding binary 但我不确定我应该使用哪个函数以及应该如
  • 如何使用 Python 将 4 个字节解释为 32 位浮点数

    我是 Python 语言的新手 我很难做一些我可以用 C 或 Java 轻松完成的事情 但由于某种原因 在 Python 中做起来似乎很复杂 我的数组中有以下四个字节 按大端顺序 0x64 0xD8 0x6E 0x3F 我事先已经知道这些字
  • 如何在Python中正确声明ctype结构+联合?

    我正在制作一个二进制数据解析器 虽然我可以依靠 C 但我想看看是否可以使用 Python 来完成该任务 我对如何实现这一点有一些了解 我当前的实现如下所示 from ctypes import class sHeader Structure
  • 字节数组到 Excel 工作簿

    我正在尝试将字节数组转换为 Excel 工作簿 当我这样做时 Response BinaryWrite renderedBytes 它工作正常并且文件符合预期 但是当我尝试用我在网上找到的这个来做到这一点时 private Object B
  • C++ 中的有符号短到字节

    我正在尝试使用 C 将十六进制数字转换为短数字 2 个字节 一切都很好 除了一件事 从短到字节的签名转换 最后一次测试 我发现了这个问题 但并不能真正从中受益 可移植的有符号 无符号字节转换 C https stackoverflow co

随机推荐