Java基础笔记(5)-IO流

I/O流

I/O流原理以及分类

IO流原理:

  1. I/O技术,用于处理数据传输,如读写文件,网络通讯等
  2. java.io包下提供了各种“流”的类和接口,用以获取不同种类的数据,并通过方法输入或输出数据

流的分类:

  • 按照操作数据单位不同分为:
    • 字节流(8 bit)
    • 字符流(按照字符,不同的编码可能对应不同的字节大小)
  • 按照流的流向不同分为:
    • 输入流
    • 输出流
  • 按照流的角色不同分为:
    • 节点流
    • 处理流 / 包装流
抽象基类 字节流 字符流
输入流 InputStream Reader
输出流 OutputStream Writer

字节流

一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时一样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据。

字节流中又分为了字节输入流和字符输出流。

InputStream:字节输入类

InputSteam常用的子类
FileInputStream 文件输入流
BufferedInputStream 缓冲字节输入流
ObjectInputStream 对象字节输入流
  • public void close() :关闭此输入流并释放与此流相关联的任何系统资源
  • public abstract int read(): 从输入流读取数据的下一个字节
  • public int read(byte[] b): 从输入流中读取一些字节数,并将它们存储到字节数组 b中 ,返回读取的字节数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 构建字节输入流
FileInputStream fileInput = new FileInputStream("xxx/xxx");

// 准备buf字节数组,承接字节流中的数据
byte[] buf = new byte[256];
int len = 0;

// 循环读取字节流中的字节,存入buf中
while(len = fileInput.read(buf) != -1){
// get new buf[0 - len]
}

// 关闭流
fileInput.close();

OutputStream:字节输出类

OutputStream常用的子类
FileOutputStream 文件输出流
  • public void close() :关闭此输出流并释放与此流相关联的系统资源
  • public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出
  • public void write(byte[] b):将 b.length字节从指定的字节数组写入此输出流
  • public void write(byte[] b, int off, int len) :从指定的字节数组写入len字节,从偏移量off开始输出到此输出流
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 构建字节输出流
FileOutputStream fileOutput = new FileOutputStream("xxx/xxx");

// 准备字节数组
byte[] b = "abcde".getBytes();

// 输出字节
fileOutput.write(b);

// 流关闭
fileOutput.close();

// 默认是覆盖写,追加写需要在构造输出流的时候指定第二个参数
public FileOutputStream(File file, boolean append);
// 创建文件输出流以写入由指定的 File对象表示的文件
public FileOutputStream(String name, boolean append);
// 创建文件输出流以指定的名称写入文件

字符流

当使用字节流读取文本文件时,可能会有一个小问题。字节是计算机能够读取的形式,但是对于人类来说,可读性并不是很好。对于人类来说,可读性较好的是字符。但是对于字符的编码方式有多种多样,对应占用的字节数也不同。而Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。

Reader:字符输入类

InputSteam常用的子类
FileReader 文件字符输入流
  • public void close() :关闭此流并释放与此流相关联的任何系统资源
  • public int read(): 从输入流读取一个字符
  • public int read(char[] cbuf): 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中

Writer:字符输出类

InputSteam常用的子类
FileWriter 文件字符输入流
  • void write(int c):写入单个字符
  • void write(char[] cbuf):写入字符数组
  • abstract void write(char[] cbuf, int offset, int len):写入字符数组的某一部分,offset为数组的开始索引,len为写的字符个数
  • void write(String str):写入字符串
  • void write(String str, int offset, int len) :写入字符串的某一部分,offset为字符串的开始索引,len为写的字符个数
  • void flush():刷新该流的缓冲
  • void close():关闭此流,但要先刷新它

节点流和处理流

基本介绍:

  • 节点流:节点流可以从一个特定的数据源读写数据,如FileReader、FileWriterd
  • 处理流:也叫做包装流,是连接在已存在的流(节点流或者处理流、对节点流进行包装)之上,为程序提供更加强大的读写功能。如BufferedReader、BufferedWriter
    • 处理流中存放了一个Reader或者Writer对象,在使用的时候这个对象可以传入对应的子类,进行功能的扩充(对其他流进行包装)

节点流和处理流之间的区别和联系:

  1. 节点流是底层流/低级流,直接和数据源相接
  2. 处理流(包装流)包装节点流,既可以消除不同节点流之间的实现差异,也可以提供更方便的方法来完成输入输出
  3. 处理流对节点流进行包装,使用修饰器设计模式,不会直接与数据源相连

处理流的功能体现:

  1. 性能的提高:主要以增加缓冲的方式来提高输入输出的效率
  2. 操作的便捷:处理流提供了一系列便捷的方法来一次性输入输出大批量的数据,使用更加灵活方便

转化流

转化流:将字节流转化成字符流(应对可能存在的文件乱码问题)

  • 转化流有两种:InputStramReader和OutputStreamWriter

  • 在转化流上可以指定编码方式

  • InputStramReader

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // 1.把FileInputStream 转成 InputStreamReader
    // 2.指定编码
    new InputStreamReader(new FileInputStream(path), "gbk");

    // 3.把InputStreamReader 传入 BufferedReader
    new BufferedReader(inputStramReader);

    // 4.读取
    bufferedReader.readLine();

    // 5.关闭外层流
    bufferedReader.close();
  • OutputStreamWriter

    1
    2
    3
    4
    5
    6
    7
    8
    // 1.创建流对象
    new OutputStreamWriter(new FileOutputStream(path), "gbk");

    // 2.写入
    osw.write("xxx");

    // 3.关闭
    osw.close();

标准输出流

标准输出流:PrintStream和PrintWriter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//PrintStream:字节打印流
PrintStream out = System.out;
out.print("Hello World");
out.close();

//改变输出位置
System.setOut(new PrintStream(path));
System.out.println("Hello World");

//PrintWriter:字符打印流
new PrintWriter(System.out);
// new PrintWriter(new FileWriter(path));
pw.print("Hello World");
pw.close();

文件类

常用的文件操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 使用File类
new File(String pathname);
new File(File parent, String child);
new File(String parent, String child);

// 进行文件创建
.creatNewFile();

// 获取文件相关信息
getName();
getAbsolutePath();
getParent();
length();
exists();
isFile();
isDirectory();

//目录操作和文件删除
mkdir();
mkdirs();
delete();//如果删除目录是删除一个空目录

文件操作

以字节流中文件中获取输入字节:

1
2
3
4
5
6
7
public static byte[] getBytesFromFile(String sourceFilePath) throws IOException {
FileInputStream fileInputStream = new FileInputStream(sourceFilePath);
byte[] bytes = new byte[fileInputStream.available()];
fileInputStream.read(bytes);
fileInputStream.close();
return bytes;
}

以字节数组写入文件中,append标识是否追加写入:

1
2
3
4
5
public static void setBytesToFile(byte[] bytes, String targetFilePath, boolean append) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream(targetFilePath, append);
fileOutputStream.write(bytes);
fileOutputStream.close();
}

输出文件内容:

1
2
3
4
5
6
7
8
9
10
// 输出文件内容
public static void showFileContent(String filePath) throws IOException {
FileReader fileReader = new FileReader(filePath);
BufferedReader reader = new BufferedReader(fileReader);
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
}

参考文章

  1. java中的io流_Jm呀的博客-CSDN博客_java的io流
  2. Java文件处理_神奇的海螺呀的博客-CSDN博客_java 文件处理

Java基础笔记(5)-IO流
http://example.com/2022/09/03/Java基础笔记-5-IO流/
作者
EverNorif
发布于
2022年9月3日
许可协议