IO
流:数据传递的统称
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。
标准输入
InputStream in = System.in;
in.read();
标准输出
PrintStream是OutputStream的子类
PrintStream out = System.out;
out.println();
分类
处理数据类型不同:字符流与字节流
数据流向不同:输入流与输出流(相对内存)
功能不同:节点流和处理流
抽象类
文件流
InputStream
FileInputStream 字节输入流
输入/读取 : 必须先找到这个文件
绝对位置 : 当前文件系统的根目录为准
相对位置 : 以当前文件所在目录为准 ./
./ 当前目录 , …/ 上级目录 , …/…/…/
eclipse中 ./ 是当前项目 D:\workspace\w20210322_17\JavaSE_08_IO
close();
read();
read(byte[] bytes);
read(byte[] bytes , int start , int length);
// 会匹配当前操作系统,window \\ linux /
System.out.println(File.separator);
// 创建字节输入流对象
// 相对
FileInputStream fis = new FileInputStream("./src/com/Test_01.java");
// read 读取下一个字节,如果到达文件末尾,返回 -1 ,默认光标在顶端,读一下,向下移动一位,并返回下一位的值
int i1 = fis.read();
System.out.println((char)i1);
// 循环读取
int temp = 0;
while ( (temp=fis.read()) != -1 ) {
System.out.print((char)temp);
}
完整需要try…catch异常,关闭流,提升变量
public static void main(String[] args) {
// 提升变量至main方法中,否则finally中访问不到
// 局部变量没有默认值,并且try有不执行情况,所以默认赋值null
FileInputStream fis = null ;
try {
// 创建对象并获取文件流
fis = new FileInputStream("./src/com/Test_01.java");
// 循环读取
int temp = 0;
while ((temp = fis.read()) != -1) {
System.out.print((char) temp);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
// 关闭资源
try {
// 防止未找到文件,导致空指针异常
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
jdk1.8后try可以自动关闭流
使用字节数组可以一次性取出多个字节提高效率,但是如果字节数组过大,会留有空位,如果小于内容则第二次读取内容会重复,为了解决这个问题,需要额外传入两个变量控制读取个数
输出时使用String的构造方法可以将字节数组转换为字符串
try (
// 创建对象并获取文件流
FileInputStream fis = new FileInputStream("./src/com/Test_01.java");) {
// 循环读取
byte[] bytes = new byte[100];
int temp = 0;
while ((temp = fis.read(bytes)) != -1) {
// 不能直接把数组转换 为字符串,否则有多种情况会导致数据不准确
// 比如 : 1 数组长1000 , 而文件中字节只有 100 , 则 数组中还有900个0 没有添加数据,此时如果全部转换为字符串,数据就不准确了
// 比如 : 2 数组长100 , 而文件中字节有150 , 则 第二次读的时候,只能读取到50个,而数组中第一次读取的后50个元素还在数组中,所以导致数据冗余
// 所以最好是 读了多少 就转换多少,而 该方法返回值 就是当前次读取的个数
// System.out.print(new String(bytes));
System.out.print(new String(bytes, 0, temp));
}
} catch (Exception e) {
e.printStackTrace();
}
OutputStream
FileOutputStream 字节输出流
常用方法
close();
flush();//清空缓存区
write(int b);
write(byte[] bytes);
write(byte[] bytes , int start , int length);
输出流,如果目标文件不存在 会自动创建该文件,注意 不会创建目录,如果目录不存在就会报错
覆盖与追加
构造方法 :
FileOutputStream(String) : 只传递需要写出的文件路径,默认覆盖写出
FileOutputStream(String,boolean) : 只传递需要写出的文件路径,第二个参数,如果为true 就是追加写出,false是覆盖写出
字符串转换为字节数组 getBytes()
// 创建对象 默认覆盖写出
// FileOutputStream fos = new FileOutputStream("D:/123.txt");
// 追加
FileOutputStream fos = new FileOutputStream("D:/123.txt",true);
// 写出单个内容
fos.write(97);
byte[] bytes = {48,49,50,51};
// 写出整个数组
fos.write(bytes);
// 写出一部分
fos.write(bytes, 0, 3);
// 写出字符串
String str ="你好吗";
bytes = str.getBytes();
fos.write(bytes);
// 刷缓存
fos.flush();
// 关闭
fos.close();
Reader
FileReader字符输入流
方法与字节输入流一致
可以解决输入数据汉字的乱码问题,一般用于纯文本文件,像压缩包,图片,视频,音乐等 还是要使用字节,使用字符会出现问题
try (
// 打开字符输入流
FileReader fr = new FileReader("./src/com/Test_01.java");
){
char[] chars = new char[100];
int temp = 0;
while ( (temp = fr.read(chars)) != -1 ) {
System.out.print(new String(chars,0,temp));
}
} catch (Exception e) {
e.printStackTrace();
}
Writer
FileWriter 字符输出流
除与字节输出流相等的方法外还有
write(String str);
write(String str , int start , int length);
append(char ch);
// 字符输出流 用于同字节输出流,只是写出方法是字符数组 和 字符串
try (
FileWriter fw = new FileWriter("D:/123.txt");
){
fw.write("你好吗");
// 换行符
fw.write("\n");
fw.write("吃了吗");
fw.flush();
} catch (Exception e) {
e.printStackTrace();
}