java中0.33_java进阶(33)--IO流

------------------------------------------分割线,以下为正文-------------------------------------------------

一、IO流概念:

1、基本概念

I:Input

O:Output

通过IO可以完成硬盘文件的读和写。

2、IO流分类

(1)按照流的方向分类:

输入流(Input)或者称为读(Reader)

输出流(Output)或者称为写(Write)

(2)按照读取数据方式不同分类:

字节流:按照字节方式读取数据,一次读取1个字节byte,等同一个8个二进制位,这种流是万能的,什么类型的文件都可以读取,包括:文本文件、图片、视频、声音等

字符流:按照字符方式读取数据,一次读取一个字符,这种流是为了方便读取普通文件而存在,这种流不能读取图片、声音、视频、word等,只能读取纯文本文件。

假设文件test.txt 内容为:"h世界"

字节流读取:第一次读'h'(占用一个字节),第二次读'世'字符的一半(占用一个字节)

字符流读取:第一次读'h'(占用一个字节),第二次读'世'字符(占用一个字符)

3、java.io流的四大家族

(1)java.io.InputStream字节输入流

(2)java.io.OutputStream字节输出流

(3)java.io.Reader字符输入流

(4)java.io.Writer字符输出流

在java中以Stream结尾都是字节流,以Reader/Writer结尾都是字符流

4、流的close和flush方法

(1)close()

所有的流都实现java.io.closeble接口,都是可以关闭的,都右close方法。

流是一个管理,是内存与硬盘之间的通道,用完之后一定要关闭,不然会耗费很多资源,养成好习惯,用完流一定要关闭。

(2)flush()

所有的输出流都实现了java.io.Flushable接口,都可以刷新,都包含flush方法。

养成好习惯,输出流输出玩都需要flush刷新一下,表示将通道/管道当中的剩余未输出的数据强行输出完,即清空管道,没有使用flush方法会导致数据丢失

5、java.io下常用的16个流

(1)文件专属:

java.io.FileInputStream;

java.io.FileOutputStream;

java.io.FileReader;

java.io.FileWriter;

(2)转换流:字节流转为字符流

java.io.InputStream;

java.io.OutputStream;

(3)缓冲区专属:

java.io.BufferedInputStream;

java.io.BufferedOutputStream;

java.io.BufferedReader;

java.io.BufferedWriter;

(4)数据专属:

java.io.DataInputStream;

java.io.DataOutputStream;

(5)标准输出流:

java.io.PrintStream;

java.io.PrintWriter;

(6)对象专属:

java.io.ObjectInputStream;

java.io.ObjectOutputStream;

二、FileInputStream字节输入流

1、FileInputStream完成字节流输入的流程

(1)准备文件如下:

9e4fd6b2fedb791d69e7ab5ffc48f284.png

(2)创建字节流输入对象,Idea自动将路径变斜杠

e4a675c6e0ffdfcd3e0f5729ceeec7fc.png

(3)alt+回车添加try+catch或者上报异常,这里选择try+catch

81adaecf2ea1e92065d316dbae723a44.png

(4)第二种文件路径编写方式"\"与"//"等价

a71452b90d547cc1086149411c52ccf9.png

(5)增加finally语句且初始化流放在try+catch语句外,并添加流的关闭,流关闭前需要增加流的判空ifn可默认生成 if(fis==null)

48b2cd725eeed27e382b173bcc0877dc.png

(6)增加流的读取,并添加try+catch使用alt+回车,这里建议选择第一种异常

第一种:增加catch使用细粒度的异常

第二种:方法声明异常

第三种:替换外层FIleNotFount为IO异常

第四种:内层在增加try+catch

e4ee03b03e2f1a9d5341f73502a70f7e.png

(7)查看打印结果为a对应的字符ascII码值97

9b938b3984846c442a0061f4ef6688c5.png

(8)可重复读取6次,最后一次读取不到返回-1

9a38575699b44d1f956808f38b37876f.png

2、使用while优化FileInputStream读取流程

760caedee67bae04135c53c00fd69fb9.png

3、FileInputStream最终版,使用byte数组读取

ea2bfffba6f654bcaaff9254acea4802.png

4、FileInputStream的available

(1)查看剩余的字节数

741842cedb60f8499240c741e0346884.png

(2)available的作用:可以不适用while循环,直接一次读取全部的字节,但是不适合大的文件,因为byte数组不能太大

d0eec2093df6f2aede140b676dbd09f1.png

5、FileInputStream的skip方法

4acf90c9882065b31c6c7c9c8e5f3d57.png

三、FileOutputStream字节输出流

1、FileOutputStream概念:

字节输出流,从内存到硬盘

2、FileOutputStream输出流程

(1)使用byte数组+write方法+flush方法写入

aa340ef8328cd676d6ebe21ae286e060.png

(2)检查文件结果,相对路径为项目根目录下:

71881d84f048b936033f50f6eb226249.png

(3)再次执行,会将原文件中内容覆盖,依然输出:abcdab

(4)修改构造方法,true代表文本的追加

66659f74ce5c15bdf2902139464a5603.png

(5)查看相对路径下的文本执行结果:文本追加了内容

9662c99687efff283e1692be0d97c710.png

3、改进FileInputStream+String输出

(1)使用String转byte数组输出

fcdb7c3b05b17463ae99ea61bfbaf05b.png

(2)查看输出结果,追加一段String字符串

fc82df5942cf6537f56cbb67eaf298fb.png

4、文件复制(FileInputStream+FileOutputStream)

(1)流程:拷贝过程是一边读、一边写;文件类型任意,是万能的

(2)举例文件复制:

1 packageJAVAADVANCE;2

3 importjava.io.FileInputStream;4 importjava.io.FileNotFoundException;5 importjava.io.FileOutputStream;6 importjava.io.IOException;7

8 public classTestAdvance33IOTest08 {9 public static voidmain(String[] args) {10 FileInputStream fis=null;11 FileOutputStream fos=null;12 try{13 //创建一个输入对象流

14 fis=new FileInputStream("D:\\javaTest\\inFile\\甜蜜家园第01集.mp4");15 //创建一个输出对象流

16 fos=new FileOutputStream("D:\\javaTest\\outFile\\甜蜜家园第01集.mp4");17 //准备一个byte数组,1024byte=1KB,*1024=1M,一次最多读1M

18 byte[] bytes=new byte[1024*1024];19 int readCount=0;20 while ((readCount=fis.read(bytes))!=-1)21 {22 //读取多少,写多少

23 fos.write(bytes,0,readCount);24 }25 fos.flush();26 } catch(FileNotFoundException e) {27 e.printStackTrace();28 } catch(IOException e) {29 e.printStackTrace();30 } finally{31 //fos与fis的关闭分开try catch比较好,避免互相影响,有流没有关闭

32 if (fos != null) {33 try{34 fos.close();35 } catch(IOException e) {36 e.printStackTrace();37 }38 }39 if(fis!=null){40 try{41 fis.close();42 } catch(IOException e) {43 e.printStackTrace();44 }45 }46 }47

48

49

50

51 }52 }

查看文件输出结果

028788c68623394ec11a4466041a9d4a.png\

四、FileReader与FileWrite

1、FileReader概念

文件字符输入流,只能读取普通文本,读取文本内容时比较方便、快捷

2、举例FileReader

1 packageJAVAADVANCE;2 import java.io.*;3 public classTestAdvance33IOTest09FileReader {4 public static voidmain(String[] args) {5 FileReader reader= null;6 try{7 //创建字符输入流

8 reader=new FileReader("C:\\Users\\Mr.White\\IdeaProjects\\javaAdvance\\myTestFile01");9 //开始读,使用char数组,一次读取4个字符

10 char[] chars=new char[4];11 int readCount=0;12 while ((readCount=reader.read(chars))!=-1){13 System.out.println(new String(chars,0,readCount));14 }15 } catch(FileNotFoundException e) {16 e.printStackTrace();17 } catch(IOException e) {18 e.printStackTrace();19 } finally{20 if (reader != null) {21 try{22 reader.close();23 } catch(IOException e) {24 e.printStackTrace();25 }26 }27 }28 }29 }

检查源文件与读取的内容

e80262a4dd74619dc8e39cf770f68a22.png

3、FileWrite概念:

文件字符输出流,只能输出普通文本

4、举例FileWrite:

1 packageJAVAADVANCE;2 importjava.io.FileWriter;3 importjava.io.IOException;4 public classTestAdvance33IOTest10FileWrite {5 public static voidmain(String[] args) {6 FileWriter out = null;7 try{8 //创建字符输出流对象,true使用追加写入模式,否则重新执行会覆盖

9 out=new FileWriter("fileWriteTest01",true);10 //开始写,使用char数组

11 char[] chars={'我','是','中','国','人'};12 //写入全部char数组

13 out.write(chars);14 //再写入部分char数组,第3个字符开始,3个字符

15 out.write(chars,2,3);16 //直接写入String

17 out.write("我是个JAVA工程师");18 out.flush();19 } catch(IOException e) {20 e.printStackTrace();21 }finally{22 if (out != null) {23 try{24 out.close();25 } catch(IOException e) {26 e.printStackTrace();27 }28 }29 }30 }31 }

查看输出结果,相对路径为工程根目录下

ad2515b7b688f71bf47569831816343c.png

5、复制普通文件(FileReader与FileWrite):

(1)使用FileReader与FileWrite进行拷贝,只能拷贝普通文本文件

(2)举例复制普通文件:

1 packageJAVAADVANCE;2 importjava.io.FileNotFoundException;3 importjava.io.FileReader;4 importjava.io.FileWriter;5 importjava.io.IOException;6 public classTestAdvance33IOTest11NormalFileCopy {7 public static voidmain(String[] args) {8 FileReader in =null;9 FileWriter out = null;10 try{11 //创建字符输入流

12 in=new FileReader("D:\\javaTest\\inFile\\fileWriteTest01");13 //创建字符输出流

14 out=new FileWriter("D:\\javaTest\\outFile\\fileWriteTest01");15 //一边读一边写

16 char[] chars=new char[1024*512]; //一次读取1M文件

17 int readCount=0;18 while ((readCount=in.read(chars))!=-1){19 out.write(new String(chars,0,readCount));20 }21 //写完后刷新

22 out.flush();23 } catch(FileNotFoundException e) {24 e.printStackTrace();25 } catch(IOException e) {26 e.printStackTrace();27 } finally{28 if (in != null) {29 try{30 in.close();31 } catch(IOException e) {32 e.printStackTrace();33 }34 }35 if (out != null) {36 try{37 out.close();38 } catch(IOException e) {39 e.printStackTrace();40 }41 }42 }43 }44 }

查看复制后结果

314a4b300aa10cd62cd090585b1ca0eb.png

五、带有缓冲区的字符流

1、BufferedReader概念:

带有缓冲区的字符输入流,使用此流不需要自定义char数组,或者说不需要自定义byte数组,自带缓冲区。

2、举例说明BufferedReader:

(1)准备文件

147860bdb2cc183436858577fa9d8d28.png

(2)按照行读取文件

packageJAVAADVANCE;import java.io.*;public classTestAdvance33IOTest12BufferedReader {//异常先抛出

public static void main(String[] args) throwsIOException {

FileReader reader=new FileReader("D:\\javaTest\\inFile\\fileWriteTest02");//FileReader为节点流,BufferedReader为包装流/处理流

BufferedReader br=newBufferedReader(reader);//读第一行

String firstLine =br.readLine();

System.out.println(firstLine);//读第二行

String secondLine =br.readLine();

System.out.println(secondLine);//读第三行

String thirdLine =br.readLine();

System.out.println(thirdLine);//只需要关闭最外层的流,对于包装流来说

br.close();

}

}

(3)循环读取全部文件

1 packageJAVAADVANCE;2 importjava.io.BufferedReader;3 importjava.io.FileReader;4 importjava.io.IOException;5 public classTestAdvance33IOTest12BufferedReader02 {6 //异常先抛出

7 public static void main(String[] args) throwsIOException {8 FileReader reader=new FileReader("D:\\javaTest\\inFile\\fileWriteTest02");9 //FileReader为节点流,BufferedReader为包装流/处理流

10 BufferedReader br=newBufferedReader(reader);11 //使用String字符串读取

12 String s=null;13 while ((s=br.readLine())!=null){14 System.out.println(s);15 }16 //只需要关闭最外层的流,对于包装流来说

17 br.close();18 }19 }

检查执行结果

24d47c7ea20b36208f38c97ff4a87465.png

(4)print方法测试readLine方法不带换行符

1 packageJAVAADVANCE;2 importjava.io.BufferedReader;3 importjava.io.FileReader;4 importjava.io.IOException;5 public classTestAdvance33IOTest12BufferedReader02 {6 //异常先抛出

7 public static void main(String[] args) throwsIOException {8 FileReader reader=new FileReader("D:\\javaTest\\inFile\\fileWriteTest02");9 //FileReader为节点流,BufferedReader为包装流/处理流

10 BufferedReader br=newBufferedReader(reader);11 //使用String字符串读取

12 String s=null;13 while ((s=br.readLine())!=null){14 //print方法测试readLine方法不带换行符

15 System.out.print(s);16 }17 //只需要关闭最外层的流,对于包装流来说

18 br.close();19 }20 }

查看执行结果

d533adc33fa410f24b237ab888e07199.png

3、节点流与包装流

(1)节点流与包装流都是相对而言

(2)举例说明:节点流与包装流

以下例子:

in与reader:in为节点流,reader为包装流

reader与br:reader与节点流,br为包装流

packageJAVAADVANCE;import java.io.*;public classTestAdvance33IOTest12BufferedReader03 {//异常先抛出

public static void main(String[] args) throwsIOException {

FileInputStream in=new FileInputStream("D:\\javaTest\\inFile\\fileWriteTest02");//通过InputStreamReader转换流将字节流转换为字符流

InputStreamReader reader=newInputStreamReader(in);

BufferedReader br=newBufferedReader(reader);//使用String字符串读取

String line=null;while ((line=br.readLine())!=null){//print方法测试readLine方法不带换行符

System.out.println(line);

}//只需要关闭最外层的流,对于包装流来说

br.close();

}

}

查看运行结果:

045ad835fcb75d2ff0374d8e5ab67060.png

4、BufferedWrite:带有缓冲区的字符输出流

(1)举例说明BufferedWrite

packageJAVAADVANCE;import java.io.*;public classTestAdvance33IOTest13BufferedWrite {//异常先抛出

public static void main(String[] args) throwsIOException {

BufferedWriter out=new BufferedWriter(new FileWriter("D:\\javaTest\\outFile\\fileWriteTest02"));

out.write("hello world");

out.write("\nhello kitty");

out.flush();

out.close();

}

}

查看执行结果

0ebc393fd924646d1cbcfb6bda74cadc.png

(2)使用包装流追加输出

packageJAVAADVANCE;import java.io.*;public classTestAdvance33IOTest13BufferedWrite02 {//异常先抛出

public static void main(String[] args) throwsIOException {

BufferedWriter out=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("D:\\javaTest\\outFile\\fileWriteTest02",true)));

out.write("\n这是继续使用包装流追加的文字");

out.flush();

out.close();

}

}

查看执行结果:

80359e28035f9a34fbeda9bab53bf470.png

六、数据流

1、DataOutputStream概念:

数据专属的流

这个流可以将数据连同数据的类型一并写入文件

注意:这个文件不同普通文本文档(这个文件使用记事本打不开)

2、举例说明:DataOutputStream

packageJAVAADVANCE;import java.io.*;public classTestAdvance33IOTest14DataOutputStream01 {//异常先抛出

public static void main(String[] args) throwsIOException {//创建数据专属字节输出流

DataOutputStream dos=new DataOutputStream(new FileOutputStream("D:\\javaTest\\outFile\\fileWriteTest03"));byte b=100;short s=200;int i=300;float t=400F;double d=3.14;boolean sex=false;char c='a';

dos.writeByte(b);

dos.writeShort(s);

dos.writeInt(i);

dos.writeFloat(t);

dos.writeDouble(d);

dos.writeBoolean(sex);

dos.writeChar(c);

dos.flush();

dos.close();

}

}

查看文件结果:无法使用记事本或notepad++打开,需要使用DataInputStream流打开,并且读的顺序需要与写的顺序一致。

3e1c9dfba2f85e2a59550d22079a3382.png

3、DataInputStream流概念:

数据字节输入流,DataOutputStream流写的文件只能使用DataInputStream打开,并且读的顺序需要和写的顺序一致。

4、举例说明:DataInputStream

1 packageJAVAADVANCE;2 import java.io.*;3 public classTestAdvance33IOTest15DataInputStream01 {4 //异常先抛出

5 public static void main(String[] args) throwsIOException {6 //创建数据专属字节输入流

7 DataInputStream dis =new DataInputStream(new FileInputStream("D:\\javaTest\\outFile\\fileWriteTest03"));8 //开始读,读的顺序要与写的时候保持一致。

9 byte b=dis.readByte();10 short s=dis.readShort();11 int i=dis.readInt();12 float t =dis.readFloat();13 double d=dis.readDouble();14 boolean sex=dis.readBoolean();15 char c=dis.readChar();16 dis.close();17 System.out.println(b);18 System.out.println(s);19 System.out.println(i);20 System.out.println(t);21 System.out.println(d);22 System.out.println(sex);23 System.out.println(c);24

25 }26 }

查看显示结果

397e444aa809c4cb09047bc73802dc75.png

七、标准输出流

1、PrintStream标准字节输出流:

标准字节输出流,默认输出到控制台。

1 packageJAVAADVANCE;2 importjava.io.IOException;3 importjava.io.PrintStream;4 public classTestAdvance33IOTest16PrintStream01 {5 //异常先抛出

6 public static void main(String[] args) throwsIOException {7 //标准输出流直接输出到控制台

8 System.out.println("hello world");9 //换一种写法

10 PrintStream ps=System.out;11 ps.println("hello zhangsan");12 ps.println("hello lisi");13 //标准输出流不需要手动关闭

14 }15 }

2、更改标准输出流的输出方向

1 packageJAVAADVANCE;2 importjava.io.FileOutputStream;3 importjava.io.IOException;4 importjava.io.PrintStream;5 public classTestAdvance33IOTest16PrintStream01 {6 //异常先抛出

7 public static void main(String[] args) throwsIOException {8 //更改标准输出流的输出方向,指向log文件

9 System.setOut(new PrintStream(new FileOutputStream("log")));10 //再次输出

11 System.out.println("hello world");12 System.out.println("hello kitty");13 }14 }

查看项目根目录的输出文件

f78337d7c143109d9eb323fe8b904ebf.png

3、日志工具生成原理:

packageJAVAADVANCE;importjava.io.FileNotFoundException;importjava.io.FileOutputStream;importjava.io.PrintStream;importjava.text.SimpleDateFormat;importjava.util.Date;public classTestAdvance33IOTest16LogTest {//异常先抛出

public static voidlog(String msg) {try{

PrintStream out=new PrintStream(new FileOutputStream("log.txt",true));//改变文件的输出方向

System.setOut(out);//当前日期格式

Date nowTime = newDate();

SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");

String strTime=sdf.format(nowTime);

}catch(FileNotFoundException e) {

e.printStackTrace();

}

}

}

编写测试程序开始测试日志打印

1 packageJAVAADVANCE;2 public classTestAdvance33IOTest16LogTest {3 public static voidmain(String[] args) {4 //测试工具是否好用

5 TestAdvance33IOTest16PrintStream02.log("调用了Sytem的gc()方法,建议启动垃圾回收");6 TestAdvance33IOTest16PrintStream02.log("调用了userService的dosome()方法");7 TestAdvance33IOTest16PrintStream02.log("用户正在尝试登录,验证失败");8 }9 }

查看输出结果

4549cfdf479e5e5b8de0ef34ed615866.png

八、File类

File类参照如下章节:

九、对象流

对象流、序列化与反序列化参考如下章节:

十、IO和Properties

IO和Properties联合使用参考如下章节:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值