目录
流的分类
- 按操作数据单位不同分为:字节流(8 bit)二进制文件,字符流(按字符)文本文件
- 按数据流的流向不同分为:输入流,输出流
- 按流的角色的不同分为:节点流,处理流 / 包装流
抽象基类 | 字节流 | 字符流 |
---|---|---|
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
- 流共涉及40多个类,实际上非常规则,都是从如上 4 个抽象基类派生的。
- 由这四个类派生出来的子类名称都是以其父类名作为子类名后缀
IO流体系图
InputStream / OutputStream:字节输入 / 输出流
InputStream抽象类是所有类字节输入流的超类
InputStream常用的子类
FilelnputStream
:文件输入流BufferedInputStream
:缓冲字节输入流ObjectInputStream
:对象字节输入流
FileInputStream字节输入流案例
package day06.inputStream_;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.IOException;
/**
* @Author: Gin
* @Description: FileInputStream 字节输入流案例
* @Modified By: Gin
* @Date: Created in 15:27 2021/9/2
*/
public class Demo1 {
public static void main(String[] args) {
}
// 1. 演示利用 FileInputStream 读取文件,read() 方法单个字节读取,效率低
@Test
public void read1(){
String path = "E:\\news1.txt";
// 创建 FileInputStream 对象,用于读取文件
FileInputStream fileInputStream = null;
int readData = 0;
try {
// 从该输入流读取一个字节的数据,如果没有输入可用,此方法将阻止
fileInputStream = new FileInputStream(path);
// fileInputStream返回值为 int 类型,将读取到的单个内容赋值给 readData,输出时将 readData 强转为 char 类型。
// 如果返回 -1,表示读取完成
while((readData = fileInputStream.read()) != -1){
System.out.print((char)readData);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 关闭文件流,释放资源
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 2. read(byte[] b) 方法读取,一次性读取多个字节
@Test
public void read2(){
String path = "E:\\news1.txt";
// 创建 FileInputStream 对象,用于读取文件
FileInputStream fileInputStream = null;
byte[] buf = new byte[8]; // 定义字节数组,表示一次读取 8 个字节
int readLen = 0;
try {
// 从该输入流读取一个字节的数据,如果没有输入可用,此方法将阻止
fileInputStream = new FileInputStream(path);
// 如果返回 -1,表示读取完成
while((readLen = fileInputStream.read(buf)) != -1){
System.out.print(new String(buf, 0, readLen));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 关闭文件流,释放资源
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
FileOutputStream字节输出流案例
package day06.FileOutputStream;
import org.junit.Test;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @Author: Gin
* @Description: FileOutputStream 字节输出流案例
* @Modified By: Gin
* @Date: Created in 16:10 2021/9/2
*/
public class Demo {
public static void main(String[] args) {
}
@Test
public void write(){
String path = "E:\\news2.txt";
FileOutputStream fileOutputStream = null;
try {
// *** new FileOutputStream(filePath) ====> 覆盖写入内容
// fileOutputStream = new FileOutputStream(path);
// *** new FileOutputStream(filePath, true) ====> 追加写入内容
fileOutputStream = new FileOutputStream(path, true);
// 1. 写入一个字节
// fileOutputStream.write('G'); // 单引号
// 写入一串字符
String str = "Vermouth"; // str.getBytes():将字符串转换为字节数组
// 2. 直接将所有字符写入文件
// fileOutputStream.write(str.getBytes());
// 3. 写入规定长度的字符
// 下标从 0 开始,从下标为 3(off) 的字符开始,写入 5(len) 个字符
fileOutputStream.write(str.getBytes(), 3, 5); // 写入内容为 mouth
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字节流练习:拷贝文件
package day06.FileOutputStream;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @Author: Gin
* @Description: 文件拷贝
* @Modified By: Gin
* @Date: Created in 16:35 2021/9/2
*/
public class Demo2 {
public static void main(String[] args) {
}
@Test
public void copy(){
String srcFilePath = "E:\\fenmao.png";
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
String destFilePath = "D:\\fenmao.png"; // 此处要给定拷贝后的文件名,如果只有 D:\\ 会抛出异常。
try {
fileInputStream = new FileInputStream(srcFilePath);
fileOutputStream = new FileOutputStream(destFilePath);
// 定义字节数组,提高读取效率
byte[] buf = new byte[1024];
int readLen;
while ((readLen = fileInputStream.read(buf)) != -1){
// 读取到后,就写入到文件,通过 fileOutputStream
// 即一边读一边写
// 写入时一定要用 fileOutputStream.write(byte[] b, int off, int len)
fileOutputStream.write(buf, 0, readLen);
}
System.out.println("拷贝ok~");
} catch (IOException e) {
e.printStackTrace();
} finally {
try{
// 关闭输入输出流
if(fileInputStream != null){
fileInputStream.close();
}
if(fileOutputStream != null){
fileOutputStream.close();
}
}catch(IOException e){
e.printStackTrace();
}
}
}
}
Reader / Writer:字符输入 / 输出流
FileReader 相关方法
new FileReader(File / String)
read
:每次读取单个字符,返回该字符,如果到文件末尾返回 -1read(char[])
:批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾返回 -1
相关APl:
new String(char[])
:将char[]
转换成String
new String(char[],off,len)
:将char[]
的指定部分转换成String
FileReader 练习
package day06.FileOutputStream;
import org.junit.Test;
import java.io.FileReader;
import java.io.IOException;
/**
* @Author: Gin
* @Description: FileReader 案例
* @Modified By: Gin
* @Date: Created in 17:13 2021/9/2
*/
public class Demo3 {
public static void main(String[] args) {
String filePath = "E:\\news3.txt";
FileReader reader = null;
int readData;
try {
// 创建 FileReader 对象
reader = new FileReader(filePath);
// 循环读取,使用 read() 方法,读取单个字符
while ((readData = reader.read()) != -1){
System.out.print((char) readData);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try{
if(reader != null){
reader.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
// 使用字符数组读取文件
@Test
public void reader(){
String filePath = "E:\\news3.txt";
FileReader reader = null;
char[] buf = new char[8];
int readLen;
try {
// 创建 FileReader 对象
reader = new FileReader(filePath);
// 循环读取,使用 read(char[] c) 方法,读取字符数组,返回的是读取到的字符数
// 如果返回 -1,读取结束
while ((readLen = reader.read(buf)) != -1){
System.out.print(new String(buf, 0, readLen));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try{
if(reader != null){
reader.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
FileWriter常用方法
new FileWriter(File/String)
:覆盖模式,相当于流的指针在首端new FileWriter(File/String,true)
:追加模式,相当于流的指针在尾端write(int)
:写入单个字符write(char[])
:写入指定数组write(char[],off,len)
:写入指定数组的指定部分write (string)
:写入整个字符串write(string,off,len)
:写入字符串的指定部分
相关API:
- String类:
toCharArray
:将String
转换成char[]
- 注意:
FileWriter
使用后,必须要关闭(close)
或刷新(flush)
,否则写入不到指定的文件!
FileWriter 练习
package day06.FileWriter_;
import java.io.FileWriter;
import java.io.IOException;
/**
* @Author: Gin
* @Description:
* @Modified By: Gin
* @Date: Created in 18:42 2021/9/2
*/
public class Demo {
public static void main(String[] args) {
String filePath = "E:\\note.txt";
FileWriter writer = null;
char[] chars = {'a', 'b', 'c', 'd'};
try {
// 1. new FileWriter(File/String):覆盖模式,相当于流的指针在首端
// 2. new FileWriter(File/String,true):追加模式,相当于流的指针在尾端
writer = new FileWriter(filePath);
// 3. write(int):写入单个字符
writer.write("H");
// 4. write(char[]):写入指定数组
writer.write(chars);
// 5. write(char[],off,len):写入指定数组的指定部分
writer.write("太原理工大学".toCharArray(), 2, 4);
// 6. write (string):写入整个字符串
writer.write(" Gin / Vodka");
// 7. write(string,off,len):写入字符串的指定部分
writer.write("上海广州", 2, 2);
// 在数据量大的时候用循环
} catch (IOException e) {
e.printStackTrace();
} finally {
// 对于 FileWriter,一定要 `关闭流close()` 或者 `刷新flush()`,才能真正把数据写入到文件中
// 查看源码
/*
private void writeBytes() throws IOException {
bb.flip();
int lim = bb.limit();
int pos = bb.position();
assert (pos <= lim);
int rem = (pos <= lim ? lim - pos : 0);
if (rem > 0) {
if (ch != null) {
if (ch.write(bb) != rem)
assert false : rem;
} else {
out.write(bb.array(), bb.arrayOffset() + pos, rem);
}
}
bb.clear();
}
*/
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("写入完毕!");
}
}