作者:庄严
链接:https://www.zhihu.com/question/28457447/answer/44911601
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
流只是一个比喻。
任何比喻都无法完美。
流比喻数据的均匀连续性。
你从水龙头接水,无论拿杯子,脸盘,还是桶。只要水流不断,你都可以接满。
假设水龙头吐出的是大小不一的冰块,那就不叫连续了。
当然,计算机最小单位是字节,所以流数据最小单位也是字节(byte)。当然可以通过写程序模拟以位(bit 每字节8位)为单位的bit流。
模拟bit流多用在压缩算法。平常我们更多时候是需要连续的字节以某种方式组合起来读入或写出,比如以字符形式就是两个两个读(char,在java里是两个字节。)。看看jdk里有什xxxstream的类。
你的问题是自我想像流一定是个管子。其实在计算机世界里,管子是管子,流是流。
以文件流为比喻。你下载了1个G的某片,存在磁盘上总要占用一大块磁盘空间(物理上很可能是不连续的,但暂时想像它们是家里瓷盘上的一汪水)然后你凑过嘴,把嘴嘟起来,陶醉(假装)地吸上一口,字节带着细微的水花从你嘴唇穿入,这时候磁盘的一汪字节和你产生吸力的嘴之间,没有吸管,但真的有流。
你说嘴巴吸不了磁盘上的字节。你说甚至一G的文件在磁盘上很可能是分在不连续的扇区存储的,怎么有连续的流呢?
你说得很对。。。也许你看本地片子时,突然某处稍卡了一下,你怀疑是不是正好上个字节和下个字节之间 隔了几个扇区几个磁道。。。但其实通常不是的。操作系统不会这么直接。它会趁你慢慢欣赏某些片段时,早就将数据从慢腾腾的磁盘预读到快如闪电的内存中了,这个位于磁盘和播放器程序之间的缓存区,是很像你说的管子,但它真的和流这个对象没有什么关系,在代码中的流对象看来 那缓存区就是操作系统提供的文件。
JAVA代码是在虚拟机上跑的,所以在操作系统自带的缓存区这管子后面,可能还要再接一截虚拟机提供的管子。并且,看过净水机的广告吧? 什么十八过滤芯层层净化,那就是JAVA虚拟机或运行时提供的,用于转换数据编码什么的。
流这个比喻的本质就是为了让某个对象可以均匀持续地吐出无间隔的数据,或者你可以向这个对象毫无压力地持续不断塞进数据。。。。至于那些管子。。。恰恰是因为现实世界不够符合这个要求,所以必须有。经典例子改成网上看超大的片子。我们希望网络是一个符合我们说的条件的流,它必须连续出数据,但它做不到,它卡卡卡的,太像是在咳嗽吐结石了……认真回答我,看片子很卡,你会有“流”的任何联想和感受吗。。怎么办?你先等等,操作系统已经准备了个长管子,帮你缓存一大段你再看,这回就很流很流的感觉了。
所以,管子什么的,那不是流,那是不得不要靠它们来装(装逼的装 不是装放的装)流的枝节。通常是伟大的C程序员们要管的事。
最后有关网线。。。你要从公司回家,公司是A端,家是B端,你是数据,两个问题请回答:
一,你回家不从任何路上经过,你闭上眼睛心里默念我要回家,然后就瞬间转移到家里出现了??
二,你拉开家门,你老婆会说:哟,从公司回来了呀? 还是她很认真严谨地说:哟,从马路上回来了呀?
再说三点:一,物理上你无法直接从公司转移到家,所以需要马路管子。二,你老婆关心以及认知你是从公司还是某些她不喜欢的店回来的,通常不关心你从哪条马路回来了。三,但你也不是一个流,除非哪天你有个孩子,并且孩子日志里写到:下午,爸爸陆陆续续地回来了。。。。。。。。。