缓冲流
缓冲流是对4个基本的 FileXxx 流的增强,所以也是4个流,按照数据类型分类:
- 字节缓冲流: BufferedInputStream , BufferedOutputStream
字符缓冲流: BufferedReader , BufferedWriter
缓冲流的基本原理:
在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率
字节缓冲流
字节输出缓冲流 BufferedOutputStream
- BufferedOutputStream 继承OutputStream,,操作时还是使用OutputStream的write方法
构造方法
BufferedInputStream 继承InputStream,操作还是使用InputStream的read方法
构造方法:
BufferedWriter 继承了Writer,可以使用父类Writer中的write方法
- 构造方法:
- BufferedWriter(Writer out) 参数要传入基本流,靠基本流来操作文件
特有方法:
BufferedReader 继承了Reader,可以使用父类Reader中的read方法
- 构造方法:
- BufferedReader(Reader in) 参数要传入基本流,靠基本流来操作文件
特有方法
读写一个字节,使用缓冲流,可以明显提高效率
- 读写一个字节数组,基本流和缓冲流差别不大
-
转换流
概述
-
输入转换流 InputStreamReader
InputStreamReader 继承 Reader
- 可以使用平台默认编码 或者 指定编码 读取字符
- InputStreamReader(InputStream in) 使用默认编码读取数据
InputStreamReader(InputStream in, String charsetName) 使用指定编码读取数据
输出转换流OutputStreamWriter
OutputStreamWriter 继承 Writer
- 可以使用平台默认编码 或者 指定编码 写出字符
- OutputStreamWriter(OutputStream out) 使用默认编码写数据
OutputStreamWriter(OutputStream out, String charsetName) 使用指定编码写数据 :::
对象流(序列化流)
对象操作流分为两类
ObjectOutputStream 对象输出流
-
对象操作流API
对象输出流
- ObjectOutputStream(OutputStream out) 对象输出流, 把对象以字节的形式写到本地文件
- public void writeObject(Object obj) 写一个对象到文件中
对象输入流
使用对象输出流将对象保存到文件时会出现NotSerializableException异常
- 解决办法:需要让类实现Serializable接口
- 用对象序列化流序列化了一个对象后,假如我们修改了对象所属的类结构,读取数据会会出问题,会抛出InvalidClassException异常
- 解决办法:给对象所属的类加一个 serialVersionUID 属性
如果一个对象中的某个成员变量的值不想被序列化,那么给成员变量加transient关键字,该成员变量就不会被序列化到文件中 :::
打印流
字节打印流: PrintStream
继承自FileOutputStream,write()方法和 FileOutputStream 流一样,可以写出字节或者字节数组
特有的 println() 和 print() 方法,根据参数写出数据
字符打印流: PrintWriter
继承自Writer,write()方法和 Writer 流一样,可以写出字符或者字符数组或者字符串。
特有的 println() 和 print() 方法,根据参数写出数据
System.out.println()输出语句中的out对象,其实就是一个PrintStream类的对象
- System类内置了一个PrintStream对象,用于将数据快速打印到控制台
PrintStream 的API
构造器
- PrintStream(File file) 创建PrintStream, 指定打印的目的地
PrintStream(String fileName) 创建PrintStream, 指定打印的目的地
特有方法
print(Xxx x) 不换行打印,参数写什么,就输出什么
println(Xxx x) 换行打印,参数写什么,就输出什么
PrintWriter 和 PrintStream 用法几乎一样 只不过PrintStream是操作字节,PrintWriter是操作字符
属性集
:::tips
Properties 类表示属性集。他是一个特殊的集合,可以结合IO流操作
- Properties实现了Map接口,可以当做Map集合使用
Properties可以结合流进行数据读写,可以把集合中的数据保存到流中,也可以从流中来加载数据
Properties作为集合的特有方法
Object setProperty(String key, String value) 添加键和值,键和值都是String类型,键存在就覆盖值
- String getProperty(String key) 通过键获取值,如果键不存在,返回null
Set
stringPropertyNames() 获取所有的键 Properties和IO流结合的方法
void load(Reader reader) 使用字符输入流 加载 键值对 到Properties中
- void store(Writer writer, String comments) 使用字符输出流将Properties中的键值对 保存 到文件中
- void load(InputStream inStream) 使用字节输入流 加载 数据到Properties中
- void store(OutputStream out, String comments) 使用字节输出流将Properties中的数据保存到文件
:::
IO流异常处理
:::tipsJDK7增加 try-with-resource 语句来处理资源,该语句确保了每个资源在语句结束时关闭
- try(创建流对象,多个语句使用分号隔开) {
- 可能出现异常的代码;
- } catch(异常类名 变量名) {
- 异常的处理代码;
- }
自动关闭流,释放资源 :::
/*
目标:学习字节缓冲流的使用
1.字节缓冲输入流:
BufferedInputStream
2.特点:
缓冲流以Buffered开头,用法和FileInputStream一样。
缓冲流底层使用数组作为缓冲区,能提高读写的效率。
3.构造方法:
BufferedInputStream(InputStream in)
*/
public static void main(String[] args) throws Exception {
//创建输入流对象
BufferedInputStream input = new BufferedInputStream(
new FileInputStream("Day11BufferedIO\\A\\a.txt")
);
byte[] arr = new byte[1024];
int len;
while ((len = input.read(arr)) != -1) {
System.out.println(new String(arr, 0 ,len));
}
input.close();
}
/*
目标:学习字节缓冲流的使用
1.字节缓冲输出流:
BufferedOutputStream
2.特点:
缓冲流以Buffered开头,用法和FileOutputStream一样。
缓冲流底层使用数组作为缓冲区,能提高读写的效率。
3.构造方法:
BufferedOutputStream(OutputStream out)
*/
public static void main(String[] args) throws Exception {
//创建输出流对象
BufferedOutputStream outPut = new BufferedOutputStream(
new FileOutputStream("Day11BufferedIO\\A\\a.txt", true)
);
//写入数据
outPut.write("爪哇程序员".getBytes());
outPut.close();
}
/*
目标:学习字符缓冲流的使用
字符输入缓冲流:BufferedReader
特点:
继承自Reader,用法和FileReader一样。
底层使用缓冲数组读取数据,效率高。
构造方法:
BufferedReader(Reader in)
特有方法:
String readLine() 读取一行数据,读取不到返回null
*/
public static void main(String[] args) throws Exception {
BufferedReader reader = new BufferedReader(
new FileReader("Day11BufferedIO\\A\\b.txt")
);
String line;
//一次读取一行,到返回null结束
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
}
/*
目标:学习字符缓冲流的使用
字符输出缓冲流:BufferedWriter
特点:
继承自Reader,用法和FileWriter一样。
底层使用缓冲数组读取数据,效率高。
构造方法:
BufferedWriter(Writer out)
特有方法:
void newLine() 写一个换行符,相当于写出"\r\n"
注意:
使用BufferedWriter写出数据后,记得调用flush或者close
*/
public static void main(String[] args) throws Exception {
BufferedWriter writer = new BufferedWriter(
new FileWriter("Day11BufferedIO\\A\\b.txt", true)
);
writer.write("爪哇程序运行");
writer.newLine();
writer.write("爪哇程序运行");
writer.close();
}
//DEA中默认使用UTF-8编码,如果在IDEA中读取其他编码的文件,就容易乱码
public static void main(String[] args) throws Exception {
InputStreamReader reader = new InputStreamReader(
new FileInputStream("Day11BufferedIO\\A\\gbk_file.txt"), "GBK"
);
char[] arr = new char[1024];
int len;
while ((len = reader.read(arr)) != -1) {
System.out.println(new String(arr, 0, len));
}
reader.close();
}
/*
练习文件的编码转换
需求:读取GBK编码的文本文件gbk_file.txt,转换为UTF-8编码的文本文件utf8_file.txt。
分析:
使用GBK编码读取文件内容。
使用UTF-8编码写字符数据到文件。
循环读写
*/
public class DemoFileCode {
public static void main(String[] args) throws Exception {
InputStreamReader reader = new InputStreamReader(
new FileInputStream("Day11BufferedIO\\A\\gbk_file.txt"), "GBK"
);
OutputStreamWriter writer = new OutputStreamWriter(
new FileOutputStream("Day11BufferedIO\\A\\utf8_file.txt"), "UTF-8"
);
char[] arr = new char[1024];
int len;
while ((len = reader.read(arr)) != -1) {
writer.write(arr, 0, len);
}
reader.close();
writer.close();
}
}
/*
目标:使用对象输出流将内存中的对象写到文件中。
ObjectOutputStream (对象输出流/序列化流)
继承自OutputStream,可以将内存中的对象数据写出到文件中。
1.构造方法: ObjectOutputStream(OutputStream out)
2.序列化对象(将对象持久化保存): writeObject(Object obj)
3.要求:对象所属的类要实现 Serializable接口
4.transient关键字:被修饰的成员变量不会被序列化
目标:使用对象输入流将文件中的对象读入程序中
ObjectInputStream(对象输入流/反序列化流)
把写到本地文件中的对象读到内存中。
1.构造方法: ObjectInputStream(InputStream in)
2.反序列化(将对象读回内存): Object readObject()
*/
public static void main(String[] args) throws Exception {
Person person = new Person("张三", 23);
//创建对象输出流
ObjectOutputStream output = new ObjectOutputStream(
new FileOutputStream("Day11BufferedIO\\A\\c.txt")
);
//序列化对象(将对象持久化保存)
output.writeObject(person);
output.close();
//创建对象输入流
ObjectInputStream stream = new ObjectInputStream(
new FileInputStream("Day11BufferedIO\\A\\c.txt")
);
//反序列对象(将对象读回内存)
Object o = stream.readObject();
System.out.println(o);
stream.close();
}
//需要序列化对象,类要实现Serializable接口
public class Person implements Serializable {
//为当前类加一个唯一序列化标记
private static final long serialVersionUID = 3725032426848681276L;
private String name;
//transient不让成员变量序列化
private transient int age;
//构造方法setgettoString
}
/*
目标:了解打印流的使用
1.打印流分类:
字节打印流: PrintStream
字符打印流: PrintWriter
2.PrintStream构造方法:
PrintStream(String fileName) :根据字符串路径指定打印目的地。
3.重要方法:
print(任意类型数据) 打印数据,不换行
println(任意类型数据) 打印数据,换行
原样输出,参数写什么就打印什么
说明:PrintWriter和PrintStream用法几乎一样。
只不过PrintStream是操作字节,PrintWriter是操作字符。
*/
public static void main(String[] args) throws Exception {
//打印流
PrintStream stream = new PrintStream("Day11BufferedIO\\A\\d.txt");
//保存数据到文件并且换行
stream.println("123");
stream.print("qwe");
stream.close();
}
/*
目标:掌握Properties保存和加载文件的方式
1.将Properties中的键值对数据保存到文件中:
void store(Writer writer, String comments) :
第一个参数为字符输出流,第二个参数为写到文件的注释。
*/
public static void main(String[] args) throws Exception {
Properties p = new Properties();
//添加键值对
p.setProperty("张三", "23");
p.setProperty("李四", "24");
p.setProperty("王五", "25");
p.store(new FileWriter("Day11BufferedIO\\A\\用户列表.txt"), "");
}
/*
2.加载文件数据到Properties集合中:
void load (Reader reader) : 参数为字符输入流
*/
public static void main(String[] args) throws Exception {
Properties p = new Properties();
p.load(new FileReader("Day11BufferedIO\\A\\用户列表.txt"));
Set<String> keys = p.stringPropertyNames();
for (String key : keys) {
String s = p.getProperty(key);
System.out.println(key + " = " + s);
}
}
/*
Properties作为Map集合的特有方法:
Object setProperty(String key, String value) :添加键值对,键和值都是字符串类型。
String getProperty(String key) :通过键获取值,获取不到返回null
stringPropertyNames() 获取所有的属性名,遍历属性名获取属性值
*/
public static void main(String[] args) {
Properties p = new Properties();
//setProperty 添加键值对,键和值都是字符串类型。
p.setProperty("name","张三");
p.setProperty("age","18");
p.setProperty("address","广州");
//getProperty(String key)
String name = p.getProperty("name");
System.out.println(name);
//遍历 stringPropertyNames 获取所有的属性名
Set<String> keys = p.stringPropertyNames();
for (String key : keys) {
String value = p.getProperty(key);
System.out.println(key+","+value);
}
}