言成言成啊 | Kit Chen's Blog

理解字节流

发布于2022-07-09 16:25:31,更新于2022-07-10 23:21:54,标签:java  文章会持续修订,转载请注明来源地址:https://meethigher.top/blog

理解

先看代码吧。

字节流写入,常用的写法是两种形式。

一种是读一个写一个,如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void main(String[] args) throws Exception {
//该文件66byte
InputStream is = new FileInputStream("C:\\Users\\meethigher\\Desktop\\一键拉取博客.bat");
OutputStream os = new FileOutputStream("test.txt");
int b, count = 0;
while ((b = is.read()) != -1) {
os.write(b);
count++;
}
is.close();
os.close();
//输出66
System.out.println(count);
}

还有一种是读到内存里先存着,最后再一起写,如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void main(String[] args) throws Exception {
//该文件66byte
InputStream is = new FileInputStream("C:\\Users\\meethigher\\Desktop\\一键拉取博客.bat");
OutputStream os = new FileOutputStream("test.txt");
int b, count = 0;
byte[] bytes = new byte[10];
while ((b = is.read(bytes)) != -1) {
os.write(bytes, 0, b);
count++;
}
is.close();
os.close();
//输出7
System.out.println(count);
}

其实,我一开始疑问的是,字节流,读为啥是个int,写又是个int,而且这个范围还是0-255?难道是int表示的是读到内存里的字节流的偏移量?然后写的时候再将内存里偏移该大小的内容的写出去?难不成是读到了线程内存里?会不会存在多线程被别的线程给读取出去的情况?

以上是基础不扎实导致的思考,计算机课上虽然老师教过,但都是墨守成规,从来没去思考过,所以所学知识并没有真正串联起来。

此处int返回的是一个字节的值,这个值是闭区间0-255。

下面具体记录下,字节(byte)、位(bit)、字(word)之间的关系。

1个字节等于8个比特,按习惯上的写法,1B=8bit。比特英文翻译是binary digit (缩写bit,即二进制),比特也叫位

对于64位操作系统,1个字就表示了64位,即64bit=8byte=1word。

对于32位操作系统,1个字就表示了32位,即32bit=4byte=1word。

比特是计算机存储数据的最小单位,而字节是计算机处理数据的基本单位。

二进制数位也叫做比特位,例如0101,这是4位二进制,即4比特。

1个字节等于8比特,即8位,那么,最小就是0000 0000,换算成十进制就是0;最大就是1111 1111换算成十进制就是1+2+4+8+16+32+64+128=255。

这就是1个字节的整型范围为0-255的原因。

未解决Bug

提到这里,不得不记录一下之前遇到的bug。

去年做一个日志实时预览功能,就是用户可以在线观看系统的实时日志输出,最初的思路是ws+流实现的。流死循环,读到写入的字节再写出去。但是,在logback对日志进行归档时,他是把内容读出去归档后,就将该日志文件所有内容删除(后来为了解决这个问题,手动的通过file进行clear),这就导致我的流读不到内容或者乱码了。

我下面用个简单的例子重现一下。

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) throws Exception {
InputStream is = new FileInputStream("input.txt");
OutputStream os = new FileOutputStream("result.txt");
int b, count = 0;
while (true) {
if ((b = is.read()) != -1) {
System.out.println("新增内容了");
os.write(b);
os.flush();
}
}
}

我在input文件里面,输入你好,result同样有你好

此时删除字,result还是你好

再追加,result还是你好

再追加,result变成你好啊

最终的结果,input是你坏啊,result是你好啊

这时候,两边的结果完全不一样了

如果删除一个数字(占1字节),追加一个汉字(占3字节),此时只会写出2个字节,就会导致乱码。

流里面,应该有记录索引的偏移的。比如我现在字节边界是3,你给我删除了3个字节,那么再写入时,就得先补全这3个才行。

有人说用字符流,其实一个道理,也存在这个问题。

这个目前还不清楚如何解决,留个问号。

发布:2022-07-09 16:25:31
修改:2022-07-10 23:21:54
链接:https://meethigher.top/blog/2022/byte-stream/
标签:java 
付款码 打赏 分享
若无法评论请科学上网
Shift+Ctrl+1 可控制工具栏