java面试中技术官通常都会对应聘者提些java io这块的面试题
IO方面:
1、IO熟悉吧,你介绍一下IO的体系吧
2、你使用过IO进行文件的操作吗?
//------------------------以下是结论部分
Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列。
数据流是一串连续不断的数据的集合,就象水管里的水流,在水管的一端一点一点地供水,而在水管的另一端看到的是一股连续不断的水流。数据写入程序可以是一段、一段地向数据流管道中写入数据,这些数据段会按先后顺序形成一个长的数据流。对数据读取程序来说,看不到数据流在写入时的分段情况,每次可以读取其中的任意长度的数据,但只能先读取前面的数据后,再读取后面的数据(不能随机读取)。不管写入时是将数据分多次写入,还是作为一个整体一次写入,读取时的效果都是完全一样的。
简而言之:数据流是一组有序,有起点和终点的字节的数据序列。包括输入流和输出流。
当程序需要读取数据的时候,就会建立一个通向数据源的连接,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会建立一个通向目的地的连接。
数据流分类:
流序列中的数据既可以是未经加工的原始二进制数据,也可以是经一定编码处理后符合某种格式规定的特定数据。因此Java中的流分为两种: 1) 字节流:数据流中最小的数据单元是字节 2) 字符流:数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节。
概览
Java.io包中最重要的就是5个类和一个接口。5个类指的是File、OutputStream、InputStream、Writer、Reader;一个接口指的是Serializable。掌握了这些就掌握了Java I/O的精髓了。
Java I/O主要包括如下3层次:
流式部分——最主要的部分。如:OutputStream、InputStream、Writer、Reader等
非流式部分——如:File类、RandomAccessFile类和FileDescriptor等类
其他——文件读取部分的与安全相关的类,如:SerializablePermission类,以及与本地操作系统相关的文件系统的类,如:FileSystem类和Win32FileSystem类和WinNTFileSystem类。
主要类如下:
File(文件特征与管理):用于文件或者目录的描述信息,例如生成新目录,修改文件名,删除文件,判断文件所在路径等。
InputStream(字节流,二进制格式操作):抽象类,基于字节的输入操作,是所有输入流的父类。定义了所有输入流都具有的共同特征。
OutputStream(字节流,二进制格式操作):抽象类。基于字节的输出操作。是所有输出流的父类。定义了所有输出流都具有的共同特征。
Reader(字符流,文本格式操作):抽象类,基于字符的输入操作。
Writer(字符流,文本格式操作):抽象类,基于字符的输出操作。
RandomAccessFile(随机文件操作):它的功能丰富,可以从文件的任意位置进行存取(输入输出)操作。
I/O流
java.io包里有4个基本类:InputStream、OutputStream及Reader、Writer类,它们分别处理字节流和字符流。
来看看几种不同的InputStream:
FileInputStream把一个文件作为InputStream,实现对文件的读取操作
ByteArrayInputStream:把内存中的一个缓冲区作为InputStream使用
StringBufferInputStream:把一个String对象作为InputStream
PipedInputStream:实现了pipe的概念,主要在线程中使用
SequenceInputStream:把多个InputStream合并为一个InputStream
几种不同的OutputStream:
ByteArrayOutputStream:把信息存入内存中的一个缓冲区中
FileOutputStream:把信息存入文件中
PipedOutputStream:实现了pipe的概念,主要在线程中使用
SequenceOutputStream:把多个OutStream合并为一个OutStream
有两个需要注意的:
InputStreamReader : 从输入流读取字节,在将它们转换成字符。
BufferReader :接受Reader对象作为参数,并对其添加字符缓冲器,使用readline()方法可以读取一行。
如何选择I/O流
确定是输入还是输出
输入:输入流 InputStream Reader
输出:输出流 OutputStream Writer
明确操作的数据对象是否是纯文本
是:字符流 Reader,Writer
否:字节流 InputStream,OutputStream
明确具体的设备。
文件:
读:FileInputStream, FileReader,
写:FileOutputStream,FileWriter
数组:
byte[ ]:ByteArrayInputStream, ByteArrayOutputStream
char[ ]:CharArrayReader, CharArrayWriter
String:
StringBufferInputStream(已过时,因为其只能用于String的每个字符都是8位的字符串), StringReader, StringWriter
Socket流
键盘:用System.in(是一个InputStream对象)读取,用System.out(是一个OutoutStream对象)打印
是否需要转换流
是,就使用转换流,从Stream转化为Reader、Writer:InputStreamReader,OutputStreamWriter
是否需要缓冲提高效率
是就加上Buffered:BufferedInputStream, BufferedOuputStream, BufferedReader, BufferedWriter
是否需要格式化输出
常见的纯文本格式文件的扩展名:
TXT、HTM、ASP、BAT、C、BAS、PRG、CMD等。能用windows自带的记事本打开的就是
Java I/O 总结
http://www.importnew.com/23708.html
关于Java IO与NIO知识都在这里
https://juejin.im/post/5af79bcc51882542ad771546
Java学习+面试指南
https://github.com/Snailclimb/JavaGuide
Java IO,硬骨头也能变软
https://mp.weixin.qq.com/s?__biz=MzU4NDQ4MzU5OA==&mid=2247483981&idx=1&sn=6e5c682d76972c8d2cf271a85dcf09e2&chksm=fd98542ccaefdd3a70428e9549bc33e8165836855edaa748928d16c1ebde9648579d3acaac10#rd
java IO体系的学习总结
https://blog.csdn.net/nightcurtis/article/details/51324105
//---------------重磅(java面试,感谢前辈们的总结)
https://mp.weixin.qq.com/s?__biz=MzU4NDQ4MzU5OA==&mid=2247483985&idx=1&sn=38531c2cee7b87f125df7aef41637014&chksm=fd985430caefdd26b0506aa84fc26251877eccba24fac73169a4d6bd1eb5e3fbdf3c3b940261#rd
它是一种数据的流从源头流到目的地。比如文件拷贝,输入流和输出流都包括了。输入流从文件中读取数据存储到进程(process)中,输出流从进程中读取数据然后写入到目标文件。
字节流在JDK1.0中就被引进了,用于操作包含ASCII字符的文件。JAVA也支持其他的字符如Unicode,为了读取包含Unicode字符的文件,JAVA语言设计者在JDK1.1中引入了字符流。ASCII作为Unicode的子集,对于英语字符的文件,可以可以使用字节流也可以使用字符流。
3.Java中流类的超类主要由那些?
java.io.InputStream
java.io.OutputStream
java.io.Reader
java.io.Writer
这是在拷贝文件操作的时候,经常用到的两个类。在处理小文件的时候,它们性能表现还不错,在大文件的时候,最好使用BufferedInputStream (或 BufferedReader) 和 BufferedOutputStream (或 BufferedWriter)
个人来说,更喜欢使用字符流,因为他们更新一些。许多在字符流中存在的特性,字节流中不存在。比如使用BufferedReader而不是BufferedInputStreams或DataInputStream,使用newLine()方法来读取下一行,但是在字节流中我们需要做额外的操作。
6.System.out.println()是什么?
println是PrintStream的一个方法。out是一个静态PrintStream类型的成员变量,System是一个java.lang包中的类,用于和底层的操作系统进行交互。
7.什么是Filter流?
Filter Stream是一种IO流主要作用是用来对存在的流增加一些额外的功能,像给目标文件增加源文件中不存在的行数,或者增加拷贝的性能。
有哪些可用的Filter流?
在java.io包中主要由4个可用的filter Stream。两个字节filter stream,两个字符filter stream. 分别是FilterInputStream, FilterOutputStream, FilterReader and FilterWriter.这些类是抽象类,不能被实例化的。
有些Filter流的子类:
LineNumberInputStream 给目标文件增加行号
DataInputStream 有些特殊的方法如readInt(), readDouble()和readLine() 等可以读取一个 int, double和一个string一次性的,
BufferedInputStream 增加性能
PushbackInputStream 推送要求的字节到系统中
9.SequenceInputStream的作用?
这个类的作用是将多个输入流合并成一个输入流,通过SequenceInputStream类包装后形成新的一个总的输入流。在拷贝多个文件到一个目标文件的时候是非常有用的。可用使用很少的代码实现
10.说说PrintStream和PrintWriter
他们两个的功能相同,但是属于不同的分类。字节流和字符流。他们都有println()方法。
12 .说说管道流(Piped Stream)
有四种管道流, PipedInputStream, PipedOutputStream, PipedReader 和 PipedWriter.在多个线程或进程中传递数据的时候管道流非常有用。
13.说说File类
它不属于 IO流,也不是用于文件操作的,它主要用于知道一个文件的属性,读写权限,大小等信息。注意:Java7中文件IO发生了很大的变化,专门引入了很多新的类来取代原来的基于java.io.File的文件IO操作方式。详情阅读下面的文章:
Java NIO之拥抱Path和Files
14. 说说RandomAccessFile?
它在java.io包中是一个特殊的类,既不是输入流也不是输出流,它两者都可以做到。他是Object的直接子类。通常来说,一个流只有一个功能,要么读,要么写。但是RandomAccessFile既可以读文件,也可以写文件。 DataInputStream 和 DataOutStream有的方法,在RandomAccessFile中都存在。
原文
http://www.imooc.com/article/details/id/24305
//-------------------------------以下装逼项,谨慎哈,免得反被草
Java NIO 概览
https://mp.weixin.qq.com/s?__biz=MzU4NDQ4MzU5OA==&mid=2247483956&idx=1&sn=57692bc5b7c2c6dfb812489baadc29c9&chksm=fd985455caefdd4331d828d8e89b22f19b304aa87d6da73c5d8c66fcef16e4c0b448b1a6f791#rd
官方JDK相关文档:https://docs.oracle.com/javase/8/docs/api/
谷歌搜索排名第一的Java NIO教程:http://tutorials.jenkov.com/java-nio/channels.html
Java NIO 与 IO之间的区别:https://blog.csdn.net/evan_man/article/details/50910542
《Java程序员修炼之道》:https://book.douban.com/subject/24841235/
Java NIO 之 Buffer(缓冲区)
https://mp.weixin.qq.com/s?__biz=MzU4NDQ4MzU5OA==&mid=2247483961&idx=1&sn=f67bef4c279e78043ff649b6b03fdcbc&chksm=fd985458caefdd4e3317ccbdb2d0a5a70a5024d3255eebf38183919ed9c25ade536017c0a6ba#rd
Java NIO 之 Channel(通道)
https://mp.weixin.qq.com/s?__biz=MzU4NDQ4MzU5OA==&mid=2247483966&idx=1&sn=d5cf18c69f5f9ec2aff149270422731f&chksm=fd98545fcaefdd49296e2c78000ce5da277435b90ba3c03b92b7cf54c6ccc71d61d13efbce63#rd
Java NIO之Selector(选择器)
https://mp.weixin.qq.com/s?__biz=MzU4NDQ4MzU5OA==&mid=2247483970&idx=1&sn=d5e2b133313b1d0f32872d54fbdf0aa7&chksm=fd985423caefdd354b587e57ce6cf5f5a7bec48b9ab7554f39a8d13af47660cae793956e0f46#rd
高级装逼篇
高并发Java(8):io/NIO和AIO
http://www.importnew.com/21341.html
https://my.oschina.net/hosee/blog/615269
结论:
NIO是基于块(Block)的,它以块为基本单位处理数据 (硬盘上存储的单位也是按Block来存储,这样性能上比基于流的方式要好一些)
为所有的原始类型提供(Buffer)缓存支持
增加通道(Channel)对象,作为新的原始 I/O 抽象
支持锁(我们在平时使用时经常能看到会出现一些.lock的文件,这说明有线程正在使用这把锁,当线程释放锁时,会把这个文件删除掉,这样其他线程才能继续拿到这把锁)和内存映射文件的文件访问接口
提供了基于Selector的异步网络I/O
总结下使用Buffer的步骤是:
得到Channel
申请Buffer
建立Channel和Buffer的读/写关系
关闭
Channel
使用非阻塞的NIO (读取数据不等待,数据准备好了再工作)
而Channel有点类似于流,一个Channel可以和文件或者网络Socket对应 。
selector是一个选择器,它可以选择某一个Channel,然后做些事情。
一个线程可以对应一个selector,而一个selector可以轮询多个Channel,而每个Channel对应了一个Socket。
与上面一个线程对应一个Socket相比,使用NIO后,一个线程可以轮询多个Socket。
当selector调用select()时,会查看是否有客户端准备好了数据。当没有数据被准备好时,select()会阻塞。平时都说NIO是非阻塞的,但是如果没有数据被准备好还是会有阻塞现象。
当有数据被准备好时,调用完select()后,会返回一个SelectionKey,SelectionKey表示在某个selector上的某个Channel的数据已经被准备好了。
只有在数据准备好时,这个Channel才会被选择。
这样NIO实现了一个线程来监控多个客户端。
而刚刚模拟的网络延迟的客户端将不会影响NIO下的线程,因为某个Socket网络延迟时,数据还未被准备好,selector是不会选择它的,而会选择其他准备好的客户端。
selectNow()与select()的区别在于,selectNow()是不阻塞的,当没有客户端准备好数据时,selectNow()不会阻塞,将返回0,有客户端准备好数据时,selectNow()返回准备好的客户端的个数。
NIO会将数据准备好后,再交由应用进行处理,数据的读取/写入过程依然在应用线程中完成,只是将等待的时间剥离到单独的线程中去。
节省数据准备时间(因为Selector可以复用)
AIO
AIO的特点:
读完了再通知我
不会加快IO,只是在读完后进行通知
使用回调函数,进行业务处理
在理解了NIO的基础上,看AIO,区别在于AIO是等读写过程完成后再去调用回调函数。
NIO是同步非阻塞的
AIO是异步非阻塞的
由于NIO的读写过程依然在应用线程里完成,所以对于那些读写过程时间长的,NIO就不太适合。
而AIO的读写过程完成后才被通知,所以AIO能够胜任那些重量级,读写过程长的任务。