要搞清楚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认为最适合发送的数据块(报文段或段)。报文段通过网络的传输到达指定地址(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('\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
分享到:
相关推荐
这个方法创建一个`RandomAccessFile`对象,然后使用`readFully`方法一次性读取文件的全部内容到byte数组。 以上三种方法各有优缺点。传统IO方式简单易懂,但效率相对较低;NIO的内存映射文件方法性能优异,但理解...
public static byte[] ReadFully(Stream stream) { byte[] buffer = new byte[32768]; using (MemoryStream ms = new MemoryStream()) { while (true) { int read = stream.Read(buffer, 0, buffer.Length); ...
public static byte[] ReadFully(Stream stream) { byte[] buffer = new byte[32768]; using (MemoryStream ms = new MemoryStream()) { while (true) { int read = stream.Read(buffer, 0, buffer.Length); ...
示例代码: OkHttpClient client = new OkHttpClient();... byte[] response = readFully(in); return new String(response, "UTF-8"); } finally { if (in != null) in.close(); } } 标签:okhttp
- `public final void readFully(byte[] b)`:从当前数据输入流中读取b.length个字节到该数组。 - `public final void readFully(byte[] b, int off, int len)`:从当前数据输入流中读取len个字节到该字节数组。 - `...
for (byte b : data) { hexString.append(String.format("%02X ", b & 0xFF)); } Log.d("TAG_DATA", "Hexadecimal data: " + hexString.toString()); ``` 最后,根据解析出的16进制数据,你可以执行相应的业务逻辑...
DataInputStream 的 `readFully(byte b[])` 方法可以从输入流中读取数据并填满字节数组 b 中。该方法可以重复读取直到填满字节数组 b。 DataInputStream 是 Java 中一个非常重要的输入流类,它提供了许多方法来读取...
本篇文章将详细讲解如何利用`FileSystem API`执行Hadoop文件的读写操作,带你一步步深入理解这一关键知识点。 首先,我们要了解`FileSystem API`的基本概念。它是一个抽象接口,用于与不同的文件系统(如HDFS、本地...
4. **读取操作**:`read()` 或 `readFully()` 方法用于从指定位置读取数据。`read()` 通常返回一个字节,而 `readFully()` 会读取指定长度的数据到字节数组中。例如,读取一个字节: ```java int byteRead = ...
read.readFully(buf); out.write(buf, 0, len); out.flush(); read.close(); } else { // ...处理文件不存在的情况... } } // ...其他代码... } } } ``` 以上代码展示了如何使用Java实现一个多线程的...
在示例代码中,`read()`方法被用来一次读取一个字节,而`read(byte[])`则用于一次读取多个字节。需要注意的是,当文件末尾到达时,`read()`方法会返回-1。 2、**按字符读取文件内容** 当处理包含文本的文件,如源...
- `read()` / `readFully(byte[] b)`:读取单个字节或指定长度的字节数组。 - `length()`:获取文件的总长度。 例如,以下代码片段展示了如何向文件末尾追加数据: ```java RandomAccessFile myFile = new ...
解决方法由于使用Java直接写入和读取ZIP文件的注释都不可行,使用Python又不方便与Gradle系统集成,所以只能自己实现注释的写入和读取。 实现起来也不复杂,就是为了提高性能,避免读取整个文件,需要在注释的最后...
它提供与`DataInputStream`相对应的写入方法,如`writeBoolean()`、`writeByte()`、`writeChar()`、`writeShort()`、`writeInt()`、`writeLong()`、`writeFloat()`、`writeDouble()`以及写入UTF编码字符串的`...