IO流汇总
Posted 好多个码农
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IO流汇总相关的知识,希望对你有一定的参考价值。
一.Java IO输入输出流
1.什么是IO
IO:Input/Output,输入/输出流
作用:通过IO流可以完成硬盘文件的读写操作
2.io流的分类
按传输流的方向分为:输入流和输出流
按传输流的数据格式分为:字节流(stream)和字符流(reader/writer)
输入输出流
输入(Input):也就是从外部文件中获取数据(即读取外部数据)
输出(Output):也就是把内存中的文件保存到硬盘上(即把数据写到电脑中)
字节字符流
字节流:一次传送一个字节byte(即一次传送8个二进制位)
注意:它是一个万能流,什么数据都可以传输,如:视频、文本、语音、图片(以Stream结尾的类都是字节流)
字符流:以字符为单位进行数据的传输,一次传输一个字符
注意:它只能传输普通的文本信息,不能读取非文本信息(以Reader/Writer结尾的类都是字符流)
例如:一个文件的内容为:abc你好
一个字母占用1个字节,汉字占用两个字节
用字节流的方式读取的话,第一次会读取到97(a对应的字节码),第二次读取到98(b对应的字节码),第三次是99(c),第四次...
用字符流的方式读取的话,第一次会读取到’a’,第二次会读取到’b’,第三次是’c’,第四次是’你’,第五次是’好’(一个汉字也是一个字符)
3.File类
它也是java.io下的一个类,file是文件的意思,也就是一个文件类,它里面就是包括一下文件的基本方法,文件的基本属性
首先了解什么是相对路径和绝对路径
相对路径:就是相对于当前文件来说的,例如你在IDEA的一个项目里创建了一个temp文件,那你路径名就可以直接写成temp,这就是相对路径
绝对路径,是在哪里都可以用这个路径,这个路径指的就是在电脑硬盘里真正的路径,如:D:\\java\\lib\\fonts就是绝对路径
File文件其实就是文件和目录路径名的抽象表示形式
1)public boolean exists( ) 判断文件或目录是否存在
2)public boolean isFile( ) 判断是文件还是目录
3)public boolean isDirectory( ) 判断是文件还是目录
4)public String getName( ) 返回文件名或目录名
5)public String getPath( ) 返回文件或目录的路径。
6)public long length( ) 获取文件的长度
7)public String[ ] list ( ) 将目录中所有文件名保存在字符串数组中返回。
File类中还定义了一些对文件或目录进行管理、操作的方法,常用的方法有:
1) public boolean renameTo( File newFile ); 重命名文件
2) public void delete( ); 删除文件
3) public boolean mkdir( ); 创建目录
常用类
字节流
字节输入流InputStream主要方法:
read() :从此输入流中读取一个数据字节。
read(byte[] b) :从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
read(byte[] b, int off, int len) :从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。
close():关闭此输入流并释放与该流关联的所有系统资源。
字节输出流OutputStream主要方法:
write(byte[] b) :将 b.length 个字节从指定 byte 数组写入此文件输出流中。
write(byte[] b, int off, int len) :将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
write(int b) :将指定字节写入此文件输出流。
close() :关闭此输入流并释放与该流关联的所有系统资源。
字符流
字符输入流Reader主要方法:
read():读取单个字符。
read(char[] cbuf) :将字符读入数组。
read(char[] cbuf, int off, int len) : 将字符读入数组的某一部分。
read(CharBuffer target) :试图将字符读入指定的字符缓冲区。
flush() :刷新该流的缓冲。
close() :关闭此流,但要先刷新它。
字符输出流Writer主要方法:
write(char[] cbuf) :写入字符数组。
write(char[] cbuf, int off, int len) :写入字符数组的某一部分。
write(int c) :写入单个字符。
write(String str) :写入字符串。
write(String str, int off, int len) :写入字符串的某一部分。
flush() :刷新该流的缓冲。
close() :关闭此流,但要先刷新它。
文件流
java.io.FileInputStream:文件字节输入流
java.io.FileOutputStream:文件字节输出流
java.io.FileReader:文件字符输入流
java.io.FileWriter:文件字符输出流
FileInputStream:文件字节输入流
FileInputStream是一个万能流,可以读取任意文件的数据,首先要定义一个文件字节输入流对象,把要读取的文件地址传进去,然后调用read()方法来进行字节的读取,read()方法返回的是一个int型的字节码数,当读完数据的时候回返回-1;我们也可以让它一下读取一个bye数组,读取的字节长度是byte[].length个字节,read(byte [])方法返回的是读取了几个字节,读取的字节码存储在byte[]数组中,读完数据压缩会返回-1,读取的时候建议采用循环来读取,最后不要忘记关闭流
FileOutputStream:文件字节输出流
首先创建一个 FileOutputStream字节输出流对象,将写入文件的地址信息传进去,如果文件不存在系统会自动新建,调用write()方法开始写,参数为要写入数据的字节码数,一次只能写一个;也可以一下写一个byte[]数组,调用read(byte[])方法;要写入字符串的时候可以调用getBytes()方法将字符串转化为byte[]数组,输出流最后要记得刷新flush()一下,清空要写入的数据以防止数据丢失,记得还要close()关闭一下。
FileReader:文件字符输入流
FileReader是一个纯文本的输入流,只能进行文本文件的读入,输入时,首先创建一个文件字符输入对象,把要读的文件地址放进去,调用read()方法开始读,它一次读取一个字符,返回的是int型的字符编码,读到最后无数据会返回-1,;也可以一下读取一个char[]数组,读取的长度为char[].length个长度,调用read(char[])开始读,返回的是读取了几个字符,读到最后也是返回-1,可以利用String的一个构造器String(char value[], int offset, int count)来进行char[]与String的转换,最后不要忘记关闭流
FileWriter:文件字符输出流
FileWriter是文件字符输出流,首先创建一个文件字符输出流对象,传入要写入的文件地址,调用write()方法,可以一次一个字符的形式写入,参数为字符码;也调用write(String str, int off, int len)这个方法,传进去一个String字符串;或者一次写一个char[]数组,长度为char[].length个字符,想要换行的时候可以调用write(String str)方法–>即writer("\\n")以换行,最后记得刷新flush()+关闭close()
缓冲流
当一个流的构造器中需要一个流时,被传进来的这个流叫做节点流
外部负责包装的这个流称为包装流,又叫处理流
Java缓冲流本身并不具有IO流的读取与写入功能,只是在别的流(节点流或其他处理流)上加上缓冲功能提高效率就像是把别的流包装起来一样,缓冲流是一种处理流(包装流)
当对文件或者其他数据源进行频繁的读写操作时,效率比较低,这时如果使用缓冲流就能够更高效的读写信息。
BufferedInputStream带缓冲的字节输入流
BufferedInputStream是一个缓冲字节输入流,其实跟普通的字节输入流的方法差不多,因为它也实现了InputStream接口,有着同样的方法,那为什么会出现这种缓冲流呢,因为普通的输入流它与其他数据源进行频繁的读写操作时,效率较低,使用缓冲流的话就能够更高效的读写信息
BufferedOutputStream带缓冲的字节输出流
BufferedOutputStream是带缓冲的字节输出流,在我们使用的时候感觉跟普通的输出流差不多,其实他的底层是为我们知道创建了一个缓冲区,我们在想文件中写入数据的时候,数据会被先存放在缓冲区,等缓冲区满的时候,它会将缓冲区的数据一下子传输到输出流中,避免了一个字节一个字节地频繁与底层交互,提高了效率。
BufferedReader带缓冲的字符输入流
BufferedReader是带缓存的字符缓存输入流,比普通的输入流多了一个readLine()方法,一下读取一行数据,显然比普通的效率要更快
BufferedWriter带缓冲的字符输出流
BufferedWriter是带缓冲区的字符输出流,写入数据的时候更加的方便,它提供了 write(String str)的方法,可以直接写入一个字符串,还有newLine()方法写入一个换行符,当然也可以用write("\\n"),还有write(char cbuf[])方法写入一个char[]数组,底层也是有一个缓冲区来存放将要写入数据
字符缓冲流两个独特的方法:
BufferedWriter类newLine() :写入一个行分隔符。这个方法会自动适配所在系统的行分隔符。
BufferedReader类readLine() :读取一个文本行。
转换流
它用于字节流转为字符流,eg:在缓冲流中,一个字节输出流想要用Writer字符流,这就可以用到我们的转换流
注意:字符流不能转为字节流(万能字节流才可以转换)
InputStreamReader实现了字节输入流(InputStream)向字符输入流(Reader)的转变
OutputStreamWriter实现了字节输出流(OutputStream)向字符输出流(Writer)的转变
输入输出流是相对于内存而言的!
2、Java IO总结
(1)明确源和目的。
数据source:就是需要读取,可以使用两个体系:InputStream、Reader;
数据destination:就是需要写入,可以使用两个体系:OutputStream、Writer;
(2)操作的数据是否是纯文本数据?
如果是:
数据source:Reader
数据destination:Writer
如果不是:
数据source:InputStream
数据destination:OutputStream
(3)Java IO体系中有太多的对象,到底用哪个呢?
明确操作的数据设备。
数据source对应的设备:硬盘(File),内存(数组),键盘(System.in)
数据destination对应的设备:硬盘(File),内存(数组),控制台(System.out)。
记住,只要一读取键盘录入,就用这句话。
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
1、面试题汇总
(1)java中有几种类型的流?
字符流和字节流。字节流继承inputStream和OutputStream,字符流继承自InputSteamReader和OutputStreamWriter。
(2)谈谈Java IO里面的常见类,字节流,字符流、接口、实现类、方法阻塞
答:输入流就是从外部文件输入到内存,输出流主要是从内存输出到文件。
IO里面常见的类,第一印象就只知道IO流中有很多类,IO流主要分为字符流和字节流。字符流中有抽象类InputStream和OutputStream,它们的子类FileInputStream,FileOutputStream,BufferedOutputStream等。字符流BufferedReader和Writer等。都实现了Closeable, Flushable, Appendable这些接口。程序中的输入输出都是以流的形式保存的,流中保存的实际上全都是字节文件。
java中的阻塞式方法是指在程序调用改方法时,必须等待输入数据可用或者检测到输入结束或者抛出异常,否则程序会一直停留在该语句上,不会执行下面的语句。比如read()和readLine()方法。
(3)字符流和字节流有什么区别?
要把一片二进制数据数据逐一输出到某个设备中,或者从某个设备中逐一读取一片二进制数据,不管输入输出设备是什么,我们要用统一的方式来完成这些操作,用一种抽象的方式进行描述,这个抽象描述方式起名为IO流,对应的抽象类为OutputStream和InputStream ,不同的实现类就代表不同的输入和输出设备,它们都是针对字节进行操作的。
在应用中,经常要完全是字符的一段文本输出去或读进来,用字节流可以吗?
计算机中的一切最终都是二进制的字节形式存在。对于“中国”这些字符,首先要得到其对应的字节,然后将字节写入到输出流。读取时,首先读到的是字节,可是我们要把它显示为字符,我们需要将字节转换成字符。由于这样的需求很广泛,人家专门提供了字符流的包装类。
底层设备永远只接受字节数据,有时候要写字符串到底层设备,需要将字符串转成字节再进行写入。字符流是字节流的包装,字符流则是直接接受字符串,它内部将串转成字节,再写入底层设备,这为我们向IO设别写入或读取字符串提供了一点点方便。
(4)讲讲NIO
答:看了一些文章,传统的IO流是阻塞式的,会一直监听一个ServerSocket,在调用read等方法时,他会一直等到数据到来或者缓冲区已满时才返回。调用accept也是一直阻塞到有客户端连接才会返回。每个客户端连接过来后,服务端都会启动一个线程去处理该客户端的请求。并且多线程处理多个连接。每个线程拥有自己的栈空间并且占用一些 CPU 时间。每个线程遇到外部未准备好的时候,都会阻塞掉。阻塞的结果就是会带来大量的进程上下文切换。
对于NIO,它是非阻塞式,核心类:
1.Buffer为所有的原始类型提供 (Buffer)缓存支持。
2.Charset字符集编码解码解决方案
3.Channel一个新的原始 I/O抽象,用于读写Buffer类型,通道可以认为是一种连接,可以是到特定设备,程序或者是网络的连接。
以上是关于IO流汇总的主要内容,如果未能解决你的问题,请参考以下文章