JavaIO流-IO 流
一、IO 流
1.1、IO 流概述和分类
1.1.1、IO 流概述
- IO:输入/输出(Input/Output)
- 流:是一种抽象概念,是对数据传输的总称。也就是说数据在设备间的传输称为流,流的本质是数据传输
- IO 流就是用来处理设备间数据传输问题的
- 常见的应用:文件复制、文件上传、文件下载
1.1.2、IO 流分类
- 按照数据的流向:
- 输入流:读数据
- 输出流:写数据
- 按照数据类型来分:
- 字节流:
- 字节输入流
- 字节输出流
- 字符流:
- 字符输入流
- 字符输出流
- 字节流:
1.2、字节流
1.2.1、字节流概述
- 字节流抽象基类
InputStream:这个抽象类是表示字节输入流的所有类的超类OutputStream:这个抽象类是表示字节输出流的所有类的超类- 子类名特点:子类名称都是以其父类名作为子类名的后缀
1.2.2、字节流写数据
- 使用字节输出流写数据的步骤:
- 创建字节输出流对象(调用系统功能创建了文件,创建字节输出流对象,让字节输出流对象指向文件)
- 调用字节输出流对象的写数据方法
- 释放资源(关闭此文件输出流并释放与此流相关联的任何系统资源)
1.2.2.1、FileOutputStream() 构造方法
- FileOutputStream:文件输出流用于将数据写入 File
- FileOutputStream(String name):创建文件输出流以指定的名称写入文件
// 创建字节输出流对象
FileOutputStream fos = new FileOutputStream(".\\fos.txt");
/*
做了三件事情:
A:调用系统功能创建了文件
B:创建了字节输出流对象
C:让字节输出流对象指向创建好的文件
*/
// void write(int b)
fos.write(97);
fos.close();
1.2.2.2、字节流写数据的 3 种方式
| 方法名 | 说明 |
|---|---|
| void write(int b) | 将指定的字节写入此文件输出流 |
| void write(byte[] b) | 将 b.length 字节从指定的字节数组写入此文件输出流,一次写一个字节数组数据 |
| void write(byte[] b,int off,int len) | 将 len 字节从指定的字节数组开始,从偏移量 off 开始写入此文件输出流一次写一个字节数组的部分数据 |
1.2.2.2.1、write(int b)
- 将指定的字节写入此文件输出流。
// 创建字节输出流对象
FileOutputStream fos = new FileOutputStream(".\\fos.txt");
// 写入元素
fos.write(97);
fos.write(98);
fos.write(99);
fos.write(100);
fos.write(101);
// 释放资源
fos.close();
1.2.2.2.2、write(byte[] b)
- 将 b.length 字节从指定的字节数组写入此文件输出流,一次写一个字节数组数据。
// 创建字节输出流对象
FileOutputStream fos = new FileOutputStream(".\\fos.txt");
// 写入元素
byte[] bys = {99,97,92,100,123};
// byte[] getBytes():返回字符串对应的字节数组
byte[] bys = "abcde".getBytes();
fos.write(bys);
// 释放资源
fos.close();
1.2.2.2.3、write((byte[] b,int off,int len)
- 将 len 字节从指定的字节数组开始,从偏移量 off 开始写入此文件输出流一次写一个字节数组的部分数据。
// 创建字节输出流对象
FileOutputStream fos = new FileOutputStream(".\\fos.txt");
// 写入元素
byte[] bys = "javase".getBytes();
fos.write(bys,0,bys.length);
// 释放资源
fos.close();
1.2.2.3、字节流写入数据的两个小问题
1.2.2.3.1、字节流写数据如何实现换行
- 在写入数据后,追加换行符
- Windows:
\r\n - Linst:
\n - Mac:
\r
- Windows:
// 创建字节输出流对象
FileOutputStream fos = new FileOutputStream(".\\fos.txt");
// 写入元素
for (int i = 0; i < 10; i++) {
fos.write("java".getBytes());
fos.write("\r\n".getBytes());
}
// 释放资源
fos.close();
1.2.2.3.2、字节流写数据如何实现追加写入
public FileOutputStream(String name,boolean append):创建文件输出流以指定的名称写入文件。 如果第二个参数为true ,则字节将写入文件的末尾而不是开头
// 创建字节输出流对象
FileOutputStream fos = new FileOutputStream(".\\fos.txt",true);
// 写入元素
for (int i = 0; i < 10; i++) {
fos.write("java".getBytes());
fos.write("\r\n".getBytes());
}
// 释放资源
fos.close();
1.2.2.4、字节流写数据加异常处理
- finally:在异常处理时提供 finally 块来执行所有清除操作。比如说 IO 流中的资源释放
- 特点:被 finally 控制的语句一定会执行,除非 JVM 退出
FileOutputStream fos = null;
try {
// 创建字节输出流对象
fos = new FileOutputStream(".\\fos.txt", true);
// 写入元素
fos.write("hello".getBytes());
}catch (IOException e){
e.printStackTrace();
}
finally {
if ( fos != null) {
// 释放资源
fos.close();
}
}
1.2.3、字节流读数据
1.2.3.1、FileInputStream() 构造方法
public FileInputStream(String name):通过打开与实际文件的连接创建一个FileInputStream ,该文件由文件系统中的路径名称为name命名。
// 创建字节输入流对象
FileInputStream fis = new FileInputStream(".\\fos.txt");
// 调用字节输入流对象的读数据方法
// int by = fis.read();
// while (by != -1){
// System.out.print((char) by);
// by = fis.read();
// }
// 优化上面的代码
/*
fis.read():读数据
by = fis.read():把读取到的数据赋值给 by
by != -1:判断读取到的数据是否是 -1
*/
int by;
while ((by = fis.read()) != -1){
System.out.print((char)by);
}
// 释放资源
fis.close();
1.2.3.2、字节流读数据的 3 种方法
1.2.3.3、read()
- 从该输入流读取一个字节的数据。
// 创建字节流输入对象
FileInputStream fis = new FileInputStream("D:\\fos.txt");
int len = fis.read();
// 把 整数 强制转换为 字符
System.out.println((char)len);
// 释放资源
fis.close();
1.2.3.4、read(byte[] b)
- 从该输入流读取最多b.length个字节的数据为字节数组。
// 创建字节流输入对象
FileInputStream fis = new FileInputStream("D:\\fos.txt");
// public int read()
byte[] by = new byte[5];
int len = fis.read(by);
// 把 数组 转换为 字符串
System.out.println(new String(by));
// 释放资源
fis.close();
1.2.3.4、read(byte[] b,int off,int len)
- 从该输入流读取高达len字节的数据到字节数组。
// 创建字节流输入对象
FileInputStream fis = new FileInputStream("D:\\fos.txt");
byte[] by = new byte[10];
int len = fis.read(by);
System.out.print(new String(by,0,len));
// 释放资源
fis.close();
1.2.4、字节缓冲流
1.2.4.1、字节缓冲流构造方法
- 字节缓冲输出流:
BufferedOutputStream(OutputStream out) - 字节缓冲输入流:
BufferedInputStream(InputStream in)
1.2.4.1.1、字节缓冲输出流
BufferedOutputStream:该类实现缓冲输出流。 通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用。
// 创建字节缓冲输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(".\\bos.txt"));
// 写数据
bos.write("hello\r\n".getBytes());
// 释放资源
bos.close();
1.2.4.1.2、字节缓冲输入流
BufferedInputStream: 创建BufferedInputStream将创建一个内部缓冲区数组。 当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节。
// 创建字节输入流对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(".\\bos.txt"));
// 一次读一个字节数据
// int by;
// while ((by = bis.read()) != -1) {
// System.out.print((char) by);
// }
// 一次读取一个字节数组数据
byte[] bys = new byte[1024];
int len;
while ((len = bis.read(bys)) != -1) {
System.out.println(new String(bys, 0, len));
}
// 释放资源
bis.close();
1.2.5、字节流读写数据速度
- 基本字节流一次读写一个数组 比 基本字节流一次读写一个字节字节 块。
- 字节缓冲流一次读写一个数组 比 字节缓冲流一次读写一个字节字节 块。
- 字节缓冲流 比 基本字节流 块。
1.3、字符流
1.3.1、为什么会出现字符流
- 由于字节流操作中文不是特别的方便,所以 Java 就提供字符流
- 字符流 = 字节流 + 编码表
- 用字节流复制文本文件时,文本文件也会有中文,但是没有问题,原因是最终底层操作会自动进行字节拼接成中文,如何识别中文呢?
- 汉字在存储的时候,无论选择哪种编码存储,第一个字节都是负数
1.3.2、字符串中的编码解码问题
1.3.2.1、编码
- 编码:
byte[] getBytes():使用平台的默认字符集将该 String 编码为一系列字节,将结果存储到新的字节数组中。byte[] getBytes(String charsetName):使用指定的字符集将该 String 编码为一系列字节,将结果存储到新的字节数组中。
// byte[] getBytes()
String s = "中国";
byte[] bys = s.getBytes();
System.out.println(Arrays.toString(bys));
// byte[] getBytes(String charsetName)
String s = "中国";
byte[] bys = s.getBytes("GBK");
System.out.println(Arrays.toString(bys));
1.3.2.2、解码
- 解码:
String(byte[] bytes):通过使用平台的默认字符集解码指定的字节数组来构造新的 String。String(byte[] bytes,String charsetName):通过指定的字符集解码指定的字节数组来构造新的 String。
// String(byte[] bytes)
byte[] b = {-28, -72, -83, -27, -101, -67};
String ss = new String(b);
System.out.println(ss);
// String(byte[] bytes,String charsetName)
byte[] b = {-28, -72, -83, -27, -101, -67};
String ss = new String(b,"UTF-8");
System.out.println(ss);
1.3.3、字符流中的编码解码问题
-
字符流抽象基类
- Writer:字符输出流的抽象类
- Reader:字符输入流的抽象类
-
字符流中和编码解码相关的两个类:
- OutputStreamWriter
- InputStreamReader
1.3.3.1、OutputStreamWriter 构造方法
它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。
1.3.3.1.1、OutputStreamWriter(OutputStream out)
- 创建一个使用默认字符编码的OutputStreamWriter。
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(".\\a.txt"));
osw.write("中国");
osw.close();
1.3.3.1.2、OutputStreamWriter(OutputStream out, String charsetName)
- 创建一个使用命名字符集的OutputStreamWriter。
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(".\\a.txt"),"GBK");
osw.write("中国");
osw.close();
1.3.3.2、InputStreamReader 构造方法
它读取字节,并使用指定的charset将其解码为字符。 它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。
1.3.3.2.1、InputStreamReader(InputStream in)
- 创建一个使用默认字符集的InputStreamReader。
// 创建字符输入流对象
InputStreamReader isr = new InputStreamReader(new FileInputStream(".\\a.txt"));
// 一次读取一个字符数据
int ch;
while ((ch = isr.read())!= -1){
System.out.print((char)ch);
}
// 释放资源
isr.close();
1.3.3.2.2、InputStreamReader(InputStream in, String charsetName)
- 创建一个使用命名字符集的InputStreamReader。
// 创建字符输入流对象
InputStreamReader isr = new InputStreamReader(new FileInputStream(".\\a.txt"),"GBK");
// 一次读取一个字符数据
int ch;
while ((ch = isr.read())!= -1){
System.out.print((char)ch);
}
// 释放资源
isr.close();
1.3.4、字符流写数据的 5 种方式
| 方法名 | 说明 |
|---|---|
| void write(int c) | 写一个字符 |
| void write(char[] cbuf) | 写入一个字符数组 |
| void write(char[] cbuf,int off,int len) | 写入字符数组的一部分 |
| void write(String str) | 写一个字符串 |
| void write(String str,int off,int len) | 写一个字符串的一部分 |
1.3.4.1、write(int c)
- 写一个字符
// 创建字符输出流对象
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(".\\a.txt"));
// 写一个字符
osw.write(97);
// 刷新流
osw.flush();
// 关闭资源
osw.close();
1.3.4.2、write(char[] cbuf)
- 写入一个字符数组
// 创建字符输出流对象
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(".\\a.txt"));
// 写入一个字符数组
char[] chs = {'a','b','c','d'};
osw.write(chs);
// 关闭资源
osw.close();
1.3.4.3、write(char[] cbuf,int off,int len)
- 写入字符数组的一部分
// 创建字符输出流对象
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(".\\a.txt"));
// 写入字符数组的一部分
char[] chs = {'a','b','c','d','e'};
osw.write(chs,0,chs.length);
// 关闭资源
osw.close();
1.3.4.4、write(String str)
- 写一个字符串
// 创建字符输出流对象
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(".\\a.txt"));
// 写入一个字符串
osw.write("abcdef");
// 关闭资源
osw.close();
1.3.4.5、write(String str,int off,int len)
- 写一个字符串的一部分
// 创建字符输出流对象
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(".\\a.txt"));
// 写一个字符串的一部分
osw.write("abcdef",0,"abcdef".length());
// 关闭资源
osw.close();
1.3.5、字符流读数据的 2 种方式
|方法名|说明|
|int read()|一次读一个字符数据|
|int read(char[] cbuf)|一次读一个字符数组数据|
1.3.5.1、read()
- 一次读一个字符数据。
// 创建字符输入流对象
InputStreamReader isr = new InputStreamReader(new FileInputStream(".\\a.txt"));
// 一次读一个字符数据
int ch;
while ((ch=isr.read()) != -1){
System.out.print((char)ch);
}
// 释放资源
isr.close();
1.3.5.2、read(char[] cbuf)
- 一次读一个字符数组数据。
// 创建字符输入流对象
InputStreamReader isr = new InputStreamReader(new FileInputStream(".\\a.txt"));
// 一次读一个字符数组数据
char[] bys = new char[1024];
int ch;
while ((ch=isr.read(bys))!=-1){
System.out.print(new String(bys,0,ch));
}
// 释放资源
isr.close();
1.3.6、字符缓冲流
1.3.6.1、字符缓冲流构造方法
1.3.6.1.1、字符缓冲输出流
- BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区大小,或者可以接受默认大小。 默认值足够大,可用于大多数用途。
// 创建字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter(".\\aa.txt"));
// 写入数据
bw.write("hello\n");
bw.write("world");
// 释放资源
bw.close();
1.3.6.1.2、字符缓冲输入流
- BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取,可以指定缓冲区大小,或者可以使用默认大小。 默认值足够大,可用于大多数用途。
// 创建字符缓冲输入流
BufferedReader br = new BufferedReader(new FileReader(".\\aa.txt"));
// 一次读写一个字节数据
// int ch;
// while ((ch=br.read())!=-1){
// System.out.print((char) ch);
// }
// 一次读写一个字节数组
char[] chrs = new char[1024];
int len;
while ((len=br.read(chrs))!=-1){
System.out.println(new String(chrs,0,len));
}
// 释放资源
br.close();
1.3.7、字符缓冲流特有功能
1.3.7.1、BufferedWriter 特有方法
- void newLine():写一行行分隔符,行分隔符字符串由系统属性定义。
// 创建字符输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter(".\\a.txt"));
// 写数据
for (int i = 0; i < 10; i++) {
bw.write("hello " + i);
// 写入系统默认的换行符
bw.newLine();
// 把缓存种的数据刷到文件中
bw.flush();
}
// 释放资源
bw.close();
1.3.7.2、BufferedReader 特有方法
- public String readLine():读一行文字。结果包含行的内容的字符串,不包括任何行终止字符,如果流的结果已经到达,则为 null。
// 创建字符输入流对象
BufferedReader br = new BufferedReader(new FileReader(".\\a.txt"));
String line;
// 读一行数据数据
while ((line=br.readLine())!=null){
System.out.println(line);
}
// 释放资源
br.close();
1.4、IO 流小结
1.4.1、字节流小结
小结:字节流可以复制任意文件数据,有 4 种方式一般采用字节缓冲流一次读写一个字节数组的方式。
1.4.2、字符流小结
小结:字符流只能复制文本数据,有 5 种方式,一般采用字符缓冲流的特有功能。

浙公网安备 33010602011771号