`
rogerhunt
  • 浏览: 57752 次
  • 性别: Icon_minigender_1
  • 来自: 新加坡
社区版块
存档分类
最新评论

对read(byte[] b)跟readFully(byte[] b)的理解

阅读更多
对read(byte[] b)和readFully(byte[] b)的理解

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

1.代码的具体实现

2.方法何时返回

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


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


Java代码

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; 

  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代码

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; 

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


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


Java代码

//发送端:  
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); 

//发送端:
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个数据全部到达(数据缓冲区装满)
  • 大小: 36 KB
分享到:
评论

相关推荐

    JAVA流读取中英文字符

    提示:readFully(byte[] b, int off, int len) 将正好 len 个字节从此文件读入 byte 数组,并从当前文件指针开始 readByte() 从此文件读取一个有符号的八位值。 readChar() 从此文件读取一个字符。

    HTTP SPDY客户端开发包okhttp.zip

    示例代码: OkHttpClient client = new OkHttpClient();... byte[] response = readFully(in); return new String(response, "UTF-8"); } finally { if (in != null) in.close(); } } 标签:okhttp

    java 远程监控系统

    byte[] imageData = new byte[len]; dis.readFully(imageData); ImageIcon image = new ImageIcon(imageData); backImage.setIcon(image); jframe.repaint(); } } catch ...

    Android渠道打包工具packer-ng-plugin.zip

    注释包含Comment Length和File Comment两个字段,前者表示注释内容的长度,后者是注释的内容,正确修改这一部分不会对ZIP文件造成破坏,利用这个字段,我们可以添加一些自定义的数据,PackerNg项目就是在这里添加和...

    commons-io-2.CHM

    所以,我们理解它的方法并不是难事。因此,对于方法的用法总结如下: 1. buffer方法:将传入的流进行包装,变成缓冲流。并可以通过参数指定缓冲大小。 2. closeQueitly方法:关闭流。 3. contentEquals方法:比较...

Global site tag (gtag.js) - Google Analytics