欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

从零开始的java学习Day15----------基础篇(IO流)

程序员文章站 2022-05-28 14:46:34
...

IO流

我们电脑中的数据,都是一个个二进制数字(字节)组成,我们传输数据,就可以看做是一种数据的流动,以内存为基准按照流动的方向,就分为输入流(流向内存)和输出流(输出内存)。输入也叫做读取数据,输出也叫做写出数据,这就是IO流
I:input(输入)
O:output(输出)

IO的分类

按照数据的流向分为:

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

按照数据类型分为:

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

*父类

字节流:字节输入流(InputStream) 字节输出流(OutputStream)
字符流:字符输入流(Reader) 字符输出流(Writer)

字节流

字节输出流OutputStream

OutputStream是所有字节输出流的超类,将指定字节信息写出到目的地,他里面定义了字节输出流的基本共性方法。
常用方法:

void close() :关闭此输出流并释放与此流相关联的任何系统资源。
void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。
abstract void write(int b) :将指定的字节输出到输出流(自动转为字符型)
void write(byte[] b):将指定字节数组内元素依次输出到输出流
void write(byte[] b, int off, int len) :将指定数组内元素按照指定索引输出指定个数
FileOutputStream类

但是OutputStream 是一个抽象类,并不能直接创建对象,这里我们介绍他的常用子类:FileOutputStream
该类对象文件是输出流,用于将数据写出到文件
构造方法:

FileOutputStream(File file):创建输出流对象,指向File内的路径,如果没有,会自动创建
FileOutputStream(File file,boolean append):创建输出流对象,指向File内的路径,如果没有,会自动创建,里面的布尔类型如果为true,则执行输出流的时候是添加,如果是false则是覆盖
FileOutputStream(String name): 创建输出流对象,指向填入的路径,如果没有,会自动创建
FileOutputStream(String name,boolean append): 创建输出流对象,指向填入的路径,如果没有,会自动创建,里面的布尔类型如果为true,则执行输出流的时候是添加,如果是false则是覆盖

关于换行:

  • Windows系统里,每行结尾是 回车+换行 ,即\r\n;
  • Unix系统里,每行结尾只有 换行 ,即\n;
  • Mac系统里,每行结尾是 回车 ,即\r。从 Mac OS X开始与Linux统一

字节输入流InputStream

InputStream是所有字节输入流的超类,可以读取字节信息到内存中,他定义了字节输入流的基本共性方法

void close() :关闭此输入流并释放与此流相关联的任何系统资源。
abstract int read():从输入流读取数据的下一个字节,自动转为Int类型返回,如果到了末尾,就返回-1
int read(byte[] b):从输入流中读取一些字节数,并将它们存储到字节数组 b中 ,一次最多读取存储数组的长度个字节,返回赋值的元素数量,用同一个数组会覆盖,到了末尾,就停止赋值,返回-1
read(byte[] b, int off, int len):和上面的区别就是可以从指定索引开始,读取存储指定个数的字节

注意:字节流读取的单位,是一个字节

FileInputStream类

同样的InputStream,是一个抽象类,我们先学习他的常用子类FileInputStream 来使用字节输入流:
FileInputStream类是文件输入流,从文件中读取字节。
构造方法:

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

注意:这里的文件路径必的文件须是存在的,如果不存在会报错。

字符流

当我们使用字节流读取文本数据的时候,可能会遇到一点问题,那就是遇到中文字符时,没办法显示,那是因为一个中文字符会占多个字节储存。所以Java中也提供了一些字符流,以字符为单位存储数据,专门用于处理文本文件。
注意

  • 字符流,只能操作文本文件,不能操作图片,视频等非文本文件
  • 如果是一个中文以gbk编码形式存储,就是占2个字节,以utf-8编码形式存储就会占3个字节
  • 而windws系统中默认是gbk编码, idea开发工具则是utf-8编码,意思就是如果用不同编码打开就会乱码。

字符输入流Reader

Reader是字符读取流的所有超类,该类可以读取字节信息到内存中。它定义了字符输入流的基本共性方法

void close() :关闭此流并释放与此流相关联的任何系统资源。
int read(): 从输入流读取一个字符。(基本类型自动转换后返回int格式)如果到末尾则返回-1
int read(char[] cbuf): 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中,返回存入的元素个数(默认存满),如果到末尾了就返回-1
int read(char[] cbuf,int off,int len): 比上面的增加了,存入指定索引,指定个数个元素

FileReader类

同样的,因为Reader是抽象类,我们都是使用它的子类,FileReader就是一个字符输入流的常用类
构造方法:

FileReader(File file): 创建一个新的 FileReader ,使用File对象作为路径指定
FileReader(String fileName): 创建一个新的 FileReader ,使用字符串形式作为路径指定

字符输出流Writer

Writer是字符输出流的所有超类,该类可以将指定的信息写出到目的地,他定义了字节输出流的基本共性功能方法

abstract void close() :关闭此输出流并释放与此流相关联的任何系统资源。
abstract void flush() :刷新此输出流并强制任何缓冲的输出字符被写出。
void write(int c) :写出一个字符,(写入目的地)
void write(char[] cbuf):将整个字符数组写入目的地
abstract void write(char[] b, int off, int len) :比上面的多了指定索引开始和指定个数
void write(String str) :写出一个字符串到目的地

FileWriter类

因为Writer是一个抽象类,我们要实用,也都是用他的子类,FileWriter就是一个他的常用子类
构造方法:

FileWriter(File file): 创建一个新的 FileWriter,用给定的File里的路径指定
FileWriter(String fileName): 创建一个新的 FileWriter,用给定的字符串的路径指定

关闭和刷新

因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要Flush方法。

  • flush :刷新缓冲区,流对象可以继续使用。
  • close :关闭流,释放系统资源。关闭前会刷新缓冲区。(不能再继续读取或写出操作了)

如何拷贝一个文件

  • 1.创建一个字节输入流对象,封装数据源文件(路径)
  • 2.创建一个字节输出流对象,封装目的地文件
  • 3.定义一个int类型的变量,用来存储读取到的字节数据
  • 4.循环读取,只要满足条件,就一直读取
  • 5.写出数据
  • 6.关闭流,释放资源

缓冲流(高效流)

作为IO流的入门,上面都是一些基本的流,现在我们学习一些更加强大的流。缓冲流就是其中之一。

  • 缓冲流也叫高效流,它内置了一个长度为8192的byte数组作为缓冲区,我们从读写数据,可以一次性读8192字节到缓冲流的缓冲区,直接在内存中进行我们的操作(比如一次读取一个字节),减少了与硬盘的交互(内存内执行效率比硬盘快),提交了速度。
  • 缓冲流也就字节缓冲流和字符缓冲流,都有各自的输入和输出流

字节缓冲流

输入流:BufferedInputStream
输出流:BufferedOutputStream
构造方法:

// 创建字节缓冲输入流,需要传入一个InputStream的实现类,可以使用昨天学的FileInputStream
BufferedInputStream bis = new BufferedInputStream(InputStream a);
// 创建字节缓冲输出流,需要传入一个OutputStream的实现类,可以使用昨天学的FileOutputStream
BufferedOutputStream bos = new BufferedOutputStream(OutputStream a);

字节缓冲流也继承了我们昨天学的两个字节输入输出流的超类IntputStream、OutputStream,所以他的方法和我们昨天学的几个方法一样,也是用read输出,write输出,close关闭。

字符缓冲流

输入流:BufferedReader
输出流:BufferedWriter
构造方法:

// 创建字符缓冲输入流
BufferedReader br = new BufferedReader(new FileReader("br.txt"));
// 创建字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));

和字节缓冲流一样,它们各自也都需要传入一个字符(输入/输出)流。方法也都继承了Reader和Writer。
除了继承的方法外,字符缓冲流还有它自己的特有方法:

BufferedReader(输入流):String readLine(): 读一行文字。,返回这一行字符的String,到末尾就返回null
BufferedWriter(输出流):void newLine(): 写一行行分隔符,由系统属性定义符号。相当于写一个"/r/n"

字符编码

  • 字符编码,简单来说,就是一套自然语言的字符与二进制数之间对应的规则。
  • 计算机中存储的数据都是二进制数表示的,但是我们在屏幕上看到的文字都是一些我们认识的东西(英文,数字,汉字等等),这是因为计算机已经自动帮我们进行转换了。
  • 我们要将字符存储到计算机中,称为编码,从计算机中读取二进制数变为字符就叫做解码
  • 不同的字符集所使用的编码和解码的规则是不一样的,如果我们用A字符集的规则套到B字符集上用,就会产生乱码现象

常用字符集

  • Ascll:美国信息交换标准码,128个(0-127),包含英文字母,数字,常用符号等,我们之前用的int和char自动转换就是用的它
  • GBK:常用的中文码表,winds默认使用的字符集,兼容Ascll
  • UTF-8:业界标准,统一码,我们以后主要使用的,包含大部分国家的字符,兼容Ascll

转换流

可以将字节流转换为字符流,并且指定使用的字符集

InputStreamReader

InputStreamReader类,继承Reader,他可以将一个字节流输入对象转换为字符流的输入对象,并且可以指定所使用的字符集的解法方式解码
构造方法:

InputStreamReader(InputStream in): 创建一个使用默认字符集的字符流,ider默认是UTF-8
InputStreamReader(InputStream in, String charsetName): 创建一个指定字符集的字符流,例如GBK,就填入"gbk"就可以

他继承Reader,有Reader内的方法,例如read和close他都有

OutputStreamWriter

OutputStreamWriter类,继承Writer,他可以将一个字节流输出对象转换为字符流输出对象,并且指定所使用的字符集。
注意:我们直接用字节流输出中文字符,会默认使用UTF-8编码,一个字符占3个字节
构造方法:

OutputStreamWriter(OutputStream in): 创建一个使用默认字符集的字符流。Ider默认UTF-8
OutputStreamWriter(OutputStream in, String charsetName): 创建一个指定字符集的字符流。

他继承Writer,有Wreter内的方法,例如write和flush、close他都有

打印流

平时我们在控制台打印的数据,都是使用的print和println两个方法完成的,其实这两个方法都来自PrintStream类,只是我们使用System.out会自动返回一个PrintStream类,我们使用的链式编程完成的该方法
注:使用System.setout()方法,可以传入一个PrintStream对象,改变系统默认(默认控制台)的打印位置。

PrintStream

PrintStream类,打印输出流,可以打印输出东西到指定的地方
构造方法:

PrintStream(String n)          //里面的String类型就是传入一个路径,如果没有,会自动生成

常用方法:print和pringtln

IO的异常处理

IO类异常有规范的处理形式

  • JDK7以前:
    先创建(在try外)所要使用流的对象,赋值null
    再使用try…catch,在try后的括号里,使用之前创建的对象,调用构造方法赋值。再执行我们要执行的代码
    最后释放资源的时候,要把colse语句写到finally里面,如果有多条colse语句,就嵌套(因为colse也要try)放到finally里

  • JDK7及之后可以使用:
    try后面可以加个小括号,把创建流对象的语句写到里面(多条创建以;隔开)。后面的语句体放到try的{}里,不用再写colse语句,系统执行完try里的会自动释放小括号里面定义的流对象的资源。

  • JDK9及之后可以使用:
    它在JDK7上面优化了,可以把创建流对象的语句写在try之前,然后在try后的小括号里直接写定义好的对象(多个对象以;隔开)。

相关标签: 从零开始学java