IO流
I :Input(输入)数据从外部流入程序(硬盘到内存)
O:Output(输出)数据从程序流出外部(内存到硬盘)
流:类似于水流—有方向,线性
作用:
可以读写文件的内容
体系:
A).字节流:按“字节”读写文件。可以操作任何类型文件
1).输出流:OutputStream(抽象类)
|--FileOutputStream(子类)
2).输入流:InputStream(抽象类)
|--FileInputStream(子类)
B).字符流:按“字符”读写文件。仅仅可以读、写纯文本文件。
1).输出流:Writer(抽象类)
|--OutputStreamWriter(转换流)
|--FileWriter(子类)
2).输入流:Reader(抽象类)
|--InputStreamReader(转换流)
|--FileReader(子类)
IO流图解:
字节流
一切皆为字节,“字节流”是Java中IO流的最基本的流,任何的其它流(字符流、打印流....)都是基于字节流的
1字节输出流OutputStream:
OutputStream(抽象类) à 子类:FileOutputStream
输出的方法;
1).write(int b) 输出一个字节
2).write(byte[] byteArray) 输出一个字节数组
3).write(byte[] byteArray,int off,int len)输出一个字节数组的部分,起始位置和长度
2字节输出流子类FileOutputStream:
构造方法:
1). FileOutputStream(String name) :使用指定的文件名构造一个输出流 覆盖写
2). FileOutputStream(File file) 创建文件输出流以写入由指定的 File对象表示的文件。覆盖写
3). FileOutputStream(File file, boolean append) 创建文件输出流以写入由指定的 File对象表示的文件。追加写
4). FileOutputStream(String name, boolean append) 创建文件输出流以指定的名称写入文件。 追加写
输出的方法:(无特有,都是从父类继承的)
1).write(int b):输出一个字节(很少用)
2).write(byte[] byteArray):输出一个字节数组(常用:write("你好".getBytes()))
3).write(byte[] byteArray,int off,int len):输出一个字节数组的一部分(很少用)。
注意:
1).Java中任何的输出流,构造时文件都可以不存在,会自动创建一个空文件。
2).Java的IO流不要构造在一个“存在的目录上”,否则运行时异常。
3).三种输出的方法都是无返回值的,每次调用方法都会写入一次内容
public static void main(String[] args) throws IOException {
File file = new File("demo.txt");
FileOutputStream out1 = new FileOutputStream(file);
FileOutputStream out2 = new FileOutputStream(file,true);
FileOutputStream out3 = new FileOutputStream("demo.txt");
FileOutputStream out4 = new FileOutputStream("demo.txt",true);
int b = 97;
byte[] array = new byte[4];
out1.write(b);
out1.write(array);
out1.write(array,0,3);
String s = "我爱Java";
out1.write(s.getBytes(),0,3);//一个汉字是三个字节
}
写出换行
Windows系统里,换行符号是 \r\n
fos.write("\r\n".getBytes());
3字节输入流InputStream:
InputStream(抽象类) à 子类: FileInputStream
读取的方法:
1).public int read():依次读取一个字节;
2).public int read(byte[] byteArray):依次读取一个字节数组;
3).public int read(byte[] byteArray,int off,int len)读取一个字节数组的部分,起始位置和长度
4.字节输入流的子类FileInputStream:
构造方法:
1).FileInputStream(String pathname):
2).FileInputStream(File file):
//构造方法
File file = new File("demo.txt");
FileInputStream in1 = new FileInputStream(file);
FileInputStream in2 = new FileInputStream("demo.txt");
注意:
1).Java中所有的“输入流”构造时,文件必须存在,否则运行时异常。
读取的方法(从父类继承):
1).public int read():读取一个字节;返回读取的字节对应编码,两次调用会连续读取两个字节
2).public int read(byte[] byteArray):读取一个字节数组;返回每次读取的字节个数,读取的字节覆盖数组原有的内容,如果读取一个返回1覆盖数组第一个内容,如果没有读取到内容返回-1
3).write(byte[] byteArray,int off,int len)输出一个字节数组的部分,起始位置和长度返回读取的字节数
byte[] b = new byte[4];
System.out.println(in1.read());
System.out.println(in1.read());
in1.read(b,0,3);
while ((a = in1.read(b)) != -1) {
System.out.println(Arrays.toString(b));
}
//结果
// 97
//98
//[99, 100, 101, 102]
//[103, 100, 101, 102]
5.字节流文件复制案例:
首先按照字节流读入文件,然后按照字节流输出文件,所以需要一个输入流一个输出流
示例代码:
public static void main(String[] args) throws IOException {
//首先读取文件,创建输入流
FileInputStream in = new FileInputStream("demo.txt");
//然后写入文件,创建输出流
FileOutputStream out = new FileOutputStream("demo_copy.txt");
//1,一个字节的读取,一个字节的写入
int b = 0;
while ((b = in.read()) != -1) {
out.write(b);
}
//2.一个字节数组的输入和输出
byte[] byteArray = new byte[3];
while ((b = in.read(byteArray)) != -1) {
//最后一次输入的字节个数不一定
//所以输出用部分输出的方式
out.write(byteArray,0,b);
}
in.close();
out.close();
}
字符流
按照一次一个字符读取和写入,因为每个国家的字符的字节数不同,如果按照一个字节的方式比较麻烦,所以Java提供了只能操作纯文本字符流的方式,
1.字符输出流Writer:
Writer(抽象类) à OutputStreamWriter(转换流) à FileWriter(子类)
输出的方法:
1).write(int c):输出一个字符;
2).write(char[] chArray):输出一个字符数组
3).write(char[] chArray,int off,int len):输出字符数组的一部分;
4).write(String s):输出一个字符串;
5).write(String s,int off,int len):输出字符串的一部分。
2.字符输出流子类FileWriter:
构造方法:
1).FileWriter(String fileName) 构造一个给定文件名的FileWriter对象。
2).FileWriter(File file) 给一个File对象构造一个FileWriter对象。
3).FileWriter(String fileName, boolean append) 构造一个给定带有布尔值的和文件名FileWriter对象。表示是否追加写入的数据。
4).FileWriter(File file, boolean append) 给一个File对象和布尔值构造一个FileWriter对象。 表示是否追加写入的数据。
输出的方法(全部从父类继承):
1).write(int c):输出一个字符;
2).write(char[] chArray):输出一个字符数组
3).write(char[] chArray,int off,int len):输出字符数组的一部分;
4).write(String s):输出一个字符串;
5).write(String s,int off,int len):输出字符串的一部分。
注意:
1).字符流输出完之后必须刷新或者关闭,关闭有刷新的功能,否则内容在缓存区不会被写入文件
public static void main(String[] args) throws IOException {
//构造方法:
File file = new File("demo.txt");
FileWriter out1 = new FileWriter(file);
FileWriter out2 = new FileWriter(file,true);
FileWriter out3 = new FileWriter("demo.txt",true);
FileWriter out4 = new FileWriter("demo.txt");
//输出方法:
char[] array = {'a','b','c'};
out1.write(97);
out1.write(array);
out1.write(array,0,2);
out1.write("java");
out1.write("java",0,3);
//关闭刷新
out1.close();
}
关闭和刷新:
因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。但是关闭的流对象,是无法继续写出数据的。
如果我们既想写出数据,又想继续使用流,就需要 flush 方法了。
flush() :刷新缓冲区,流对象可以继续使用。
close() :关闭流,释放系统资源。关闭前会刷新缓冲区。
字符输入流Reader:
Reader(抽象类) à InputStreamWriter(转换流) à FileReader(子类)
读取的方法:
1).int read():读取一个字符。返回:读取的字符的编码值;int类型
2).int read(char[] chArray):读取一个字符数组;返回值:读取的字符数量。
字符输入流子类FileReader:
构造方法:
1).FileReader(String path):
2).FileReader(File file):
输入的方法:
1).public int read():依次读取一个字节;
2).public int read(byte[] byteArray):依次读取一个字节数组;
3).public int read(byte[] byteArray,int off,int len)读取一个字节数组的部分,起始位置和长度
public static void main(String[] args) throws IOException {
//构造方法
File file = new File("demo.txt");
FileReader in1 = new FileReader(file);
FileReader in2 = new FileReader("demo.txt");
//读取方法
char[] arr = new char[4];
in1.read();
in1.read(arr);
in1.read(arr, 0, 2);
}
IO异常处理
JDK7之前,使用 try...catch...finally代码块处理异常部分
JDK7,使用try-with-resource处理,自动关闭每个资源
JDK9,对于引入对象的方式,支持的更加简洁,也是自动关闭资源
Properties
java.util.Properties(类):此类是一个Map集合。此类中有两个方法可以用于方便的读、写配置文件;
配置文件:
指软件运行过程中记录用户的一些设置信息的文件,这种配置文件在国际上有一个通用的格式:
名1 = 值
名2 = 值
名3 = 值
....
这种格式同Map的键值对格式正好匹配,所以Java制作了一个Properties类来方便的读写配置文件。
使用:
1).Properties集合-->配置文件:store()方法
2).配置文件-->Properties集合:load()方法
代码示例:
public class Properties_添加到文件 {
public static void main(String[] args) throws IOException {
FileWriter out = new FileWriter("demo.txt");
Properties ps = new Properties();
ps.setProperty("姓名1", "姓名11");
ps.setProperty("姓名2", "姓名22");
ps.setProperty("姓名3", "姓名33");
ps.store(out,"名单");
out.close();
}
}
public class Properties_读取文件内容 {
public static void main(String[] args) throws IOException {
Properties ps = new Properties();
FileReader in = new FileReader("demo.txt");
ps.load(in);
//stringPropertyNames()返回Set<String>集合
for (String s : ps.stringPropertyNames()) {
System.out.println(ps.get(s));
}
}
}