day28_io

  • io流
  • 字节流
  • 字符流
  • io中的异常处理

学习目标:

  1. ​ 说出io流的分类与功能
  2. ​ 使用字节输出流写出数据到文件
  3. ​ 使用字节输入流读取数据到程序中
  4. ​ 理解读取数据read方法的原理
  5. ​ 使用字节流完成文件的复制
  6. ​ 使用FileWriter写数据到文件中
  7. ​ 说出FileWriter中关闭和刷新方法的区别
  8. ​ 使用FileWriter写数据的常用方法
  9. ​ 使用FileWriter实现数据的追加和换行
  10. ​ 使用FileReader读取数据
  11. ​ 使用FileReader读取数据一次一个字符数组
  12. ​ 使用Properties的load方法和store方法加载文件中的配置信息

IO

两大类	      抽象类       实现子类      缓冲流
----|字节流
	----|InputStream
		----|FileInputStream
		********
			----|BufferedInputStream
	----|OutputStream
		----|FileOutputStream
		********
			----|BufferedOutputStream
	
	      抽象类   缓冲流    实现子类           
----|字节流
	----|Reader
		----|BufferedReader
		----|InputStreamReader
			----|FileReader
		********
	----|Writer
		----|BufferedWriter
		----|OutputStreamWriter
			----|FileWriter
		********

什么是io呢?

​ 输入与输出

输入:把硬盘中的数据,读取到内存中使用

输出:把内存中的数据写入到硬盘保存

IO流的顶级父类

输入流 输出流
字节流 InputStream OutputStream
字符流 Reader Writer

Java中I/O的操作主要是靠java.io包下的类和接口来实现的,进行输入和输出操作。输入也可以叫做读取数据,输出也可以叫做写入数据

IO分类

根据数据的流向分为:输入流 / 输出流

  • ​ 输入流:把数据从其他设备上读取到内存当中的流
  • ​ 输出流:把数据从内存当中写入到其他设备上的流

根据数据的类型分为:字节流 / 字符流

  • ​ 字节流:以字节为单位,读写数据的流
  • ​ 字符流:以字符为单位,读写数据的流

字节流

一切皆为字节

​ 一切文件数据(文档、图片、视频、音频...)都是以二进制数字的形式保存,都是一个个字节。数据进行传输的时候,也是以字节形式传输。so字节流可以传输任意文件的数据,在操作流的时候,我们必须明确:无论使用什么样的流对线,低层始终以二进制传输。

字节输出流【OutputStream】

java.io.OutputStream此抽象类是表示输出字节流的所有类的超类,讲指定的字节信息写入目的地,定义了字节输出流基本共性的方法:

  • ​ public void close():关闭此输出流,释放与此流相关的其他任何系统资源
  • ​ public void flush():刷新此输出流并强制任何缓冲的输出字节信息被写入
  • ​ public void write(byte[ ] b):将b.length字节从指定的字节数组写入到输出流中
  • ​ public void write(bytr [ ] ,int off,int len):从指定的字节数组写入len个字节,从偏移量off开始输出到此输出流中
  • ​ public abstract void write(int b) :将指定的字节输出到此输出流中

备注:close方法,当完成流的操作时,必须完成此方法,释放系统资源。

FileOutPutStream

java.io.FileOutPutStream类是文件字节输出流,用于将数据写入到文件

构造方法:

  • ​ public FileOutputStream(File file): 创建一个向指定 File 对象表示的文件中写入数据的文件输出流
  • ​ public FileOutputStream(String name):创建文件输出流以指定的文件名称写入文件
File file :目的地是一个文件
String name :目的地是一个文件路径

构造方法作用:

  1. ​ 创建一个FileOutputStream类对象
  2. ​ 根据构造方法中传递的文件 / 文件路径 (路径上的文件不存在),创建一个空文件
  3. ​ 会把FileOutputStream对象指向创建好的文件

当你创建一个流对象是,必须先传递文件路径,该路径如果没有这个文件,自己创建;如果有这个文件,情况这个文件当中的数据,再把新的内容写入

FileOutputStream fileOutputStream = new FileOutputStream("C:\Users\42123\Desktop\newFile.txt");//1
fileOutputStream.write(98);//2
fileOutputStream.close();//3
写入数据的原理:
         Java程序--->JVM虚拟机--->OS--->OS中写入数据的方法--->把数据写入

备注:使用FileOutputStream写入硬盘文件时,写入的都是二进制码,使用文本编辑器查看的时候,文本编辑器根据编码表,把字节转换为字符表示让我们看到

数据的追加与续写

​ 如何在保留目标文件中数据的情况下,还能继续添加新的数据到目标文件中?

构造方法:

  • ​ public FileOutputStream(File file,boolean append):创建文件输出流以写入由指定的File对象表示的文件中。
  • ​ public FileOutputStream(String name,boolean append):创建文件输出流以指定的名称写入文件中

这两个构造方法,参数中都需要传入一个boolean类型的值,true表示追加数字、false表示清空原有数据。这样的清况下创建输出流对象,就可以指定是否需要在文件的末尾追加内容。

***使用write方法写入字节***
FileOutputStream fileOutputStream1 = new FileOutputStream("C:\Users\42123\Desktop\newFile.txt", true);
fileOutputStream1.write("
追加的内容:****".getBytes());
fileOutputStream1.close();
写入换行

在Windows中,换行符号是 . 代表回车 代表开始新的一行。

在Linux中,换行符号是/n.

在Mac中,换行符号是/r.

在Unix中,每行结尾只有换行,即/n.

回车符 和换行符

  • ​ 回车符:回到一行的开头
  • ​ 换行符:下一行(new Line)

系统中的换行:

​ Windows:每行结尾回车+换行,即

​ Unix系统中,每行结尾只有换行,即/n

​ Max系统中,每行结尾只有回车,即/r

字节输入流【InputStream】

java.io.InputStream此抽象类表示字节输入流所有类的超类,可以读取字节信息到内存中,它定义了输入流的基本共性方法:

  • ​ public void close():关闭此输入流并释放与此相关的其他的任何系统资源
  • ​ public abstract int read():从输入流中读取数据的下一个字节
  • ​ public int read(byte[ ] b):从输入流中读取一些字节数,并将它们存储到字节数组b当中

备注:close方法,当完成流的操作时,必须完成此方法,释放系统资源。

FileInputStream类

java.io.FileInputStream类是文件输入流,从硬盘文件中读取字节内容到内存

构造方法

  • ​ FileInputStream(File file):通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的File对象file命名
  • ​ FileInputStream(String name):通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的路径名name命名

参数:读取文件的数据源

​ String name :文件的路径

​ File file :文件

构造方法的作用:

  1. ​ 创建一个FileInputStream类对象
  2. ​ 会把FileInputStream类对象指定到构造方法中要读取的文件

当你创建一个流对象时,必须传入一个文件路径,该路径下,如果没有该文件,会抛出FileNotFoundException

***使用read方法读取字节***
File file = new File("C:\Users\42123\Desktop\newFile.txt");//路径不存在 抛出FileNotFoundException
//1.
FileInputStream fis = new FileInputStream(file);
//2.
int read = fis.read();//虽然读取了一个字节,但是会被自动提升为int类型
System.out.println(read);//读取到文件末尾会返回-1
读取数据的原理:
         Java程序--->JVM虚拟机--->OS--->OS中读取数据的方法--->把数据读取

练习:通过字节流实现图片复制

原理:从已知的文件读取字节,再把读取到的字节写入到另一个文件

FileInputStream fileInputStream = new 
FileInputStream("C:\Users\42123\Desktop\JDK1.6\QQ图片20201204140227.jpg");
        byte[] bytes = new byte[1024];
FileOutputStream fileOutputStream = new FileOutputStream("C:\Users\42123\Desktop\sss\bbb.jpg",true);
        //1k1k传输
        int len = 0;
        while ((len = fileInputStream.read(bytes))!=-1){
            fileOutputStream.write(bytes,0,len);
        }
fileOutputStream.close();
fileInputStream.close();//关闭流有先后顺序   先开的要后关

字符流

​ 当使用字节流读取文件的时候,可能会引发一些小问题。如果你遇到了中文字符时,可能不会显示完整的字符。那是因为一个中文字符占多个字符存储,不同的解码方式导致 。所以出现了字符流类,以字符为单位读写数据,专门用来处理文档文件

字符输入流【Reader】

java.io.Reader是一个抽象类,表示用于读取字符流所有类的超类,可以读取字符信息到内存当中,定义了字符输入流基本的共性方法:

  • ​ public void close():关闭此输入流并且释放与此流相关的其他系统资源
  • ​ public int read():从输入流中读取一个字符
  • ​ public int read(char [ ] chuf):从输入流中读取多个字符,并将他们存储到字符数组chuf中
FileReader类

java.io.FileReader类主要用于读取字符文件的便捷类。构造方法使用的是默认的编码字符集和默认的字节缓冲区

备注:

  1. ​ 字符编码:字节与字符的对应规则在Windows系统中,中文编码默认为GBK编码表,ideal中默认UTF-8
  2. ​ 字节缓冲区:一个数组,临时存储字节数据

构造方法:

  • ​ FileReader(File file):创建一个新的FileReader对象,指定需要读取的file对象
  • ​ FileReader(String filename):创建一个新的FileReader对象,指定需要读取的文件名称

当你创建一个流对象时,必须传入一个文件路径,类似于FileInputStream。

	   char []chuf = new char[1024];
        int len =0;
        while ((len =fr.read(chuf))!=-1){
            /*
            字符数组转换为字符串
            1.String  static  valueOf();
            2.String  (char[] value);
            3.String  (char[] value,int offset,int count);
             */
            System.out.println(String.valueOf(chuf,0,len));
        }
        fr.close();

使用字符数组读取数据:read( char []chuf)每次读取chuf的长度个字符到数组当中,返回读取到的有效字符个数,当读到末尾的时候,返回-1.

字符输出流【Writer】

java.io.Writer抽象类是表示用于输出字符流所有类的超类,将指定的字符信息写入到目的地,它定义了字符输出流的基本共性方法:

  • ​ void writer(int c):写入单个字符
  • ​ void writer(char [ ] chuf):写入字符数组
  • ​ abstract void writer(char [ ] chuf ,int off,int len):写入char数组的一部分,从索引off位置开始,写入len个字符个数
  • ​ void writer(String str):写入字符串
  • ​ void writer(String str,int off,int len):写入字符串的一部分,从字符串的起始索引off开始,写入len个字符
  • ​ void flush():刷新该流的缓冲。
  • ​ void close():关闭此流,但是需要先刷新它
FileWriter类

java.io.FileWriter类是用于写入字符到文件中,构造方法使用系统默认的字符编码和默认的字节缓冲区

构造方法
FileWriter(File file):创建一个新的FileWriter,指定写入的file对象

​ FileWriter(String name):创建一个新的FileWriter,指定需要写入的文件名称

当你创建一个流对象时,必须传入一个文件路径,类似于FileOutputStream

FileWriter fileWriter = new FileWriter("C:\Users\42123\Desktop\newFile.txt");
fileWriter.write("34");
//fileWriter.flush();//3.刷新,不释放资源的情况下无法写入
fileWriter.close();//会先把内存缓冲区中的数据刷新到文件中

关闭和刷新

​ 因为内置缓冲区的原因,如果不关闭输出流,无法写入字符到文件中。但是关闭流对象就无法写入数据到文件中。如果既想写入数据到文件中、又不想关闭流对象,那么就需要flush方法

flush():刷新缓冲区,流对象可以继续使用
close():先刷新缓冲区,然后关闭流对象,释放资源,流对象不可使用

写入字符数组:write(char [ ] chuf)writer(char [ ] chuf ,int off,int len)每次可以写入一个字符数组的数据

数据的追加和续写
  • ​ FileWriter(File file,boolean append)
  • ​ FileWriter(String filename,boolean append)

filename / file:写入数据的目的地

boolean append:追加数据的开关

​ true:不会创建新的文件覆盖源文件,可以续写

​ false:创建新的文件覆盖原文件,不能续写

备注:字符类,只能操作文本文件,不能操作图片、视频等非文本文件

所以当我们单纯的就是想操作文本文件,就使用字符流,其他情况一律使用字节流

io的异常处理

JDK1.7之前的处理:

使用try...catch...finally处理流中的异常

FileWriter fileWriter = null; //提高变量的作用域范围,使finally语句块能够使用到
        //为什么要初始化?
        //以下new对象时可能发生异常  进入catch块,对象可能创建失败,未完成初始化
        try {
            fileWriter = new FileWriter("", true);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            fileWriter.write(97);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            fileWriter.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                fileWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
JDK1.7之后的处理:

在try后可以增加一个(),在括号中定义流对象,那么这个流对象的作用域就在try中有效。
try中代码执行完毕,会自动把流对象释放,那么自然finally就舍弃了

try(FileWriter fileWriter = new FileWriter("C:\Users\42123\Desktop\newFile.txt",true);
             FileReader fr =new FileReader("C:\Users\42123\Desktop\newFile.txt")
        ){//创建流对象,如果多个,使用';'隔开
            int len = 0;
            while ((len =fr.read())!=-1){
                fileWriter.write(len);
            }
        }catch (IOException e){
            e.printStackTrace();
        }

可以使用try-with-resource语句,该语句确保了每个资源在语句结束时关闭,所谓的资源(resource)是指在程序完成后,必须要关闭的对象
实际上,编译器并不会特别地为InputStream加上自动关闭。编译器只看try(resource = ...)中的对象是否实现了java.lang.AutoCloseable接口,如果实现了,就自动加上finally语句并调用close()方法。InputStream和OutputStream都实现了这个接口,因此,都可以用在try(resource)中。

原文地址:https://www.cnblogs.com/mitoris/p/14141192.html