一、IO流
1.1 IO流的概述
IO(Input/Output)流 是 Java 中用于处理输入输出操作的核心机制。它将数据抽象为"流"的形式,通过流的方式实现数据在内存与外部设备(如文件、网络、键盘等)之间的传输。
- 输入流(Input Stream):从数据源读取数据到程序中。
- 输出流(Output Stream):将数据从程序写入到目标设备中。
Java 的 IO 流设计基于 面向对象 思想,提供了丰富的类来支持各种类型的输入输出操作。
✅ 核心思想:
所有 IO 操作都围绕"流"展开,数据以字节或字符的形式流动。



读写操作是以程序为参考物进行的,


1.2 IO流的分类

word、excel都不是文本文件,用记事本打开是乱码的。


1.3 IO流的体系


1.3.1 FileOutputStream字节输出流
FileOutputStream 是用于向文件中写入字节数据的输出流,继承自 OutputStream。


首先创建对象的时候会根据我们书写的路径让程序跟文件之间产生一个通道;
然后再通过wirte()方法写出数据,那么这个数据就在这个通道之中传输;
最后调用close()方法进行释放通道资源。
操作细节:

① FileOutputStream写数据的三种方式

java
package com.lkbhua.IO;
import java.io.FileOutputStream;
import java.io.IOException;
public class demo2 {
public static void main(String[] args) throws IOException {
/* FileOutputStream书写数据的三种方式
void write(int b) 一次写一个字节数据
void write(byte[] b) 一次写一个字节数组数据
void write(byte[] b, int off, int len) 一次写一个字节数组的部分数据
参数一:字节数组 参数二:开始位置 参数三:写入的长度
*/
// 1、创建FileOutputStream对象
FileOutputStream fos = new FileOutputStream("c:\\Users\\27116\\Desktop\\test\\a.txt");
// 2、调用write方法,写入数据
fos.write(97); // a
fos.write(98); // b
// 3、关闭资源
fos.close();
System.out.println("-------------");
// 创建对象的文件已经存在,数据会覆盖
// 1、创建数组
byte[] bytes = {97, 98, 99, 100};
// 2、调用write方法,写入数据
fos.write(bytes);
// 3、关闭资源
fos.close();
System.out.println("-------------");
// 1、创建数组
byte[] bytes2 = {97, 98, 99, 100};
fos.write(bytes2, 1, 2);
fos.close();
System.out.println("-------------");
}
}
② FileOutputStream书写数据的俩个小问题
如何利用FileOutputStream在文件内进行"换行"书写操作;
如何利用FileOutputStream在文件内进行"续写"书写操作,不清空不覆盖之前的内容。

java
package com.lkbhua.IO.FileOutputStreamDemo;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
public class demo3 {
public static void main(String[] args) throws IOException {
/* FileOutputStream的"换行"、"续写"操作:
换行:
再次写出一个换行符即可
windows: \r\n
linux: \n
mac: \r
细节:
在windows操作系统当中,java对回车\r换行\n进行了优化
虽然完整的是\r\n,但是我们只需要写一个即可
java会自动将\r\n转换成\n
建议:
不要省略,还是写全最好
续写:
如果想要续写,打开续写开关即可
开关位置: 创建对象关闭续写,此时创建对象就会清空文件
手动传递一个true,此时创建对象就不会清空文件
*/
// 1、创建FileOutputStream对象
FileOutputStream fos = new FileOutputStream("lkb04-File&IOCode\\a.txt", true);
// 2、写出数据
String str = "ZengQ is perfect";
byte[] arr = str.getBytes();
fos.write(arr);
// 换行
String line = "\r\n";
byte[] lineArr = line.getBytes();
fos.write(lineArr);
String str1 = "so cool 66";
byte[] arr1 = str1.getBytes();
fos.write(arr1);
fos.close();
}
}

1.3.2 FileInputStream字节输入流




① FileInputStream读取数据的细节

② FileInputStream循环读取

1.4 文件拷贝练习题
https://blog.csdn.net/2401_84643729/article/details/155569428?spm=1001.2014.3001.5501

要拷贝的文件我们称之为"数据源",拷贝的位置称之为"目的地",它们都存在于硬盘上。在中间执行的地方是我们的程序,程序运行在内存当中。当我们在代码中创建了输入与输出流时,就表示我们将三者之间创建了连接通道。
在代码中,b就是一个临时变量,用以存储当前读取到的数据,再调用read()方法去读取数据,利用write()方法写出到目的地文件中。一次只能读到一个字节的数据。36.8MB的数据需要循环3800多万次,速度太慢了。
如何提示拷贝的效率? 从源头开始,能不能多读取到几个字节的数据或者更多呢? 我们创建数组一般创建1024字节(1MB)的整数倍

java
package com.lkbhua.IO.FileInputStreamDemo;
import java.io.FileInputStream;
import java.io.IOException;
public class test2 {
public static void main(String[] args) throws IOException {
/*
public int read(byte[] buffer) 一次读取一个字节组数据
*/
// 1、创建FileInputStream对象
FileInputStream fis = new FileInputStream("c:\\Users\\27116\\Desktop\\test\\a.txt");
// 2、创建字节数组
byte[] bytes = new byte[2];
// 一次读取多少个字节数据,具体都多少,跟数组的长度有关
// 返回值: 本次读取到了多少个字节数据
int len = fis.read(bytes);
System.out.println(len);
String str = new String(bytes);
System.out.println(str);
// 3、关闭资源
fis.close();
}
}
这里变量len是记录了读取了多少个数据,创建的bytes数组记录的才是真正的数据。第一次尽可能的读满数组,读取两个数据,将a和b记录到了数组当中。第二次,尽可能的读满数组,读取c和d到数组当中,数组原来的a和b因此被覆盖。第三次,只能读到一次数据e并且旧有的数据c覆盖了,而旧有的d因为没有新的数据被读取到覆盖而保留。第四次则是没有读取到数据,len返回-1。

如何将这个残留数据去除呢?只留下读取到的e。在我们的String的构造方法里面,它除了能把字节数组变成字符串以外,它还可以把字节数组的一部分变成字符串,我们可以在方法参数里面添上0和len,表示从0索引开始,一共要去把len个元素变成字符串。这样第三次读取的时候只会读到e。

1.5 try-catch异常处理


java
package com.lkbhua.IO.FileInputStreamDemo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class demo4 {
public static void main(String[] args) {
/* 利用try...catch..finally捕获拷贝文件中代码出现的异常 */
FileInputStream fis = null;
FileOutputStream fos = null;
try {
// 1、创建对象
fis = new FileInputStream("c:\\Users\\27116\\Desktop\\test\\a.txt");
fos = new FileOutputStream("lkb04-File&IOCode\\b.txt");
// 2、拷贝
int len;
byte[] bytes = new byte[1024];
while ((len = fis.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 3、释放资源
// 报错的原因:fos、fis是局部变量,只在所属的括号范围内有效,这里没有定义
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}


