04.JavaIO流问题

86次阅读

共计 5891 个字符,预计需要花费 15 分钟才能阅读完成。

目录介绍

4.0.0.1 说一下 Java IO 里面的常见类,字节流,字符流、接口、实现类、方法阻塞?
4.0.0.2 什么是比特 (Bit), 什么是字节 (Byte), 什么是字符 (Char), 它们长度是多少, 各有什么区别?
4.0.0.3 字符流和字节流有什么区别?如何选择字节流或者字符流?什么是缓冲区,有什么作用?
4.0.0.4 IO 流中用到哪些模式?谈一谈 IO 流中用到的适配器模式和装饰者模式的作用优势?
4.0.0.5 说一下对 NIO 的理解?NIO 和 IO 的主要区别?NIO 和 IO 如何影响应用程序的设计?
4.0.1.1 对字节流进行大量的从硬盘读取, 要用那个流, 为什么?

好消息

博客笔记大汇总【15 年 10 月到至今】,包括 Java 基础及深入知识点,Android 技术博客,Python 学习笔记等等,还包括平时开发中遇到的 bug 汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是 markdown 格式的!同时也开源了生活博客,从 12 年起,积累共计 500 篇 [近 100 万字],将会陆续发表到网上,转载请注明出处,谢谢!
链接地址:https://github.com/yangchong2…
如果觉得好,可以 star 一下,谢谢!当然也欢迎提出建议,万事起于忽微,量变引起质变!所有博客将陆续开源到 GitHub!

4.0.0.1 说一下 Java IO 里面的常见类,字节流,字符流、接口、实现类、方法阻塞?

输出流和输入流
输入流就是从外部文件输入到内存,输出流主要是从内存输出到文件。

IO 里面常见的类
IO 流中有很多类,IO 流主要分为字符流和字节流。字符流中有抽象类 InputStream 和 OutputStream,它们的子类 FileInputStream,FileOutputStream,BufferedOutputStream 等。字符流 BufferedReader 和 Writer 等。都实现了 Closeable, Flushable, Appendable 这些接口。程序中的输入输出都是以流的形式保存的,流中保存的实际上全都是字节文件。

IO 流中方法阻塞

java 中的阻塞式方法是指在程序调用改方法时,必须等待输入数据可用或者检测到输入结束或者抛出异常,否则程序会一直停留在该语句上,不会执行下面的语句。比如 read() 和 readLine() 方法。
技术博客大总结

4.0.0.2 什么是比特 (Bit), 什么是字节 (Byte), 什么是字符 (Char), 它们长度是多少, 各有什么区别?

什么是比特 (Bit)?
Bit 最小的二进制单位,是计算机的操作部分 取值 0 或者 1

什么是字节
Byte 是计算机操作数据的最小单位由 8 位 bit 组成 取值(-128-127)

什么是字符
Char 是用户的可读写的最小单位,在 Java 里面由 16 位 bit 组成 取值(0-65535)

各有什么区别
Bit 是最小单位 计算机 只能认识 0 或者 1

4.0.0.3 字符流和字节流有什么区别?如何选择字节流或者字符流?什么是缓冲区,有什么作用?

字符流和字节流区别

把二进制数据数据逐一输出到某个设备中,或者从某个设备中逐一读取一片二进制数据,不管输入输出设备是什么,我们要用统一的方式来完成这些操作,用一种抽象的方式进行描述,这个抽象描述方式起名为 IO 流,对应的抽象类为 OutputStream 和 InputStream,不同的实现类就代表不同的输入和输出设备,它们都是针对字节进行操作的。
在应用中,经常要完全是字符的一段文本输出去或读进来,用字节流可以吗?计算机中的一切最终都是二进制的字节形式存在。对于“中国”这些字符,首先要得到其对应的字节,然后将字节写入到输出流。读取时,首先读到的是字节,可是我们要把它显示为字符,我们需要将字节转换成字符。由于这样的需求很广泛,人家专门提供了字符流的包装类。
底层设备永远只接受字节数据,有时候要写字符串到底层设备,需要将字符串转成字节再进行写入。字符流是字节流的包装,字符流则是直接接受字符串,它内部将串转成字节,再写入底层设备,这为我们向 IO 设别写入或读取字符串提供了一点点方便。
技术博客大总结
字符流和字节流的使用非常相似,但是实际上字节流的操作不会经过缓冲区(内存)而是直接操作文本本身的,而字符流的操作会先经过缓冲区(内存)然后通过缓冲区再操作文件。

如何选择字节流或者字符流?

字符流是由 Java 虚拟机将字节转化为 2 个字节的 Unicode 字符为单位的字符而成的
如果是音频文件、图片、歌曲,就用字节流好点(避免数据丢失)
如果是关系到中文(文本)的,用字符流好点)

什么是缓冲区,有什么作用?

缓冲区就是一段特殊的内存区域,很多情况下当程序需要频繁地操作一个资源(如文件或数据库)则性能会很低,所以为了提升性能就可以将一部分数据暂时读写到缓存区,以后直接从此区域中读写数据即可,这样就显著提升了性能。
对于 Java 字符流的操作都是在缓冲区操作的,所以如果我们想在字符流操作中主动将缓冲区刷新到文件则可以使用 flush() 方法操作。

4.0.0.4 IO 流中用到哪些模式?谈一谈 IO 流中用到的适配器模式和装饰者模式的作用优势?

IO 流中用到哪些模式

大概有装饰者模式和适配器模式!
要知道装饰者模式和适配器模式的作用;其次,可以自己举个例子把它的作用生动形象地讲出来;最后,简要说一下要完成这样的功能需要什么样的条件。

谈一谈 IO 流中用到的适配器模式和装饰者模式的作用优势

装饰器模式:就是动态地给一个对象添加一些额外的职责(对于原有功能的扩展)。
// 把 InputStreamReader 装饰成 BufferedReader 来成为具备缓冲能力的 Reader。
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

1. 它必须持有一个被装饰的对象(作为成员变量)。
2. 它必须拥有与被装饰对象相同的接口(多态调用、扩展需要)。
3. 它可以给被装饰对象添加额外的功能。
比如,在 io 流中,FilterInputStream 类就是装饰角色,它实现了 InputStream 类的所有接口,并持有 InputStream 的对象实例的引用,BufferedInputStream 是具体的装饰器实现者,这个装饰器类的作用就是使得 InputStream 读取的数据保存在内存中,而提高读取的性能。

适配器模式:将一个类的接口转换成客户期望的另一个接口,让原本不兼容的接口可以合作无间。
// 把 FileInputStream 文件字节流适配成 InputStreamReader 字符流来操作文件字符串。
FileInputStream fileInput = new FileInputStream(file);
InputStreamReader inputStreamReader = new InputStreamReader(fileInput);

1. 适配器对象实现原有接口
2. 适配器对象组合一个实现新接口的对象
3. 对适配器原有接口方法的调用被委托给新接口的实例的特定方法 (重写旧接口方法来调用新接口功能。)
比如,在 io 流中,InputStreamReader 类继承了 Reader 接口,但要创建它必须在构造函数中传入一个 InputStream 的实例,InputStreamReader 的作用也就是将 InputStream 适配到 Reader。InputStreamReader 实现了 Reader 接口,并且持有了 InputStream 的引用。这里,适配器就是 InputStreamReader 类,而源角色就是 InputStream 代表的实例对象,目标接口就是 Reader 类。
适配器模式主要在于将一个接口转变成另一个接口,它的目的是通过改变接口来达到重复使用的目的;而装饰器模式不是要改变被装饰对象的接口,而是保持原有的接口,但是增强原有对象的功能,或改变原有对象的方法而提高性能。

用到设计模式优势

装饰者模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例(各种字符流间装饰,各种字节流间装饰)。
技术博客大总结
适配器模式就是将某个类的接口转换成我们期望的另一个接口表示,目的是消除由于接口不匹配所造成的类的兼容性问题(字符流与字节流间互相适配)。

4.0.0.5 说一下对 NIO 的理解?NIO 和 IO 的主要区别?NIO 和 IO 如何影响应用程序的设计?

说一下对 NIO 的理解?

传统的 IO 流是阻塞式的,会一直监听一个 ServerSocket,在调用 read 等方法时,它会一直等到数据到来或者缓冲区已满时才返回。调用 accept 也是一直阻塞到有客户端连接才会返回。每个客户端连接过来后,服务端都会启动一个线程去处理该客户端的请求。并且多线程处理多个连接。每个线程拥有自己的栈空间并且占用一些 CPU 时间。每个线程遇到外部未准备好的时候,都会阻塞掉。阻塞的结果就是会带来大量的进程上下文切换。

对于 NIO,它是非阻塞式,核心类:

1.Buffer 为所有的原始类型提供 (Buffer) 缓存支持。
2.Charset 字符集编码解码解决方案
3.Channel 一个新的原始 I / O 抽象,用于读写 Buffer 类型,通道可以认为是一种连接,可以是到特定设备,程序或者是网络的连接。

NIO 和 IO 的主要区别?

主要区别
IO NIO
面向流 面向缓冲
阻塞 IO 非阻塞 IO
无 选择器

面向流与面向缓冲
Java IO 和 NIO 之间第一个最大的区别是,IO 是面向流的,NIO 是面向缓冲区的。JavaIO 面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的数据,需要先将它缓存到一个缓冲区。JavaNIO 的缓冲导向方法略有不同。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。但是,还需要检查是否该缓冲区中包含所有您需要处理的数据。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。

阻塞与非阻塞 IO
Java IO 的各种流是阻塞的。这意味着,当一个线程调用 read() 或 write() 时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。JavaNIO 的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取,而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。线程通常将非阻塞 IO 的空闲时间用于在其它通道上执行 IO 操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)。

选择器
Java NIO 的选择器允许一个单独的线程来监视多个输入通道,你可以注册多个通道使用一个选择器,然后使用一个单独的线程来“选择”通道:这些通道里已经有可以处理的输入,或者选择已准备写入的通道。这种选择机制,使得一个单独的线程很容易来管理多个通道。

NIO 和 IO 如何影响应用程序的设计?

无论您选择 IO 或 NIO 工具箱,可能会影响您应用程序设计的以下几个方面:技术博客大总结

1. 对 NIO 或 IO 类的 API 调用。
2. 数据处理。
3. 用来处理数据的线程数。

API 调用
当然,使用 NIO 的 API 调用时看起来与使用 IO 时有所不同,但这并不意外,因为并不是仅从一个 InputStream 逐字节读取,而是数据必须先读入缓冲区再处理。

数据处理

使用纯粹的 NIO 设计相较 IO 设计,数据处理也受到影响。在 IO 设计中,我们从 InputStream 或 Reader 逐字节读取数据。
请注意处理状态由程序执行多久决定。换句话说,一旦 reader.readLine() 方法返回,你就知道肯定文本行就已读完,readline() 阻塞直到整行读完,这就是原因。你也知道此行包含名称;同样,第二个 readline() 调用返回的时候,你知道这行包含年龄等。正如你可以看到,该处理程序仅在有新数据读入时运行,并知道每步的数据是什么。一旦正在运行的线程已处理过读入的某些数据,该线程不会再回退数据(大多如此)。

4.0.1.1 对字节流进行大量的从硬盘读取, 要用那个流, 为什么?

对字节流进行大量的从硬盘读取, 要用那个流, 为什么?

因为明确说了是对字节流的读取,所以肯定是 inputstream 或者他的子类,又因为要大量读取,肯定要考虑到高效的问题,自然想到缓冲流。技术博客大总结

用 BufferedInputStream, 原因:BufferedInputStream 是 InputStream 的缓冲流,使用它可以防止每次读取数据时进行实际的写操作,代表着使用缓冲区。不带缓冲的操作,每读一个字节就要写入一个字节,由于涉及磁盘的 IO 操作相比内存的操作要慢很多,所以不带缓冲的流效率很低。带缓冲的流,可以一次读很多字节,但不向磁盘中写入,只是先放到内存里。等凑够了缓冲区大小的时候一次性写入磁盘,这种方式可以减少磁盘操作次数,速度就会提高很多!并且也可以减少对磁盘的损伤。

其他介绍
01. 关于博客汇总链接

1. 技术博客汇总

2. 开源项目汇总

3. 生活博客汇总

4. 喜马拉雅音频汇总

5. 其他汇总

02. 关于我的博客

我的个人站点:www.yczbj.org,www.ycbjie.cn
github:https://github.com/yangchong211

知乎:https://www.zhihu.com/people/…

简书:http://www.jianshu.com/u/b7b2…

csdn:http://my.csdn.net/m0_37700275

喜马拉雅听书:http://www.ximalaya.com/zhubo…

开源中国:https://my.oschina.net/zbj161…

泡在网上的日子:http://www.jcodecraeer.com/me…

邮箱:yangchong211@163.com
阿里云博客:https://yq.aliyun.com/users/a… 239.headeruserinfo.3.dT4bcV
segmentfault 头条:https://segmentfault.com/u/xi…

掘金:https://juejin.im/user/593943…

正文完
 0