第二十一章 文件和IO二
1.作业回顾
1,编写程序,在E盘创建一个目录test,再创建一个子目录abc,在abc中创建一个文件test.txt,使用输出流将往test.txt中写一个字符串,然后再使用输入流,将test.txt中的文本读到程序中。
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Day20HomeWork {
public static void main(String[] args) {
FileWriter fw = null;
try {
fw = new FileWriter("C:/test/abc/test.txt");
fw.write("我爱你中国!");
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fw.flush();
} catch (IOException e) {
e.printStackTrace();
}
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
FileReader fr = null;
try {
fr = new FileReader("C:/test/abc/test.txt");
int c = 0;//保存读到的字符
while(-1 != (c = ( fr.read() )))
System.out.println((char)c);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2,编写程序,在控制台输入源文件路径和目标文件路径,实现任意文件的复制。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class Day20HomeWork2 {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.println("请输入源文件路径");
String src = s.nextLine();
System.out.println("请输入目标文件路径");
String dest = s.nextLine();
File srcFile = new File(src);
File destFile = new File(dest);
if (!srcFile.exists()) {
System.out.println("源文件不存在");
}else {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(srcFile);
fos = new FileOutputStream(destFile);
byte[] bs = new byte[256];
int len = 0;
while(-1 != ( len = fis.read()) ) {
fos.write(bs, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
fos.flush();
} catch (IOException e) {
e.printStackTrace();
}
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
2.节点流和过滤流
2.1节点流和过滤流介绍
直接和数据源(文件,内存块,网络)相连接的流是节点流,否则就是过滤流。
过滤流相当于 在节点流上加了一个流。
节点流和过滤流示意图:
节点流:
FileReader:以字符读文件
FileWriter:以字符写文件
FileInputStream:以字节读文件
FileOutputStream: 以字节写文件
CharArrayReader:以字符读字符数组
CharArrayWriter:以字符写字符数组
StringReader:以字符读字符串
StringWriter:以字符写字符串
ByteArrayInputStream:以字节读字节数组
ByteArrayOutputStream:以字节写字节数组
过滤流:
BufferedReader:以字符读缓冲区
BufferedWriter:以字符写缓冲区
BufferedInputStream:以字节读缓冲区
BufferedOutputStream:以字节写缓冲区
InputStreamReader:以字节输入流转换为字符输入流
OutputStreamWriter:以字符输出流转换为字节输出流
ObjectInputStream:以字节读对象
ObjectOutputStream:以字节写对象
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class Day2103 {
public static void main(String[] args) {
FileReader fr = null;
BufferedReader br = null;
try {
fr = new FileReader("C:/test/abc/test.txt");
//将fr包装成一个缓冲过滤流
//缓冲过滤流内部有一个缓冲区,可以提高IO效率
//装饰者模式
br = new BufferedReader(fr);
int c = 0;
while(-1 != ( c = br.read() )) {
System.out.print((char)c);//中国你好
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//只需要关闭最外层的流
//外层流关闭时会关闭内层流
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
public class Day2104 {
public static void main(String[] args) {
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter("C:/test/abc/test.txt"));
bw.write("我爱你中国");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bw.flush();
} catch (IOException e) {
e.printStackTrace();
}
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3.以指定编码读写文件
import java.nio.charset.Charset;
public class Day2105 {
public static void main(String[] args) {
//获取默认字符集
Charset charset = Charset.defaultCharset();
System.out.println(charset);//UTF-8
}
}
3.1使用GBK读取文件
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
public class Day2106 {
public static void main(String[] args) {
FileInputStream fis = null;
//过滤流,可以包装一个字节流,获得一个字符流,采用指定的编码方式进行转换
InputStreamReader isr = null;
BufferedReader br = null;
try {
fis = new FileInputStream("C:/test/abc/test.txt");
//将字节流以GBK编码转换为字符流
isr = new InputStreamReader(fis, "GBK");
br = new BufferedReader(isr);
String str = null;
while(null != (str = br.readLine())) {
System.out.println(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3.2使用UTF-8写入文件
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
public class Day2107 {
public static void main(String[] args) {
FileOutputStream fos = null;
OutputStreamWriter osw = null;
BufferedWriter bw = null;
try {
fos = new FileOutputStream("C:/test/abc/test.txt");
osw = new OutputStreamWriter(fos, "UTF-8");
bw = new BufferedWriter(osw);
bw.write("哆啦A梦");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bw.flush();
} catch (IOException e) {
e.printStackTrace();
}
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
4.对象的序列化和反序列化一
对象的序列化是将对象保存到外部存储(文件,数据库,网络)。
对象的反序列化是将外部存储(文件,数据库,网络)转换为对象。
为了将对象进行序列化和反序列化,必须实现Serializable接口。Serializable接口是一个标志接口,并没有方法。
4.1将对象保存在外部存储
import java.io.Serializable;
//为了进行序列化和反序列化,必须实现Serializable接口
public class Student implements Serializable{
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class Day2108 {
public static void main(String[] args) {
Student s1 = new Student("张三", 20);
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try {
fos = new FileOutputStream("C:/test/abc/Student.ser");
//过滤流,将一个对象写到输出流中
oos = new ObjectOutputStream(fos);
//将对象s1写到输出流中
oos.writeObject(s1);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
oos.flush();
} catch (IOException e) {
e.printStackTrace();
}
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
4.2将外部存储转换为对象
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Day2109 {
public static void main(String[] args) {
FileInputStream fis = null;
ObjectInputStream ois = null;
try {
fis = new FileInputStream("C:/test/abc/Student.ser");
//过滤流,可以从输入流中取读对象
ois = new ObjectInputStream(fis);
//读取到的对象实际是Student类型的对象,因此可以进行强制类型转换
Student s = (Student) ois.readObject();
System.out.println(s.getName());//张三
System.out.println(s.getAge()); //20
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}finally {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
5.对象的序列化和反序列化二
5.1 transient关键字
如果不想序列化某个字段,可以使用transient关键字
import java.io.Serializable;
//为了进行序列化和反序列化,必须实现Serializable接口
public class Student implements Serializable{
private String name;
//transient表示不对此字段进行序列化和反序列化
//瞬时——不必持久化
private transient int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
//反序列化不会调用构造器
System.out.println("Student构造器");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
5.2 序列化链
序列化时,如果一个对象的字段也是对象,那么这个字段也会序列化。
注意:所有需要序列化的对象都必须实现Serializable接口。
import java.io.Serializable;
//为了进行序列化和反序列化,必须实现Serializable接口
public class Student implements Serializable{
private String name;
//transient表示不对此字段进行序列化和反序列化
//瞬时——不必持久化
private transient int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
//反序列化不会调用构造器
System.out.println("Student构造器");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
public void setTeacher(Teacher t1) {
}
}
import java.io.Serializable;
public class Teacher implements Serializable {
private String name;
private int age;
private String school;
public Teacher(String name, int age, String school) {
super();
this.name = name;
this.age = age;
this.school = school;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
@Override
public String toString() {
return "Teacher [name=" + name + ", age=" + age + ", school=" + school + "]";
}
}
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class Day2108 {
public static void main(String[] args) {
Student s1 = new Student("张三", 20);
Teacher t1 = new Teacher("张三丰", 200, "清华");
s1.setTeacher(t1);
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try {
fos = new FileOutputStream("C:/test/abc/Student.ser");
//过滤流,将一个对象写到输出流中
oos = new ObjectOutputStream(fos);
//将对象s1写到输出流中
oos.writeObject(s1);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
oos.flush();
} catch (IOException e) {
e.printStackTrace();
}
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Day2109 {
public static void main(String[] args) {
FileInputStream fis = null;
ObjectInputStream ois = null;
try {
fis = new FileInputStream("C:/test/abc/Student.ser");
//过滤流,可以从输入流中取读对象
ois = new ObjectInputStream(fis);
//读取到的对象实际是Student类型的对象,因此可以进行强制类型转换
Student s = (Student) ois.readObject();
System.out.println(s.getName());//张三
System.out.println(s.getAge()); //20
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}finally {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
6.Properties文件的使用
java.util.Properties类代表一个java配置文件。
java配置文件以.properties结尾,可以将配置参数。
如数据库连接地址放入到配置文件中,而不使用硬编码。
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class Day2110 {
public static void main(String[] args) {
//props代表了一个配置文件
Properties props = new Properties();
//将配置文件的信息加载到props对象中
//Day2110.class是一个类对象
//java中的每一个类一旦加载到jvm中,就会产生一个类对象
//类对象描述了类的信息(有什么方法,有什么属性)
//类对象有一个方法getResourceAsStream可以从classpath路径下加载文件
//java从classpath下加载类
//每个类只被加载一次,每个类只有一个类对象
InputStream is = null;
//将流中的数据加载到props对象中
is = Day2110.class.getResourceAsStream("/day21/db.properties");
try {
props.load(is);
//props.getProperty方法通过key得到value
System.out.println(props.getProperty("username"));//name
System.out.println(props.getProperty("password"));//1234
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
7.练习
以指定的编码读取文件内容,并将读到的内容以指定的编码写文件,两种编码都配置到properties文件中。