IO(输入输出)中的字符流和字节流

总结:本文用比较浅显的语言来解释字符流、字节流、以及编码和解码。


  计算机中,无论是文本、图片还是音视频,所有的文件都是以二进制形式(字节)存在。这句话看起来好像没什么用,但其实蕴含的信息有助于我们理解字节流、字符流、编解码等内容。例如一个视频文件(假定文件名是a.mp4),这个文件躺在你的硬盘中。那么它其实是以二进制形式存在,说的简单些就是0和1的组合。
在电脑里面: a.mp4 <----等同于------> 0100010001000...
  但是我们用播放器(软件)打开这个视频,我们看到的不是01000100这样的冷冰冰的数字,而是图像和视频。这是因为播放器读取这个文件,并将其转化为我们肉眼看到的视频。文本也是同样的道理,假如有一个b.txt文件,我们使用软件打开以后,看到的是字符,而不是01000100这样的数字。这其实就是因为软件对文件进行了读取,并且进行了解码的过程。
  接下来,还是举文本为例。我们将b.txt的内容清空然后重新输入内容。这个时候,可以理解成我们通过键盘输入了一些字符串。那么软件又会对我们输入的内容进行编码,也即是说将我们输入的内容转换成010000100010格式的文件。这再次印证上面所说的内容——所有的文件都是以二进制形式(字节)存在(涉及用户输入输出的内容见下文2.2)。


2.1 不涉及用户输入的文件操作

2.1.1 字节流

  当操作不涉及用户的输入来操作文件(例如就想将从a.mp4复制出一个aa.mp4)时,使用字节流和字符流的原理都很好理解。
  inputstream和outputstream(输入和输出流)就像是一个人的左右手。左手是inputstream,用于拿原始文件的内容,而outputstream就像是右手,将左手传递来的东西放入到右边。这样就实现将物件从左放到右(也就是实现了数据的传输)。使用字节流的方式进行操作时,“左手”(FileInputstream)先从文件中“拿取”原始的01010格式的内容,然后"右手"(FileOutputStream)原封不动将这些信息进行传递。
  最原始的方法就是左手拿一个,然后交给右手,然后左手再拿一个,再给右手,这样一个一个字节的读取,但是速度很慢。所以可以人为在程序中设置缓冲区的大小,就好像在两边都增加一个箱子。等左边箱子装满了转移到右边。那么转移的次数就大大减少了,需要的时间也就缩短了。更便捷的做法是直接使用字节缓冲流(BufferedInputStream),它自身定义了一个大小为8192的字节数组作为缓冲区,无需自己再设置缓冲区大小。

2.1.2 字符流

  接下来我们换一个工人,他的左手和右手分别对应字符流FileReader和FileWriter。虽然说是字符流,但是左手拿到的仍旧是010100形式的字节。由于右手只能够传递字节,这时候就需要在程序中手动设置,将左手拿到的字节转化成字符。(后面会有其他的字符流可以简化这个工作,甚至像bufferedReader之类的包装流可以直接读取字符格式,不需要再转化成字符流)。
  从上面来看,字节流的操作明显要简单,而且还适用于音频、视频等多种格式的文件。而字符流应用于文本文件。那为什么还要字符流呢。注意,这是因为这里没有涉及用户输入等操作。

注:
  经过装饰设计模式后的 BufferReader类,就有了readLine方法,这个方法就能够读取整行,并且返回的还是String格式。所以相应的其判断到文件末尾的方法也由上面的while(len=in.read()!= -1)变成了while((str=br.readLine()) != null)。也即是说原来的bufferedInputStream文件拷贝过程是纯字节的过程,左手拿到的是二进制数组,右手出去的还是二进制数组(缓冲区内容就是二进制数组,默认8192个字节数组)。而现在bufferedreader是纯字节的过程。左手拿到的是字符串,右手出去的还是字符串。缓冲区内容现在不再是固定长度的字符串,而被规定为一行(这个说法不准确,可能本身也有固定的缓冲区)。
  可见,其实bufferedreader是专门针对文本文档设计的。而Bufferedinputstream的适用范围要更广,不仅可以用于文本,还可以用于图片、视频等各种文件。

2.2 涉及用户输入输出的操作


  当涉及用户输入输出时,情况就不一样了。举个例子,复制文件内容并且在cmd窗口打印出来,以String格式显示给用户,这就涉及用户输出。而当我们编辑文本并保存的时候,我们输入的是String格式的内容,但是文本最终需要保存为二进制文件(还是上面所说的,所有文件都以二进制形式存在)。这又涉及用户输入的问题。
  例如当我们想将String格式的内容(例如下面的"what are you doing")来写入文件时,如果使用字节输出流FileOutputStream的话需要先将字符串转换为字节(二进制)数组,然后再进行写入。

String str = “what are you doing”;
byte[] b = str.getBytes();
for (int i=0;i<b.length;i++){
      out.write(b[i])
}

而字符流不需要这么麻烦,同样上面的效果,只需要:

     String str = “what are you doing”;
    writer.write(str);

(当然,别忘了文件都是以二进制格式存在的,所以这里字符-->字节的过程只是在程序中被“省略”了而已)

2.3 编码与解码

  我们用播放器或者文本打开一个文件,那么究竟这个软件做了什么,播放器读取这个文件,其实就是通过io输入流读取文本的字节(01001格式的数据),然后按照不同的“分割方式”进行解码。如果源文件是用utf-8编码的,那么就应该用utf-8进行解码,最后显示在我们面前的就是正常的字符。如果你用不匹配的解码方式,那么就可能变成乱码。但是你关闭了这个文件以后它还是不变的,因为本质上还是那些个字节(就好像你有很多把钥匙,但是只有一两把才能正确打开门,这里的锁和钥匙就对应编码与解码方式)。
  如果我们使用某款文本编辑器对这个文件进行编辑。这时候就涉及到编码的问题了。还是那句话,计算机中所有的文件都必须以二进制形式存在。而文本编辑器读取的是我们输入的字符(String格式),为了转成二进制,就会以某种编码方式进行保存。
  再来联想我遇到过的乱码情况,我创建了某个网站应用。用浏览器打开以后网页出现乱码,不能正常显示中文,这时候是什么问题呢。这时候应该就是浏览器的解码方式和文本编辑器的编码方式(假定我们通过某款编辑器编辑应用文件)不一致的问题。例如文本编辑器的编码方式为utf-8,而浏览器的解码方式不匹配所导致
  例如某个java文件,可以用sublime和文本编辑器正常显示,但是用Eclipse就出现乱码现象。

文本编辑器可正常打开

sublime text也可以正常打开

而Eclipse无法正常显示

  这就是因为这个java文件本身是以某种编码(例如GBK)方式保存成0100010的二进制文件的,而我们用新的文本编辑器打开就是“将这些二进制数字进行解码”。但是原来GBK的如果用utf-8来进行解码就无法正常显示了。
文本内容----->被保存为二进制文件----->我们用不同的软件打开------>解码方式不同,显示错误。
  现在我们用一个笨一点的方法,在中间多加几个步骤:
文本内容----->被保存为二进制文件----->先用可以正常显示的文本编辑器打开,这时候又转成字符----->将能够正常显示字符的这个文件用不同编码(例如utf-8)方式另存为新的文档----->我们用不同的软件打开------>解码方式相同,显示正常。
  用这个新的文件替换掉原来的文件,问题解决。

Eclipse最终能成功打开

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容