Java进阶11 IO流-功能流
一、字符缓冲流
字符缓冲流在源代码中内置了字符数组,可以提高读写效率
1、构造方法
方法 | 说明 |
---|
BufferedReader(new FileReader(文件路径)) | 对传入的字符输入流进行包装 |
BufferedWriter(new FileWriter(文件路径)) | 对传入的字符输出流进行包装 |
注意:缓冲流不具备读写功能,它们只是对普通的流对象进行包装,正真和文件建立关联的,还是普通流对象
1.1 字符缓冲流的使用
public class BufferedStreamDemo1 {
/*
1、字符缓冲流的基本使用
*/
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("day10\\A.txt"));
//单个读取
int i;
while((i=br.read())!=-1){
System.out.println((char)i);
}
//读取字符数组的一部分
int len;
char[] chs = new char[1024];
while((len=br.read())!=-1){
String s = new String(chs,0,len);
System.out.println(s);
}
br.close();
//字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("day10\\A.txt"));
bw.write("写入数据......")
bw.close();
}
}
1.2 拷贝文件Demo
public class BufferedStreamDemo {
/*
字符缓冲流+自定义数组 拷贝文件
*/
public static void main(String[] args) throws IOException {
//字符流只能拷贝纯文本文件
BufferedReader br = new BufferedReader(new FileReader("day11\\FileReaderDemo1.java"));
BufferedWriter bw = new BufferedWriter(new FileWriter("day11\\copy.java"));
int len;
char[] chs = new char[1024];
while((len=br.read())!=-1){
bw.write(chs,0,len);
}
br.close();
bw.close();
}
}
2、成员方法(特有)
2.1 BufferedReader
方法 | 说明 |
---|
public String readLine() | 一次性读取整行字符串,读取到末尾返回null |
2.2 BufferedWriter
方法 | 说明 |
---|
public void newLine() | 写出换行符(具有兼容性)兼容各个操作系统的换行符 |
2.3 特有方法使用Demo
public class BufferedStreamDemo2 {
/*
拷贝本项目中A.txt文件到本项目copy.txt;
一整行一整行地拷贝
*/
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("day11\\A.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("day11\\copy.txt"));
String line;
while((line=br.readLine())!=null){
//readLine读不到换行符
bw.write(line);
//写出换行符
bw.newLine();
}
br.close();
bw.close();
}
}
二、转换流
1、按照指定的字符编码读写操作
构造方法 | 说明 |
---|
InputStreamReader(InputStream in,String charsetName) | 按照指定的字符编码读取 |
OutputStreamWriter(OutputStream out,String charsetName) | 按照指定的字符编码写出 |
public class ChangeStreamDemo {
/*
转换流的使用Demo
*/
public static void main(String[] args) throws IOException {
//使用GBK字符编码向路径D:\itheima\Resource\A.txt文件写入你好呀
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D:\\itheima\\Rescouce\\A.txt"),"GBK");
osw.write("你好呀");
osw.close();
//使用gbk字符编码从路径D:\itheima\Resource\A.txt文件中读取字符
InputStreamReader isr = new InputStreamReader(new FileInputStream("D:\\itheima\\Resource\\A.txt"),"gbk");
//单个读取
int i;
while((i=isr.read())!=-1){
System.out.print((char)i);
}
isr.close();
}
}
2、将字节流转换为字符流进行操作
三、序列化流
可以在流中,以字节的形式直接读写对象
1、构造方法
方法 | 说明 |
---|
public ObjectInuputStream(InputStream in) | 对象输入流关联文件,关联方式使用字节输入流 |
public ObjectOutputStream(OutoutStream out) | 对象输出流关联文件,关联方式使用字节输出流 |
2、成员方法
方法 | 说明 |
---|
Object readObject() | 从流中读取对象(反序列化) |
void writeObject(Object obj) | 在流中将对象写出(序列化) |
3、方法使用案例
需求:现有3个学生对象,并将对象序列化到流中,随后完成反序列化操作
public class ObjectStreamDemo2 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
readObject();
//用流读对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day11\\obj.txt"));
ArrayList<Student> stuList = (ArrayList<Student>) ois.readObject();
System.out.println(stuList);
ois.close();
}
//将对象写入流
private static void readObject() throws IOException {
//为了一次读写三个学生对象,创建list集合存储
ArrayList<Student> stu = new ArrayList<>();
stu.add(new Student("张三",23));
stu.add(new Student("李四",24));
stu.add(new Student("王五",25));
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day11\\obj.txt"));
oos.writeObject(stu);
oos.close();
}
}
注意事项
-
类需要实现Serializable接口才可以序列化
-
实现接口后,类就会自带一份序列版本号。序列化操作的时候,会将对象信息和版本号一并保存到文件,反序列化的时候,会拿着版本号和流中的版本号进行对比,不一致就会抛异常,起到提醒作用。为了避免这个问题,推荐手动写死serialVersionUID
在IDEA中设置快捷添加serialVersionUID的快捷键
-
-
如果类中的属性被transient进行修饰,将不会参与序列化操作
-
建议:对象的读写操作只进行一次
四、打印流
打印流可以实现方便、高效的打印数据到文件中去(打印什么数据就是什么数据)
1、PrintStream字节打印流(重点)
构造器 | 说明 |
---|
public PrintStream(OutputStream os) | 打印流直接通向字节输出流管道(想要追加时可在os对象的第二个参数位置打开append追加开关) |
public PrintStream(File f) | 打印流直接通向文件对象 |
public PrintStream(String filepath) | 打印流直接通向文件路径 |
成员方法 | 说明 |
---|
public void print\println(Xxx xxx) | 打印任意类型的数据出去 |
2、PrintWriter字符打印流(了解即可)
构造器 | 说明 |
---|
public PrintWriter(OutputStream os) | 打印流直接通向字节输出流管道 |
public PrintWriter(Writer w) | 打印流直接通向字符输出流管道 |
public PrintWriter(File f) | 打印流直接通向文件对象 |
public PrintWriter(String filepath) | 打印流直接通向文件路径 |
方法 | 说明 |
---|
public void print\println(Xxx xxx) | 打印任意类型的数据出去 |
五、Properties集合
1、Properties作为集合使用
构造器 | 说明 |
---|
Properties() | 创建一个没有默认值的空属性列表 |
方法 | 说明 |
---|
Object setProperty(String key,String value) | 添加(修改)一个键值对 |
String getPreperty(String key,String defaultValue) | 根据键获取值 |
Set<String> stringPropertyNames() | 获取集合中所有的键 |
public class PropertiesDemo1 {
/*
properties作为集合的使用
*/
public static void main(String[] args) {
//1、创建集合容器(不需要指定泛型,键和值都是String类)
Properties prop = new Properties();
//2、添加数据到集合(类似于put方法,当key相同时,新value会覆盖旧value)
prop.setProperty("username","admin");
prop.setProperty("passward","123456");
//3、获取集合数据,根据键找值
String username = prop.getProperty("username");
String passward = prop.getProperty("passward");
System.out.println(username+"----"+passward);
System.out.println("-------------------------------");
//4、类似Map集合中keySet方法,获取所有的键
Set<String> keySet = prop.stringPropertyNames();
//5、遍历集合+根据键找值拿到properties集合中的所有键值对
for (String key : keySet) {
System.out.println(key+"----"+prop.get(key));
}
}
}
2、Properties和IO有关的方法
方法 | 说明 |
---|
void load(InputStream inStream) | 从输入字节流读取属性列表(键和元素对) |
void load(Reader reader) | 从输入字符流读取属性列表(键和元素对) |
void store(OutputStream out,String comments) | 将此属性列表(键和元素对)写入此Properties表中,以适合于使用load(InputStream)方法的格式写入输出字符流 |
void store(Writer writer,String comments) | 将次属性列表(键和元素对)写入此Properties表中,以适合使用load(Reader)方法的格式写入输出字符流 |
public class PropertiesDemo2 {
/*
以字节输入输出流为例
*/
public static void main(String[] args) throws IOException {
store();
load();
}
//读取方法
private static void load() throws IOException {
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("day11\\config.properties");
//将读取到的内容存入prop集合
prop.load(fis);
System.out.println(prop);
fis.close();
/**
经常需要修改的值(如用户名密码、数据库连接密码等)写在配置文件里,到时候只要执行这个代码就能直接加载配置文件里的一些设置,免去了频繁修改代码的繁琐
*/
String username = prop.getProperty("username");
String password = prop.getProperty("password");
System.out.println(username);
System.out.println(password);
}
//写入方法
private static void store() throws IOException {
Properties prop = new Properties();
prop.setProperty("username","admin");
prop.setProperty("password","123456");
FileOutputStream fos = new FileOutputStream("day11\\cpnfig.properties");
//第二个参数为备注内容,可传null,也可以传入字符串值
prop.store(fos,"null");
fos.close();
}
}