谈谈java中的IO流

1.字节流

1.1.字节输出流output

1.1.1.数据写入文件中

通过api查找 output 。找到很多,其中 java.io.OutputStream ,OutputStream: 输出字节流的超类。

小编整理了一些java进阶学习资料和面试题,需要资料的请加JAVA高阶学习Q群:664389243 这是小编创建的java高阶学习交流群,加群一起交流学习深造。群里也有小编整理的2019年最新最全的java高阶学习资料!

基本特点:

1、操作的数据都是字节。

2、定义了输出字节流的基本共性功能。

3、输出流中定义都是写write方法。操作字节数组write(byte[]),操作单个字节 write(byte) 。

子类有规律:所有的子类名称后缀是父类名,前缀名是这个流对象功能。

想要操作文件: FileOutputStream

1publicclassFileOutputStreamDemo {2publicstaticvoidmain(String[] args)throwsIOException {3//需求:将数据写入到文件中。4//创建存储数据的文件。5Filefile=newFile("c:\\file.txt");6//创建一个用于操作文件的字节输出流对象。一创建就必须明确数据存储目的地。7//输出流目的是文件,会自动创建。如果文件存在,则覆盖。8FileOutputStream fos =newFileOutputStream(file);9//调用父类中的write方法。10byte[] data ="abcde".getBytes();11fos.write(data);12//关闭流资源。13fos.close();14}15}

1.1.2.给文件中续写和换行

我们知道直接 new FileOutputStream(file)这样创建对象,会覆盖原有的文件,那么我们想在原有的文件中续写内容怎么办呢?继续查阅FileOutputStream的API。发现在FileOutputStream的构造函数中,可以接受一个boolean类型的值,如果值true,就会在文件末位继续添加。

1publicclassFileOutputStreamDemo2 {2publicstaticvoidmain(String[] args)throwsException {3Filefile=newFile("c:\\file.txt");4FileOutputStream fos =newFileOutputStream(file,true);5String str ="\r\n"+"itcast";6fos.write(str.getBytes());7fos.close();8}9}

1.1.3.IO异常的处理

我们在开发中应该如何处理这些异常呢?

1publicclassFileOutputStreamDemo3 {2publicstaticvoidmain(String[] args) {34Filefile=newFile("c:\\file.txt");5//定义FileOutputStream的引用6FileOutputStream fos =null;7try{8//创建FileOutputStream对象9fos =newFileOutputStream(file);10//写出数据11fos.write("abcde".getBytes());1213}catch(IOException e) {14System.out.println(e.toString() +"----");15}finally{16//一定要判断fos是否为null,只有不为null时,才可以关闭资源17if(fos !=null) {18try{19fos.close();20}catch(IOException e) {21thrownewRuntimeException("");22}23}24}25}26}

1.2.字节输入流Input

1.2.1.读取数据read方法

通过api查找 input 。 java.io.InputStream。 InputStream:字节输入流的超类。

常见功能:

int read():读取一个字节并返回,没有字节返回-1.

int read(byte[]): 读取一定量的字节数,并存储到字节数组中,返回读取到的字节数。

用于读取文件的字节输入流对象:FileInputStream。

1publicclassFileInputStreamDemo {2publicstaticvoidmain(String[] args)throwsIOException {3Filefile=newFile("c:\\file.txt");4//创建一个字节输入流对象,必须明确数据源,其实就是创建字节读取流和数据源相关联。5FileInputStream fis =newFileInputStream(file);6//读取数据。使用 read();一次读一个字节。7intch =0;8while((ch=fis.read())!=-1){9System.out.println("ch="+(char)ch);10}11// 关闭资源。12fis.close();13}14}

1.2.2.读取数据read(byte[])方法

在读取文件中的数据时,调用 read 方法,每次只能读取一个,太麻烦了,于是我们可以定义数组作为临时的存储容器,这时可以调用重载的 read 方法,一次可以读取多个字符。

1publicclassFileInputStreamDemo2 {2publicstaticvoidmain(String[] args)throwsIOException {3/*

4          * 演示第二个读取方法, read(byte[]);

5          */6Filefile=newFile("c:\\file.txt");7// 创建一个字节输入流对象,必须明确数据源,其实就是创建字节读取流和数据源相关联。8FileInputStream fis =newFileInputStream(file);9//创建一个字节数组。10byte[] buf =newbyte[1024];//长度可以定义成1024的整数倍。        11intlen =0;12while((len=fis.read(buf))!=-1){13System.out.println(newString(buf,0,len));14}15fis.close();16}17}

2.字符流

经过前面的学习,我们基本掌握的文件的读写操作,在操作过程中字节流可以操作所有数据,可是当我们操作的文件中有中文字符,并且需要对中文字符做出处理时怎么办呢?

2.1.字节流读取问题

通过以下程序读取带有中文件的文件。

1publicclassCharStreamDemo{2publicstaticvoidmain(String[] args)throwsIOException{3//给文件中写中文4writeCNText();5//读取文件中的中文6readCNText();7}8//读取中文9publicstaticvoidreadCNText()throwsIOException{10FileInputStream fis =newFileInputStream("c:\\cn.txt");11intch =0;12while((ch = fis.read())!=-1){13System.out.println(ch);14}15}16//写中文17publicstaticvoidwriteCNText()throwsIOException{18FileOutputStream fos =newFileOutputStream("c:\\cn.txt");19fos.write("a传智播客欢迎你".getBytes());20fos.close();21}22}

上面程序在读取含有中文的文件时,我们并没有看到具体的中文,而是看到一些数字,这是什么原因呢?既然看不到中文,那么我们如何对其中的中文做处理呢?要解决这个问题,我们必须研究下字符的编码过程。

2.2.编码表

我们知道计算机底层数据存储的都是二进制数据,而我们生活中的各种各样的数据,如何才能和计算机中存储的二进制数据对应起来呢?这时老美他们就把每一个字符和一个整数对应起来,就形成了一张编码表,老美他们的编码表就是ASCII表。其中就是各种英文字符对应的编码。

编码表:其实就是生活中字符和计算机二进制的对应关系表。

1、ascii: 一个字节中的7位就可以表示。对应的字节都是正数。0-xxxxxxx

2、iso8859-1:拉丁码表 latin,用了一个字节用的8位。1-xxxxxxx  负数。

3、GB2312:简体中文码表。包含6000-7000中文和符号。用两个字节表示。两个字节都是开头为1 ,两个字节都是负数。

GBK:目前最常用的中文码表,2万的中文和符号。用两个字节表示,其中的一部分文字,第一个字节开头是1,第二字节开头是0

GB18030:最新的中文码表,目前还没有正式使用。

4、unicode:国际标准码表:无论是什么文字,都用两个字节存储。

Java中的char类型用的就是这个码表。char c = 'a';占两个字节。

Java中的字符串是按照系统默认码表来解析的。简体中文版 字符串默认的码表是GBK。

5、UTF-8:基于unicode,一个字节就可以存储数据,不要用两个字节存储,而且这个码表更加的标准化,在每一个字节头加入了编码信息(后期到api中查找)。

能识别中文的码表:GBK、UTF-8;正因为识别中文码表不唯一,涉及到了编码解码问题。对于我们开发而言;常见的编码 GBK  UTF-8  ISO8859-1

文字--->(数字) :编码。

(数字)--->文字  : 解码。

2.3.FileReader类介绍

上述程序中我们读取拥有中文的文件时,使用的字节流在读取,那么我们读取到的都是一个一个字节。只要把这些字节去查阅对应的编码表,就能够得到与之对应的字符。API中是否给我们已经提供了读取相应字符的功能流对象呢?

查阅FileInputStream的 API ,发现 FileInputStream 用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader 。如果读取字符流,要使用 FileReader , FileReader 是什么呢?

打开FileReader的 API 介绍。用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的,原来FileReader 用于读取字符流。使用 FileReader 时,了解它的功能,看它所属的体系顶层。

Reader:读取字符流的抽象超类。

read():读取单个字符并返回

read(char[]):将数据读取到数组中,并返回读取的个数。

1publicclassCharStreamDemo{2publicstaticvoidmain(String[] args)throwsIOException{3//给文件中写中文4writeCNText();5//读取文件中的中文6readCNText();7}8//读取中文9publicstaticvoidreadCNText()throwsIOException{10FileReader fr =newFileReader("D:\\test\\cn.txt");11intch =0;12while((ch = fr.read())!=-1){13//输出的字符对应的编码值14System.out.println(ch);15//输出字符本身16System.out.println((char)ch);17}18}19//写中文20publicstaticvoidwriteCNText()throwsIOException{21FileOutputStream fos =newFileOutputStream("D:\\test\\cn.txt");22fos.write("a传智播客欢迎你".getBytes());23fos.close();24}25}

2.4.FileWriter类介绍

既然有专门用于读取字符的流对象,那么肯定也有写的字符流对象,查阅 API ,发现有一个Writer 类, Writer 是写入字符流的抽象类。其中描述了相应的写的动作。

1publicclassFileWriterDemo{2publicstaticvoidmain(String[] args)throwsIOException{3//演示FileWriter 用于操作文件的便捷类。4FileWriter fw =newFileWriter("d:\\text\\fw.txt");56fw.write("你好谢谢再见");//这些文字都要先编码。都写入到了流的缓冲区中。78fw.flush();910fw.close();11}12}

2.5.flush()和close()的区别

flush(): 将流中的缓冲区缓冲的数据刷新到目的地中,刷新后,流还可以继续使用。

close(): 关闭资源,但在关闭前会将缓冲区中的数据先刷新到目的地,否则丢失数据,然后在关闭流。流不可以使用。如果写入数据多,一定要一边写一边刷新,最后一次可以不刷新,由 close 完成刷新并关闭。

3.转换流

学习完了使用字符流对文件的简单操作后,在学习字符流的时候,其中说如果需要指定编码和缓冲区大小时,可以在字节流的基础上,构造一个 InputStreamReader 或者 OutputStreamWriter ,这又是什么意思呢?

3.1.OutputSreamWriter类

需求:既然识别中文的码表有两个, GBK 、 UTF-8 等,能不能将中文数据按照 utf-8 的方式进行文件的存储呢?

还能使用 FileWriter 吗?不能使用了,因为 FileWriter 中默认的是 GBK 。通过 FileWriter 的api 描述,要指定编码表这些值,需要使用 OutputStreamWriter

OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它的作用的就是,将字符串按照指定的编码表转成字节,在使用字节流将这些字节写出去。

1publicstaticvoidwriteCN()throwsException{2//创建与文件关联的字节输出流对象3FileOutputStream fos =newFileOutputStream("c:\\cn8.txt");4//创建可以把字符转成字节的转换流对象,并指定编码5OutputStreamWriter osw =newOutputStreamWriter(fos,"utf-8");6//调用转换流,把文字写出去,其实是写到转换流的缓冲区中7osw.write("你好");//写入缓冲区。8osw.close();9}

OutputStreamWriter 流对象,它到底如何把字符转成字节输出的呢?

其实在 OutputStreamWriter 流中维护自己的缓冲区,当我们调用 OutputStreamWriter 对象的write 方法时,会拿着字符到指定的码表中进行查询,把查到的字符编码值转成字节数存放到 OutputStreamWriter 缓冲区中。然后再调用刷新功能,或者关闭流,或者缓冲区存满后会把缓冲区中的字节数据使用字节流写到指定的文件中。

3.2.InputSreamReader类

查阅 InputStreamReader 的 API 介绍, InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

1publicclassInputStreamReaderDemo{2publicstaticvoidmain(String[] args) throws IOException{3//演示字节转字符流的转换流4readCN();5}6publicstaticvoidreadCN() throws IOException{7//创建读取文件的字节流对象8InputStreamin=newFileInputStream("c: \\cn8.txt");9//创建转换流对象 10//InputStreamReader isr = new InputStreamReader(in);这样创建对象,会用本地默认码表读取,将会发生错误解码的错误11InputStreamReader isr =newInputStreamReader(in,"utf-8");12//使用转换流去读字节流中的字节13intch =0;14while((ch = isr.read())!=-1){15System.out.println((char)ch);16}17//关闭流18isr.close();19}20}

注意:在读取指定的编码的文件时,一定要指定编码格式,否则就会发生解码错误,而发生乱码现象。

3.3.转换流和子类的区别

发现有如下继承关系:

OutputStreamWriter:

FileWriter:

InputStreamReader:

FileReader;

父类和子类的功能有什么区别呢?

OutputStreamWriter和InputStreamReader是字符和字节的桥梁:也可以称之为字符转换流。字符转换流原理:字节流+编码表。 

FileWriter和FileReader:作为子类,仅作为操作字符文件的便捷类存在。当操作的字符文件,使用的是默认编码表时可以不用父类,而直接用子类就完成操作了,简化了代码。

InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));//默认字符集。

InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"GBK");//指定GBK字符集。

FileReader fr = new FileReader("a.txt");

这三句代码的功能是一样的,其中第三句最为便捷。

注意:一旦要指定其他编码时,绝对不能用子类,必须使用字符转换流。什么时候用子类呢?

条件:

1、操作的是文件。2、使用默认编码。3 纯文本

总结:

字节--->字符 : 看不懂的--->看的懂的。  需要读。输入流。 InputStreamReader

字符--->字节 : 看的懂的--->看不懂的。  需要写。输出流。 OutputStreamWriter

4.缓冲流

在我们学习字节流与字符流的时候,大家都进行过读取文件中数据的操作,读取数据量大的文件时,读取的速度会很慢,很影响我们程序的效率,那么, 我想提高速度,怎么办? Java 中提高了一套缓冲流,它的存在,可提高 IO 流的读写速度 缓冲流,根据流的分类分类字节缓冲流与字符缓冲流。

4.1.字节缓冲流

字节缓冲流根据流的方向,共有 2 个

写入数据到流中,字节缓冲输出流 BufferedOutputStream

读取流中的数据,字节缓冲输入流 BufferedInputStream

它们的内部都包含了一个缓冲区,通过缓冲区读写,就可以提高了 IO流的读写速度

4.1.1.字节缓冲输出流BufferedOutputStream

通过字节缓冲流,进行文件的读写操作 写数据到文件的操作

构造方法public BufferedOutputStream(OutputStream out)创建一个新的缓冲输出流,以将数据写入指定的底层输出流。

1publicclassBufferedOutputStreamDemo01{2publicstaticvoidmain(String[] args) throws IOException{34//写数据到文件的方法5write();6}78/*

9      * 写数据到文件的方法

10      * 1,创建流

11      * 2,写数据

12      * 3,关闭流

13      */14privatestaticvoidwrite() throws IOException{15//创建基本的字节输出流16FileOutputStream fileOut =newFileOutputStream("abc.txt");17//使用高效的流,把基本的流进行封装,实现速度的提升18BufferedOutputStreamout=newBufferedOutputStream(fileOut);19//2,写数据20out.write("hello".getBytes());21//3,关闭流22out.close();23}24}

4.1.2.字节缓冲输出流BufferedInputStream

刚刚我们学习了输出流实现了向文件中写数据的操作,那么,现在我们完成读取文件中数据的操作

构造方法

public BufferedInputStream(InputStream in)

1/*

2      * 从文件中读取数据

3      * 1,创建缓冲流对象

4      * 2,读数据,打印

5      * 3,关闭

6      */7privatestaticvoidread() throws IOException{8//1,创建缓冲流对象9FileInputStream fileIn =newFileInputStream("abc.txt");10//把基本的流包装成高效的流11BufferedInputStreamin=newBufferedInputStream(fileIn);12//2,读数据13intch =-1;14while( (ch =in.read()) !=-1) {15//打印16System.out.print((char)ch);17}18//3,关闭19in.close();20}

4.1.3.使用基本的流与高效的流完成复制文件

我们一直在说,高效的流速度快并高效,怎么体现呢?需要通过一个复制文件耗时的比较过程,来体验一下高效流带来的快感。

1/*

  2  * 需求:将d:\\test.avi文件进行复制

  3  *        采用4种方式复制

  4  *        方式1: 采用基本的流,一次一个字节的方式复制    共耗时 224613毫秒

  5  *        方式2: 采用基本的流,一个多个字节的方式赋值    共耗时    327毫秒

  6  *        方式3: 采用高效的流,一次一个字节的方式复制    共耗时    2047毫秒

  7  *        方式4: 采用高效的流,一个多个字节的方式赋值    共耗时      96毫秒

  8  *

  9  * 数据源: d:\\test.avi

10  * 目的地1: d:\\copy1.avi

11  * 目的地2: d:\\copy2.avi

12  * 目的地3: d:\\copy3.avi

13  * 目的地4: d:\\copy4.avi

14  *

15  * 实现的步骤:

16  *    1,指定数据源

17  *    2,指定目的地

18  *    3,读数据

19  *    4,写数据

20  *    5,关闭流

21  *

22  */23publicclassCopyAVI{24publicstaticvoidmain(String[] args) throws IOException{25//开始计时26longstart = System.currentTimeMillis();27//方式1: 采用基本的流,一次一个字节的方式复制28//method1("d:\\test.avi", "d:\\copy1.avi");29//方式2: 采用基本的流,一个多个字节的方式赋值30//method2("d:\\test.avi", "d:\\copy2.avi");31//方式3: 采用高效的流,一次一个字节的方式复制32//method3("d:\\test.avi", "d:\\copy3.avi");33//方式4: 采用高效的流,一个多个字节的方式赋值34method4("d:\\test.avi","d:\\copy4.avi");3536//结束计时37longend = System.currentTimeMillis();38//打印耗时多少毫秒39System.out.println("共耗时 "+(end - start)+"毫秒");40}4142//方式4: 采用高效的流,一个多个字节的方式赋值43privatestaticvoidmethod4(String src, String dest) throws IOException{44//1,指定数据源45BufferedInputStreamin=newBufferedInputStream(newFileInputStream(src));46//2,指定目的地47BufferedOutputStreamout=newBufferedOutputStream(newFileOutputStream(dest));48//3,读数据49byte[] buffer =newbyte[1024];50intlen =-1;51while( (len =in.read(buffer)) !=-1) {52//4,写数据53out.write(buffer,0, len);54}55//5,关闭流56in.close();57out.close();58}5960//方式3: 采用高效的流,一次一个字节的方式复制61privatestaticvoidmethod3(String src, String dest) throws IOException{62//1,指定数据源63BufferedInputStreamin=newBufferedInputStream(newFileInputStream(src));64//2,指定目的地65BufferedOutputStreamout=newBufferedOutputStream(newFileOutputStream(dest));66//3,读数据67intch =-1;68while((ch=in.read()) !=-1) {69//4,写数据70out.write(ch);71}72//5,关闭流73in.close();74out.close();75}7677//方式2: 采用基本的流,一个多个字节的方式赋值78privatestaticvoidmethod2(String src, String dest) throws IOException{79//1,指定数据源80FileInputStreamin=newFileInputStream(src);81//2,指定目的地82FileOutputStreamout=newFileOutputStream(dest);83//3,读数据84byte[] buffer =newbyte[1024];85intlen =-1;86while( (len=in.read(buffer)) !=-1) {87//4,写数据88out.write(buffer,0, len);89}90//5,关闭流91in.close();92out.close();93}9495//方式1: 采用基本的流,一次一个字节的方式复制96privatestaticvoidmethod1(String src, String dest) throws IOException{97//1,指定数据源98FileInputStreamin=newFileInputStream(src);99//2,指定目的地100FileOutputStreamout=newFileOutputStream(dest);101//3,读数据102intch =-1;103while(( ch=in.read()) !=-1) {104//4,写数据105out.write(ch);106}107//5,关闭流108in.close();109out.close();110}111}

4.2.字符缓冲流

字符缓冲输入流 BufferedReader

字符缓冲输出流 BufferedWriter

完成文本数据的高效的写入与读取的操作

4.2.1.字符缓冲输出流BufferedWriter

将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

方法:void newLine() 根据当前的系统,写入一个换行符

1/*

2  * BufferedWriter 字符缓冲输出流

3  * 方法

4  *    public void newLine()写入一个行分隔符

5  *

6  * 需求: 通过缓冲输出流写入数据到文件

7  * 分析:

8  *    1,创建流对象

9  *    2,写数据

10  *    3,关闭流

11  *

12  */13publicclassBufferedWriterDemo{14publicstaticvoidmain(String[] args) throws IOException{15//创建流16//基本字符输出流17FileWriter fileOut =newFileWriter("file.txt");18//把基本的流进行包装19BufferedWriterout=newBufferedWriter(fileOut);20//2,写数据21for(inti=0; i<5; i++) {22out.write("hello");23out.newLine();24}25//3,关闭流26out.close();27}28}

4.2.2.字符缓冲输入流BufferedReader

从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

方法public readLine () 读取一个文本行, 包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null

1/*

2  * BufferedReader 字符缓冲输入流

3  *

4  * 方法:

5  *    String readLine()

6  * 需求:从文件中读取数据,并显示数据

7  */8publicclassBufferedReaderDemo{9publicstaticvoidmain(String[] args) throws IOException{10//1,创建流11BufferedReaderin=newBufferedReader(newFileReader("file.txt"));12//2,读数据13//一次一个字符14//一次一个字符数组15//一次读取文本中一行的字符串内容16String line =null;17while( (line =in.readLine()) !=null){18System.out.println(line);19}2021//3,关闭流22in.close();23}24}

4.2.3.使用字符缓冲流完成文本文件的复制

刚刚我们学习完了缓冲流,现在我们就使用字符缓冲流的特有功能,完成文本文件的复制

1/*

2  * 采用高效的字符缓冲流,完成文本文件的赋值

3  *

4  * 数据源: file.txt

5  * 目的地: copyFile.txt

6  *

7  * 分析:

8  *    1,指定数据源, 是数据源中读数据,采用输入流

9  *    2,指定目的地,是把数据写入目的地,采用输出流

10  *    3,读数据

11  *    4,写数据

12  *    5,关闭流

13  */14publicclassCopyTextFile{15publicstaticvoidmain(String[] args) throws IOException{16//1,指定数据源, 是数据源中读数据,采用输入流17BufferedReaderin=newBufferedReader(newFileReader("file.txt"));18//2,指定目的地,是把数据写入目的地,采用输出流19BufferedWriterout=newBufferedWriter(newFileWriter("copyFile.txt"));20//3,读数据21String line =null;22while( (line =in.readLine()) !=null) {23//4,写数据24out.write(line);25//写入换行符号26out.newLine();27}28//5,关闭流29out.close();30in.close();31}32}

5.Properties类

5.1. Properties类介绍

Properties特点:

1 、 Hashtable 的子类, map 集合中的方法都可以用。

2 、该集合没有泛型。键值都是字符串。

3 、它是一个可以持久化的属性集。键值可以存储到集合中,也可以存储到持久化的设备 ( 硬盘、 U 盘、光盘 ) 上。键值的来源也可以是持久化的设备。

4 、有和流技术相结合的方法。

a.load(InputStream)  把指定流所对应的文件中的数据,读取出来,保存到Propertie集合中

b. load(Reader)

c. store(OutputStream,commonts)把集合中的数据,保存到指定的流所对应的文件中,参数commonts代表对描述信息

d.stroe(Writer,comments);

1/*

2  *

3  * Properties集合,它是唯一一个能与IO流交互的集合

4  *

5  * 需求:向Properties集合中添加元素,并遍历

6  *

7  * 方法:

8  * public Object setProperty(String key, String value)调用 Hashtable 的方法 put。

9  * public Set stringPropertyNames()返回此属性列表中的键集,

10  * public String getProperty(String key)用指定的键在此属性列表中搜索属性

11  */12publicclassPropertiesDemo01{13publicstaticvoidmain(String[] args){14//创建集合对象15Properties prop =newProperties();16//添加元素到集合17//prop.put(key, value);18prop.setProperty("周迅","张学友");19prop.setProperty("李小璐","贾乃亮");20prop.setProperty("杨幂","刘恺威");2122//System.out.println(prop);//测试的使用23//遍历集合24Set keys = prop.stringPropertyNames();25for(String key : keys) {26//通过键 找值27//prop.get(key)28Stringvalue= prop.getProperty(key);29System.out.println(key+"=="+value);30}31}32}

将配置文件中的数据存储到文件中

1/**

2  * 需求:使用Properties集合,完成把集合内容存储到IO流所对应文件中的操作

3  *

4  * 分析:

5  *    1,创建Properties集合

6  *    2,添加元素到集合

7  *    3,创建流

8  *    4,把集合中的数据存储到流所对应的文件中

9  *        store(OutputStream,commonts)把集合中的数据,保存到指定的流所对应的文件中,参数commonts代表对描述信息

10  *        stroe(Writer,comments);

11  *    5,关闭流

12  */13publicclassPropertiesDemo02{14publicstaticvoidmain(String[] args) throws IOException{15//1,创建Properties集合16Properties prop =newProperties();17//2,添加元素到集合18prop.setProperty("周迅","张学友");19prop.setProperty("李小璐","贾乃亮");20prop.setProperty("杨幂","刘恺威");2122//3,创建流23FileWriterout=newFileWriter("prop.properties");24//4,把集合中的数据存储到流所对应的文件中25prop.store(out,"save data");26//5,关闭流27out.close();28}29}

读取配置文件中的数据,同时更新数据,并保存

1/*

2  * 需求:从属性集文件prop.properties 中取出数据,保存到集合中

3  * 分析:

4  *    1,创建集合

5  *    2,创建流对象

6  *    3,把流所对应文件中的数据 读取到集合中

7  *        load(InputStream)  把指定流所对应的文件中的数据,读取出来,保存到Propertie集合中

8        load(Reader) 

9  *    4,关闭流

10  *    5,显示集合中的数据

11  */12publicclassPropertiesDemo03{13publicstaticvoidmain(String[] args) throws IOException{14//1,创建集合15Properties prop =newProperties();16//2,创建流对象17FileInputStreamin=newFileInputStream("prop.properties");18//FileReader in = new FileReader("prop.properties");19//3,把流所对应文件中的数据 读取到集合中20prop.load(in);21//4,关闭流22in.close();23//5,显示集合中的数据24System.out.println(prop);2526}

注意:使用字符流 FileReader 就可以完成文件中文的读取操作了

6.序列化流与烦序列化流

6.1.对象序列化流

用于从流中读取对象的操作流 ObjectInputStream   称为 反序列化流

用于向流中写入对象的操作流 ObjectOutputStream   称为 序列化流

特点:用于操作对象。

解决问题:可以将对象进行序列化和反序列化。

注意:对象序列化一定要实现Serializable接口。为了给类定义一个 serialVersionUID 。

功能:

ObjectInputStream readObject()

ObjectOutputStream writeObject()

1publicclassObjectStreamDemo{2publicstaticvoidmain(String[] args)throwsIOException, ClassNotFoundException{3/*

4          * 将一个对象存储到持久化(硬盘)的设备上。

5          */6writeObj();//对象的序列化。7}8publicstaticvoidwriteObj()throwsIOException{9//1,明确存储对象的文件。10FileOutputStream fos =newFileOutputStream("tempfile\\obj.object");11//2,给操作文件对象加入写入对象功能。12ObjectOutputStream oos =newObjectOutputStream(fos);13//3,调用了写入对象的方法。14oos.writeObject(newPerson("wangcai",20));15//关闭资源。16oos.close();17}18}

6.2.对象反序列化流

当把一个对象持久化存储起来之后,需要使用反序列化技术获取存储起来的对象。 使用此 ObjectInputStream 对象就可以完成反序列化动作

1publicclassObjectStreamDemo{2publicstaticvoidmain(String[] args)throwsIOException, ClassNotFoundException{3readObj();//对象的反序列化。4}5publicstaticvoidreadObj()throwsIOException, ClassNotFoundException{67//1,定义流对象关联存储了对象文件。8FileInputStream fis =newFileInputStream("tempfile\\obj.object");910//2,建立用于读取对象的功能对象。11ObjectInputStream ois =newObjectInputStream(fis);1213Person obj = (Person)ois.readObject();1415System.out.println(obj.toString());1617}18}

6.3.序列化接口

当一个对象要能被序列化,这个对象所属的类必须实现Serializable 接口。否则会发生异常 NotSerializableException 异常。

同时当反序列化对象时,如果对象所属的 class 文件在序列化之后进行的修改,那么进行反序列化也会发生异常 InvalidClassException 。发生这个异常的原因如下:

该类的序列版本号与从流中读取的类描述符的版本号不匹配

该类包含未知数据类型

该类没有可访问的无参数构造方法

Serializable 标记接口。该接口给需要序列化的类,提供了一个序列版本号。 serialVersionUID. 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。

1publicclassPersonimplementsSerializable{23//给类显示声明一个序列版本号。4privatestaticfinallongserialVersionUID =1L;5privateString name;6privateintage;7publicPerson(){8super();910}11publicPerson(String name,intage){12super();13this.name = name;14this.age = age;15}1617publicStringgetName(){18returnname;19}20publicvoidsetName(String name){21this.name = name;22}23publicintgetAge(){24returnage;25}26publicvoidsetAge(intage){27this.age = age;28}29@Override30publicStringtoString(){31return"Person [name="+ name +", age="+ age +"]";32}33}

7.总结

字节流

字节输入流 InputStream

FileInputStream 操作文件的字节输入流

BufferedInputStream高效的字节输入流

ObjectInputStream 反序列化流(操作对象的字节输入流)

字节输出流 OutputStram

FileOutputStream 操作文件的字节输出流

BufferedOutputStream 高效的字节输出流

ObjectOuputStream 序列化流(操作对象的字节输出流)

字符流

字符输入流 Reader

FileReader 操作文件的字符输入流

BufferedReader 高效的字符输入流

InputStreamReader 输入操作的转换流(把字节流封装成字符流)

字符输出流 Writer

FileWriter 操作文件的字符输出流

BufferedWriter 高效的字符输出流

OutputStreamWriter 输出操作的转换流(把字节流封装成字符流)

将字符流转换成字节流去存储

方法:

读数据方法:

read() 一次读一个字节或字符的方法

read(byte[]  char[]) 一次读一个数组数据的方法

readLine() 一次读一行字符串的方法(BufferedReader类特有方法)

readObject() 从流中读取对象(ObjectInputStream特有方法)

写数据方法:

write(int) 一次写一个字节或字符到文件中

write(byte[] char[]) 一次写一个数组数据到文件中

write(String) 一次写一个字符串内容到文件中

writeObject(Object ) 写对象到流中(ObjectOutputStream类特有方法)

newLine() 写一个换行符号(BufferedWriter类特有方法)

向文件中写入数据的过程

1,创建输出流对象

2,写数据到文件

3,关闭输出流

从文件中读数据的过程

1, 创建输入流对象

2, 从文件中读数据

3, 关闭输入流

文件复制的过程

1, 创建输入流(数据源)

2, 创建输出流(目的地)

3, 从输入流中读数据

4, 通过输出流,把数据写入目的地

5, 关闭流

Properties:Map集合的一种,它是Hashtable集合的子集合,它键与值都是String类型,它是唯一能与IO流结合使用的集合

方法

load( InputStream in ) 从流所对应的文件中,读数据到集合中

load( Reader in ) 从流所对应的文件中,读数据到集合中

store( OutputStream out , String message ) 把集合中的数据,写入到流所对应的文件中

store( Writer out , String message) 把集合中的数据,写入到流所对应的文件中

实现文件内容的自动追加

构造方法

FileOutputStream(File file, boolean append)

FileOutputStream(String fileName, boolean append)

FileWriter(File, boolean append)

FileWriter(String fileName, boolean append)

小编整理了一些java进阶学习资料和面试题,需要资料的请加JAVA高阶学习Q群:664389243 这是小编创建的java高阶学习交流群,加群一起交流学习深造。群里也有小编整理的2019年最新最全的java高阶学习资料!

你可能感兴趣的:(谈谈java中的IO流)