深入理解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) 的相关文章

  • python 字符串前面的 b 前缀是什么意思?

    在 python 源代码中我偶然发现了一个小b在字符串之前 例如 b abcdef 我知道关于u表示 unicode 字符串的前缀 以及r原始字符串文字的前缀 什么是b代表什么 它在哪种源代码中有用 因为它看起来就像一个没有任何前缀的纯字符
  • 了解录音机 read() 缓冲区 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我真的希望有人能帮助我 我目前正在使用 Android 录音机 一切正常 下一步是处理我调用时从缓冲区返回的字节read 作为一名退出了一
  • C# 中 bool* 的用处

    我可以用吗bool 以任何有意义的方式 我将如何转换bool to a byte例如 或存储bool 以一个字节为单位 我的目标是在我的项目中管理我自己的记忆 具体细节并不重要 只是我喜欢做的事情 现在我希望能够存储我自己的变量 并且我恰好
  • 系统中 1 字节!= 8 位? [复制]

    这个问题在这里已经有答案了 我一直读这样的句子 不要依赖 1 个字节就是 8 位大小 use CHAR BIT而不是 8 作为常量在位和字节之间转换 et cetera What real life systems are there to
  • JavaScript 中的 Java byteArray 等效项

    我正在尝试确定哪种编码方案将为 jpeg 文件类型提供数字 1 或 40 文件的起始数字 我正在开发的 REST API 需要一个类似于 1 94 43 34 等 的字节数组 在node js中 我可以将字节数组设置为十六进制或任何其他编码
  • 如何在Python中使用将双反斜杠替换为单反斜杠来替换字节字符串

    我想将 Python 中字节字符串的双反斜杠替换为单反斜杠 例如 有一个字节字符串 word b Z xa6 x97 x86j2 x08q r xca xe6m 我需要这个字节字符串 word b Z xa6 x97 x86j2 x08q
  • 如何在 C# 中将 byte[] 分配为指针

    我有一个函数 可以根据任何数据包的内容生成 CRC 校验字节 问题在于将该函数从 C 转换为 C C 代码 unsigned char GenerateCheckByte char packet int length unsigned lo
  • 撇号打印为 â\x80\x99

    import requests from bs4 import BeautifulSoup import re source url requests get http www nytimes com pages business inde
  • write() 参数必须是 str,而不是字节 [重复]

    这个问题在这里已经有答案了 我是一名初学者程序员 正在阅读 Python 初学者 一书 我在尝试为问答游戏编写高分函数时遇到了一个问题 当调用函数 highscore user highscore 时 我尝试相应地分配参数 以便我可以将信息
  • 静态 uint8_t 数组的输入过程和类型

    我目前正在尝试将 Arduino IDE 中的整数变量转换为静态 uint8 t 数组的值 我在用 include
  • 在 silverlight 中将对象(即任何对象,如人员、雇员)转换为 byte[]

    我有一个 person 对象 需要将其存储为 byte 并再次检索该 byte 并转换为 person 对象 并且 BinaryFormatter 在 silverlight 中不可用 由于 t0mm13b 提到的命名空间不是 Silver
  • C# 将字符转换为字节(十六进制表示)

    这似乎是一个简单的问题 但我无法弄清楚 我需要转换这个字符 lt 以字节 十六进制表示 表示 但如果我使用 byte b Convert ToByte lt i get 60 十进制表示 代替3c 60 0x3C 你已经有了正确的答案 但你
  • Java NIO ByteBuffer,翻转后写入

    我是 Java ByteBuffers 的新手 想知道翻转后写入 ByteBuffer 的正确方法是什么 在我的用例中 我将一个输出缓冲区写入套接字 outBuffer flip Non blocking SocketChannel int
  • 将位的字符串表示形式转换为字节

    我刚刚开始学习文件压缩 但遇到了一些障碍 我有一个应用程序将诸如 程序 之类的字符串编码为压缩的二进制表示形式 010100111111011000 请注意 这仍然存储为字符串 Encoding g 111 r 10 a 110 p 010
  • 在 Swift 中将 bytes/UInt8 数组转换为 Int

    如何将4字节数组转换为对应的Int let array UInt8 gt let value Int Example Input 0 0 0 x0e Output 14 我在互联网上找到的一些代码不起作用 let data NSData b
  • 使用字节将字母数字代码解码为键值对象

    我有一个来自 CS GO 游戏的 十字准线代码 CSGO O4Jsi V36wY rTMGK 9w7qF jQ8WB 我可以使用此函数解码一些值 import BigNumber from bignumber js Intentionall
  • 如何将 BYTE 数组转换为 char 数组以使用套接字 C++ 发送

    我有一些问题 我编写客户端服务器应用程序 其中使用 win 套接字发送和接收信息 在我的项目中需要发送BYTE数组到客户端 并在客户端上将此 char 数组转换为BYTE 我该如何创建它 请帮助我 因为send 函数只能发送char 谢谢
  • 如何使用 opencv 从字节显示视频?

    我正在开展一个项目 其中我们使用无线电调制解调器将数据 视频和遥测 从无人机传输到地面站 我们需要做的是实时显示视频 并能够知道 C 中的每一块遥测数据对应哪一帧 数据被解封装为遥测和视频 mpeg4 字节 由于我对 OpenCV 有一些经
  • 如何将字节数组转换为任何类型

    好的 我看到有人问如何将字节数组转换为int string Stream等等 答案各不相同 我个人还没有找到任何令人满意的答案 这里有一些我们想要将字节数组转换成的类型 UnityEngine Font可以吸收ttf data UnityE
  • 如何在Java中读取文件的最后“n”个字节

    如何在不使用 RandomAccessFile 的情况下从文件中读取最后 n 个字节 我的文件中的最后 6 个字节包含写回文件时的重要信息 我需要写入原始文件 然后将最后 6 个字节附加到其他地方 有什么指导吗 谢谢 你必须使用随机存取文件

随机推荐