• read(byte[] b)与readFully(byte[] b)


    转载于:http://yyzjava.iteye.com/blog/1178525

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

    1.代码的具体实现

    2.方法何时返回

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

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

    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),其中的部分关键代码如下

    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接收缓存中。应用程序如果需要获得这些数据,需要通过输入流读取并解析这些报文段。

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

    //发送端:  
    OutputStream out = ......;//通过TCP连接得到输出流对象  
    String content = "...";  
    byte[] data = content.getBytes();  
    output.write(data);  
    int len = data.length;  
    while (len++ < 30) {  
        output.writeByte('');//补够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个数据全部到达(数据缓冲区装满)

  • 相关阅读:
    解构操作的使用
    【Spring Boot】spring boot环境配置
    【Java】windows下直接运行Java程序(利用bat运行jar文件)
    【JavaScript】数学计算的函数与数字的格式化
    【python】控制台python代码导出成exe文件
    【centOS】centOS安装图形界面
    【网站】python的Windows平台的扩展包
    【Django】(4)创建其他页面
    【Django】(3)创建网页:学习笔记主页
    【Django】(2)Django模块创建应用程序
  • 原文地址:https://www.cnblogs.com/L-a-u-r-a/p/7089535.html
Copyright © 2020-2023  润新知