JDK1.7的处理方式
JDK7增加 try-with-resource 语句来处理资源,该语句确保了每个资源在语句结束时关闭。
/*
JDK7以前的处理IO流异常
try {
可能有问题的代码
} catch (异常类名 变量名) {
处理异常的代码
} finally {
关闭流
}
代码繁琐
JDK7处理IO流异常
会自动关闭流
try (创建流的代码) {
可能有问题的代码
} catch (异常类名 变量名) {
处理异常的代码
}
*/
public class Demo01 {
public static void main(String[] args) {
// JDK1.7以前处理IO流异常
FileReader fir = null;
try {
fir = new FileReader("study_day11\\abc\\1.txt");
fir.read();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//fir可能获取失败,所以先进行判断
if(fir != null){
fir.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
// JDK1.7处理IO流异常, 只有实现了AutoCloseable接口的类才能放入,会自动关闭流
try(
//自动关闭流,两个以上用分号隔开
FileReader fir1 = new FileReader("study_day11\\abc\\1.txt");
FileWriter fiw = new FileWriter("study_day11\\abc\\1.txt")
){
fir.read();
fiw.write("1");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
基本流
字节流: FileInputStream , FileOutputStream
字符流: FileReader , FileWriter
缓冲流,转换流,对象流等是对基本流的增强。
缓冲流是对4个基本的 FileXxx 流的增强,所以也是4个流,按照数据类型分类:
字节缓冲流: BufferedInputStream , BufferedOutputStream
字符缓冲流: BufferedReader , BufferedWriter
缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。
字节缓冲流
/*
目标:字节缓冲流(重点)
讲解:
基本流:
输入流 输出流
字节流 FileInputStream FileOutputStream
字符流 FileReader FileWriter
我们知道在操作流的时候使用不带数组读取的次数很多,效率低.带数组,提高效率.
既然带数组可以提高效率,Java自己写好了4个类,带数组,提高效率.
这些带数组的流称为缓冲流(高效流), 内部的数组称为缓冲区
缓冲流:
输入缓冲流 输出缓冲流
字节流 BufferedInputStream BufferedOutputStream
字符流 BufferedReader BufferedWriter
缓冲流的规律:
1.以Buffered开头
2.后缀就是继承的父类
目标:学习字节缓冲流
字节输出缓冲流
字节输入缓冲流
字节输出缓冲流
构造方法:
BufferedOutputStream(OutputStream out)
普通方法:
还是OutputStream父类的那些write方法
字节输入缓冲流
构造方法:
BufferedInputStream(InputStream in)
普通方法:
还是InputStream父类的那些read方法
*/
public class Demo02 {
public static void main(String[] args) throws Exception {
fun1();
fun2();
}
/*
BufferedOutputStream:
构造方法:
BufferedOutputStream(OutputStream out) 真正操作文件传入的流, 他内部有一个8192大小的数组,提高效率的
*/
public static void fun1() throws IOException {
//1.基本写字节流
FileOutputStream stream = new FileOutputStream("study_day11//abc//1.txt");
//2.创建缓冲流
BufferedOutputStream bos = new BufferedOutputStream(stream);
//3.写操作
bos.write(97);
//4.关闭流,将基本流放在try()中,因为实现了AutoCloseable接口,会自动帮我们关闭基本流
bos.close();
//stream.close()
}
/*
BufferedInputStream:
构造方法:
BufferedInputStream(InputStream in) 真正操作文件靠传入的流, 缓冲流内部提供8192大小的数组,提高效率
*/
public static void fun2() throws Exception {
//1.基本读字节流
FileInputStream inputStream = new FileInputStream("study_day11//abc//1.txt");
//2.创建缓冲流
BufferedInputStream bis = new BufferedInputStream(inputStream);
//3.读操作
int read = bis.read();
System.out.println((char)read);
//4.关闭流
bis.close();//底层会帮我们关闭基本流,调用基本流.close()
}
}
缓冲流读取一个字节比基本流读取一个字节快非常多
缓冲流读取一个字节数组和基本流读取一个字节数组差不多
字节流使用时建议使用基本流+数组
字符缓冲流及特有方法
/*
目标:字符缓冲流及特有方法(重点)
讲解:
字符输出缓冲流
字符输入缓冲流
小结:
1.BufferReader特有方法?
readLine() // 读一行, 读取到\r\n结束
2.BufferedWriter特有方法?
newLine() 换行, 相当于write("\r\n");
*/
public class Demo04 {
public static void main(String[] args) throws Exception {
fun1();
fun2();
}
/*
BufferedWriter:
构造方法:
BufferedWriter(Writer out) 真正靠参数传入的流去操作文件, 内部有一个8192大小的数组,提高效率
特有方法:
void newLine():
*/
public static void fun1() throws Exception {
BufferedWriter bfw = new BufferedWriter(new FileWriter("study_day11//abc//1.txt"));
bfw.write("今天星期一");
//换行
bfw.newLine();
bfw.write("不吃肯德基");
//如果忘记关闭流,还会导致原本文件中的数据丢失
//底层将基本流放在try()中,因为实现了AutoCloseable接口,会自动帮我们关闭基本流
bfw.close();
}
/*
BufferedReader:
构造方法:
BufferedReader(Reader in) 真正操作文件靠参数传入的流, 提供8192大小的数组,提高效率
特有方法:
String readLine()
*/
public static void fun2() throws Exception {
BufferedReader bfr = new BufferedReader(new FileReader("study_day11//abc//1.txt"));
/*//只能读一个
int read = bfr.read();
System.out.println((char)read);*/
/*//读一行
String s = bfr.readLine();
System.out.println(s);*/
//循环
String i;
while((i = bfr.readLine())!=null){
System.out.println(i);
}
底层会帮我们关闭基本流,调用基本流.close()
bfr.close();
}
}
字符集是一些字符的集合。
ASCII字符集
ISO-8859-1字符集
GBxxx字符集
Unicode字符集
字符编码是字符与数字之间的对应规则。
将字符转成二进制,称为编码。
使用ASCII编码,将 ‘b’ -> 01100010
将二进制数解析成文字,称为解码。
使用ASCII编码,将 01100010 -> ‘b’
InputStreamReader
OutputStreamWriter
/*
目标:学习字符流读不同编码的文件乱码问题
讲解:
中文在GBK编码中占2个字节
中文在UTF-8编码中占3个字节
IDEA默认是UTF-8编码
小结:
1.为什么会乱码?
保存和读取使用了不同的编码
2.如何解决乱码?
保证读取时的编码和保存的编码是相同的就可以
*/
public class Demo06 {
public static void main(String[] args) throws Exception {
fun1();
}
// 字符流读取UTF-8的文字 (正常) IDEA默认是UTF-8编码,文件也是UTF-8编码
//UTF-8大小写都行,-也可以省略
public static void fun1() throws Exception {
InputStreamReader ir = new InputStreamReader(new FileInputStream("study_day11\\abc\\student.txt"), "utf8");
//默认是utf8,可以指定
int len;
while ((len = ir.read()) != -1) {
System.out.println((char) len);
}
ir.close();
}
// 字符流读取GBK的文字 (有乱码, 文件是GBK编码, IDEA读取时默认使用UTF-8读取)
public static void fun2() throws Exception {
OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream("\"study_day11\\\\abc\\\\student.txt\""), "GBK");
os.write("我爱你");
os.close();
}
}
/*
转换流,指定编码读取/写数据
目标:学习InputStreamReader转换流读取字符数据
讲解:
InputStreamReader类的说明:
继承了Reader属于字符流体系,使用父类Reader中的read方法来读取数据,可以指定编码来读取数据
构造方法:
InputStreamReader(InputStream in) 创建InputStreamReader,使用默认的字符集操作字符(IDEA默认UTF-8)
InputStreamReader(InputStream in, String charsetName) 创建InputStreamReader,使用指定字符集操作字符
String charsetName: 通常写GBK/UTF-8 大小写都行
InputStreamReader类的好处
可以指定编码读取数据
*/
public class Demo07 {
public static void main(String[] args) throws Exception {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("study_day11//abc/2.txt"));
InputStreamReader isr = new InputStreamReader(new FileInputStream("study_day11//abc/2.txt"));
osw.write("a");
isr.read();
isr.close();
osw.close();
}
}
/*
目标:学习OutputStreamWriter转换流写字符数据
讲解:
类的说明:
OutputStreamWriter 继承了Writer,属于字符流体系,还是使用Writer父类的那些write方法写数据.可以指定字符集
构造方法:
OutputStreamWriter(OutputStream out) 创建一个OutputStreamWriter, 使用默认编码写数据(IDEA默认编码是UTF-8)
OutputStreamWriter(OutputStream out, String charsetName) 创建一个OutputStreamWriter, 使用指定编码写数据
OutputStreamWriter类的好处
可以指定编码写字符数据
*/
public class Demo08 {
public static void main(String[] args) throws Exception {
// 写数据到GBK编码的文件
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(""),"GBK");
osw.write(97);
osw.close();
}
}
ObjectOutputStream
/*
目标:学习对象输出流将对象写到文件中
ObjectOutputStream (对象输出流/序列化流)
将对象的数据保存到文件
构造方法:
ObjectOutputStream(OutputStream out) 创建ObjectOutputStream对象,将对象数据写入指定文件
特有方法:
void writeObject(Object obj)
注意:
1.对象要序列化到文件,这个类要实现Serializable接口
Serializable标记接口. 主要给JVM虚拟机看的.看到Serializable接口会把对象转成字节数据.我们就可以通过流写到文件中
2.被transient修饰的成员变量不会保存到文件
3.InvalidClassException: 无效的类异常,就是版本号对不上了
出现的步骤:
1.执行 writeObject 把对象保存到文件
2.修改 Person 类
3.执行 readObject 读取文件的对象
在String类中找到版本号的编写方式,版本号本身可以随意修改
*/
public class Demo10 {
public static void main(String[] args) throws Exception {
// ObjectOutputStream: 包装加强.把对象保存到文件
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("study_day11/abc/3.txt"));
Person person = new Person("张三", 18);
oos.writeObject(person);
//关闭流
oos.close();
}
}
Person
public class Person implements Serializable{
private String name;
private int age;
//版本号
private static final long serialVersionUID = -3894758923477710L;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Person{name = " + name + ", age = " + age + "}";
}
}
ObjectInputStream
/*
目标:学习对象输入流将文件中的对象读入程序中
讲解:
ObjectInputStream类 对象输入流,读取文件中的数据到程序中形成对象
构造方法:
ObjectInputStream(InputStream in) 创建ObjectInputStream对象,通过基本流指定读取哪个文件
特有方法:
Object readObject()
*/
public class Demo11 {
public static void main(String[] args) throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("study_day11//abc//3.txt"));
Object o = ois.readObject();
System.out.println(o);
}
}
如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?
给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程
/*
目标:学习打印流
讲解:
打印流分类: Print
字节打印流: PrintStream *
字符打印流: PrintWriter
PrintStream类的使用:
构造方法:
PrintStream(String fileName) 创建PrintStream, 指定打印的目的地
PrintStream(File file) 创建PrintStream, 指定打印的目的地
PrintStream(OutputStream out) 创建PrintStream, 指定打印的目的地
普通方法:
print(Xxx x) 打印数据,不换行
println(Xxx x) 打印数据,换行
原样输出,参数写什么就打印什么
小结:
2.PrintStream类常用哪2个方法?
print(Xxx x) 打印数据,不换行
println(Xxx x) 打印数据,换行
alt + 鼠标左键拖动: 多行编辑
将来我们学习Java做网站,就是使用打印流把数据打印到浏览器上面
*/
public class Demo13 {
public static void main(String[] args) throws Exception {
// 创建打印流
PrintStream printStream = new PrintStream(new FileOutputStream("study_day11//abc//1.txt"));
printStream.println(true);
printStream.close();
}
}
/*
目标:学习Properties作为集合的使用
讲解:
继承体系
Map
↑ 实现
Hashtable
↑ 继承
Properties
Properties类介绍:
1.Properties实现了Map接口,就是一个双列集合可以存储键值对数据, 键和值都是字符串类型
2.Properties可以结合流进行操作, 可以把集合中的数据保存到流中, 也可以从流中来加载数据
Properties作Map集合的特有方法:
Object setProperty(String key, String value) 添加键值对,修改键值对
String getProperty(String key) 通过键获取值
小结:
Properties是一个Map集合,可以存储键值对数据,键和值都是String类型
*/
public class Demo141 {
public static void main(String[] args) {
// Properties作为Map集合的使用
Properties properties = new Properties();
properties.setProperty("年龄","18");
properties.setProperty("姓名","张");
String name = properties.getProperty("姓名");
String age = properties.getProperty("年龄");
System.out.println(name+age);
properties.forEach((k,v)->{
System.out.println(k+":"+v);
});
}
}
/*
目标:学习Properties保存和加载文件数据
讲解:
Properties和流操作的特有方法:
void store(Writer writer, String comments) 把Properties集合中的键值对数据保存到流中
// Writer writer: 指定数据流向哪个文件
// String comments: 注释
void load(Reader reader) 把文件的键值对数据加载到Properties集合中
*/
public class Demo142 {
public static void main(String[] args) throws Exception {
//fun1();
fun2();
}
// Properties属性集保存数据到文件: void store(Writer writer, String comments)
public static void fun1() throws Exception {
Properties properties = new Properties();
properties.setProperty("username","张三");
properties.setProperty("password","123456");
//直接把数据写入文件,不会留在缓冲区
FileWriter fw = new FileWriter("study_day11//abc/5.txt");
properties.store(fw,"");
fw.close();
}
// 加载文件中数据到Properties属性集中: void load(Reader reader)
public static void fun2() throws Exception {
Properties properties = new Properties();
System.out.println("propreties:"+properties);
FileReader ifr = new FileReader("study_day11//abc/5.txt");
properties.load(ifr);
System.out.println(properties);
ifr.close();
}
}
如果你对本文有疑问,你可以在文章下方对我留言,敬请指正,对于每个留言我都会认真查看。