Java SE09_I/O框架笔记
I/O 框架
1 流的概念
内存与存储设备之间传输数据的通道,数据借助流传输。
2 流的分类
按方向【重点】
- 输入流:将<存储设备>中的内容读到<内存>中
- 输出流:将<内存>中的内容写到<存储设备>中
按单位
- 字节流:以字节为单位,可以读写所有数据
- 字符流:以字符为单位,只能读写文本数据
按功能
- 节点流:具有实际传输数据的读写功能
- 过滤流:在节点流的基础之上增强功能
3 字节流
字节流的父类(抽象类)
//InputStream 字节输入流
public int read(){}
public int read(byte[] b){}
public int read(byte[] b, int off, int len){}
// OutputStream 字节输出流
public void write(int n){}
public void write(byte[] b){}
public void write(byte[] b, int off, int len){}
3.1 文件字节流
文件输入流代码演示:
public static void main(String[] args) throws Exception {
/*
* 演示FileInputStream的使用
* 文字字节输入流
*/
//1.创建文件字节输出流并指定文件路径
FileInputStream fis =new FileInputStream("E:\\newstart\\linshi\\aaa.txt");
//2.读取文件
//2.1单个字节的读取
// int data = 0;
// while((data = fis.read())!=-1){
// System.out.print((char)data);//abcdefg
// }
//2.2一次读取多个字节
// byte[] buf = new byte[3];//大小为3的缓存区
// int count = fis.read(buf);//一次读3个
// System.out.println(new String(buf));//abc
// System.out.println(count);//3
//2.2优化之后
byte[] buf = new byte[3];//大小为3的缓存区
int count = 0;
while ((count = fis.read(buf)) != -1) {
System.out.print(new String(buf, 0, count)+" ");//abc def g
}
System.out.println();
//3.关闭
fis.close();
}
文件输出流代码演示:
public static void main(String[] args) throws Exception {
/*
* 演示FileOutputStream的使用
* 文字字节输出流
*/
//1.创建文件字节输出流并指定文件路径,append=true时,可进行追加,不然会覆盖
FileOutputStream fos =new FileOutputStream("E:\\newstart\\linshi\\bbb.txt",true);
//2.写入文件
//单个写入
String str = "hello world";
fos.write(str.getBytes());
//3.关闭
fos.close();
System.out.println("执行完毕");
}
3.2 文件复制案例
代码演示:
public static void main(String[] args) throws Exception {
//文件的复制
//1.创建流
//输入流
FileInputStream fis = new FileInputStream("路径\\aaa.txt");
//输出流
FileOutputStream fos = new FileOutputStream("路径\\bbb.txt");
//2.一边读一边写
byte[] buf = new byte[1024];
int count = 0;
while((count = fis.read(buf)) != -1){
fos.write(buf, 0, count);
}
//3.关闭
fis.close();
fos.close();
System.out.println("copy完毕");
}
3.3 字节缓冲流
缓冲流:BufferedInputStream/ BufferedOutputStream
- 提高IO效率,减少访问磁盘次数
- 数据存储在缓冲区中,flush是将缓冲区的内容写入文件中,也可以直接close
代码演示:
public static void main(String[] args) throws Exception {
/**
* 使用字节缓冲流读取
* BufferedInputStream
*/
//1.创建BufferedInputStream
FileInputStream fis = new FileInputStream("E:\\newstart\\linshi\\aaa.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
//2.读取
//方法1(推荐)
// int data = 0;
// while ((data = bis.read()) != -1){
// System.out.print((char)data);
// }
//方法2
byte[] buf = new byte[1024];
int count = 0;
while((count = bis.read(buf)) != -1){
System.out.println(new String(buf,0, count));
}
//3.关闭
bis.close();
}
代码演示:
public static void main(String[] args) throws Exception {
/**
* 使用字节缓冲流写入数据
* BufferedOutputStream
*/
//1.创建字节输出缓冲流
FileOutputStream fos =new FileOutputStream("E:\\newstart\\linshi\\bbb.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
//2.写入文件
for (int i = 0; i < 10; i++) {
bos.write("helloword\r\n".getBytes());//写入8k缓冲区
bos.flush(); // 刷新到硬盘 如果不flush(),关闭流之后也可以显示,但是刷新可以防止数据丢失
}
//3.关闭(内部调用flush方法)
bos.close();
}
4 对象流
ObjectOutputStream / ObjectInputStream
- 增强了缓冲区功能
- 增强了读写8种基本数据类型和字符串的功能
- 增强了读写对象的功能
readObject()从流中读取一个对象writeObject(Object obj)向流中写入一个对象
使用流传输对象的过程称为序列化、反序列化
理解:从内存写入文件到硬盘的过程称之为序列化,反之为反序列化。
4.1 序列化
代码演示:
public static void main(String[] args) throws Exception {
/**
* 使用ObjectOutputStream实现对象的序列化
* 要求:序列化的类必须实现Serializable接口,标记为可序列化的状态
*/
//1.创建对象流
FileOutputStream fos = new FileOutputStream("E:\\newstart\\linshi\\stu.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
//2.序列化(写入操作)
Student zs = new Student("张三", 20);
oos.writeObject(zs);
//3.关闭
oos.close();
System.out.println("序列化完毕");
}
4.2 反序列化
代码演示:
public static void main(String[] args) throws Exception {
/**
* 使用ObjectInputStream实现对象的反序列化(读取重构对象)
*/
//1.创建对象流
FileInputStream fis = new FileInputStream("E:\\newstart\\linshi\\stu.bin");
ObjectInputStream ois = new ObjectInputStream(fis);
//2.读取文件(反序列化)
Student stu = (Student) ois.readObject();
//3.关闭
ois.close();
System.out.println("反序列化完毕");
System.out.println(stu.toString());//Student{name='张三', age=20}
}
4.3 注意事项
- 某个类要想序列化必须实现Serializable接口
- 序列化类中对象属性要求实现Serializable接口
- 序列化版本号ID:
serialVersionUID,保证序列化的类和反序列化的类是同一个类 - 使用
transient(瞬间的)修饰属性,这个属性就不能序列化 - 静态属性不能序列化
- 序列化多个对象,可以借助集合来实现
注:序列化版本号ID定义:private static final long serialVersionUID = 100L;
5 字符编码
- IS0-8859-1:收录除ASCII外,还包括西欧、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号。
- UTF-8:针对Unicode码表的可变长度字符编码
- GB2312:简体中文
- GBK:简体中文、扩充
- BIG5:台湾,繁体中文
注:编码方式和解码方式不一致时,会出现乱码。
6 字符流
代码演示:
public static void main(String[] args) throws Exception {
/**
* 传统字节流读取
*/
//1.创建FileInputStream对象
FileInputStream fis = new FileInputStream("E:\\newstart\\linshi\\hello.txt");
//2.读取
int data = 0;
while((data = fis.read()) != -1){//12个字节 4个汉字
System.out.print((char)data);
}
//3.关闭
fis.close();
}
6.1 字符流的父类
reader 字符输入流
public int read(){}public int read(char[] c){}public int read(char[] b, int off, int len){}
Writer 字符输出流
public void write(int n){}public void write(String str){}public void write(char[] c){}
6.2 FileReader
文件字符输入流代码演示:
public static void main(String[] args) throws Exception {
/**
* 使用FileReader读取文件
*/
//1.创建FileReader 文件字符输入流
FileReader fr = new FileReader("E:\\newstart\\linshi\\hello.txt");
//2.读取
//2.1单个字符读取
// int data = 0;
// while ((data = fr.read()) !=-1){//读取一个字符
// System.out.print((char)data);
// }
//2.2字符缓冲区读取
char[] buf = new char[1024];//2的话一个2个字符
int count = 0;
while ((count = fr.read(buf)) != -1){
System.out.println(new String(buf, 0, count));
}
//3.关闭
fr.close();
}
6.3 FileWriter
文件字符输出流代码演示:
public static void main(String[] args) throws Exception {
/**
* 使用FileWriter写入文件
*/
//1.创建FileWriter 文件字符输出流
FileWriter fw = new FileWriter("E:\\newstart\\linshi\\writer.txt");
//2.写入
for (int i = 0; i < 10; i++) {
fw.write("java是世界上最好的语言\r\n");
fw.flush();
}
//3.关闭
fw.close();
System.out.println("执行完毕");
}
6.4 文本文件复制(案例)
使用FileReader和FileWriter不能复制图片或二进制文件,使用字节流可以复制任意文件
代码演示:
public static void main(String[] args) throws Exception {
//1.创建
FileReader fr = new FileReader("E:\\newstart\\linshi\\writer.txt");
FileWriter fw = new FileWriter("E:\\newstart\\linshi\\w.txt");
//2.读写
int data = 0;
while ((data = fr.read()) != -1){
fw.write(data);
fw.flush();
}
//3.关闭
fr.close();
fw.close();
System.out.println("copy完毕");
}
6.5 字符缓冲流
BufferedReader / BufferedWriter
高效读写、支持输入换行符、可一次写一行读一行
代码演示:
public static void main(String[] args) throws Exception {
/**
* 使用字符缓冲流读取文件
* BufferdReader
*/
//1.创建缓冲流
FileReader fr = new FileReader("E:\\newstart\\linshi\\writer.txt");
BufferedReader br = new BufferedReader(fr);
//2.读取
//2.1 第一种方式
char[] buf = new char[1024];
int count = 0;
while((count = br.read(buf)) != -1){
System.out.print(new String(buf, 0, count));
}
//2.2 第二种方式 一行一行读
String line = null;
while((line = br.readLine()) != null){
System.out.print(line);
}
//3.关闭
br.close();
}
代码演示:
public static void main(String[] args) throws Exception {
/**
* 使用字符缓冲流写入文件
* BufferedWriter
*/
//1.创建缓冲流
FileWriter fw = new FileWriter("E:\\newstart\\linshi\\buf.txt");
BufferedWriter bw = new BufferedWriter(fw);
//2.写入
for (int i = 0; i < 10; i++) {
bw.write("好好学习。");
bw.newLine();//写入一个换行符
bw.flush();
}
//3.关闭
bw.close();
System.out.println("执行完毕");
}
7 打印流
7.1 PrintWriter
封装了print() / println() 方法 支持写入后换行
支持数据原样打印
代码演示:
public static void main(String[] args) throws Exception {
/**
* 演示PrintWriter的使用
*/
//1.创建一个打印流
PrintWriter pw = new PrintWriter("E:\\newstart\\linshi\\print.txt");
//2.打印
pw.println(97);
pw.println(true);
pw.println(3.14);
pw.println("你好nihao");
//3.关闭
pw.close();
System.out.println("执行完毕");
}
8 转换流
桥转换流 InputStreamReader / OutputStreamWriter
可将字节流转换为字符流
可设置字符的编码方式,通常使用UTF-8,文件另存为ANSI就是gbk
代码演示:
public static void main(String[] args) throws Exception {
/**
* 使用InputStreamReader读取文件 指定使用的编码
*/
//1.创建InputStreamReader对象
FileInputStream fis = new FileInputStream("E:\\newstart\\linshi\\writer.txt");
InputStreamReader isr = new InputStreamReader(fis, "utf-8");
//2.读取文件
int data = 0;
while ((data = isr.read()) != -1){
System.out.print((char)data);
}
//3.关闭
isr.close();
}
代码演示:
public static void main(String[] args) throws Exception {
/**
* 使用OutputStreamWriter 写入文件 指定使用的编码
*/
//1.创建OutputStreamWriter对象
FileOutputStream fos = new FileOutputStream("E:\\newstart\\linshi\\writer.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos, "utf-8");
//2.写入文件
for (int i = 0; i < 10; i++) {
osw.write("我爱北京\r\n");
osw.flush();
}
//3.关闭
fos.close();
System.out.println("执行完毕");
}
9 File类
概念:代表物理盘符中的一个文件或者文件夹
9.1 四个常量
1.public static final char separatorChar;
与系统有关的默认名称分隔符。
此字段被初始化为包含系统属性file.separator 值的第一个字符。在 UNIX 系统上,此字段的值为 '/';在 Microsoft Windows 系统上,它为 '\\'。
2.public static final String separator;
与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串。
此字符串只包含一个字符,即 separatorChar。
3.public static final char pathSeparatorChar;
与系统有关的路径分隔符。
此字段被初始为包含系统属性 path.separator 值的第一个字符。此字符用于分隔以路径列表 形式给定的文件序列中的文件名。在 UNIX 系统上,此字段为 ':';在 Microsoft Windows 系统上,它为 ';'。
4.public static final String pathSeparator;
与系统有关的路径分隔符,为了方便,它被表示为一个字符串。
此字符串只包含一个字符,即 pathSeparatorChar。
9.2 常用方法
- 获取文件或目录的详细信息
String getName(): 返回由此抽象路径名表示的文件或目录的名称。
long length() : 返回由此抽象路径名表示的文件的长度。(只能返回文件大小,不能直接返回目录大小)
boolean exists() : 判断此抽象路径名表示的文件或目录是否存在。
boolean isHidden() : 判断此抽象路径名指定的文件是否是一个隐藏文件。
boolean canRead() : 判断应用程序是否可以读取此抽象路径名表示的文件。
boolean canWrite() : 判断应用程序是否可以修改此抽象路径名表示的文件
long lastModified() : 返回此抽象路径名表示的文件最后一次被修改的时间。(毫秒值)
String toString() : 返回此抽象路径名的路径名字符串。boolean isAbsolute(): 测试File对象对应的文件或目录是否是绝对路径。
String getParent() : 返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null。(返回父目录名称)
File getParentFile() :返回此抽象路径名父目录的抽象路径名;如果此路径名没有指定父目录,则返回 null。(返回父目录的File对象)
- 获取文件或目录的路径
String getPath() : 将此抽象路径名转换为一个路径名字符串。
File getAbsoluteFile() : 返回此抽象路径名的绝对路径名形式。
String getAbsolutePath():返回此抽象路径名的绝对路径名字符串。 返回绝对路径,从根目录开始导航
File getCanonicalFile(): 返回此抽象路径名的规范形式。
String getCanonicalPath() :返回此抽象路径名的规范路径名字符串。规范路径就是路径里没有./或../或/,会把这些自动解析
- 操作文件或目录
boolean createNewFile():当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。(只创建文件)
boolean delete(): 删除此抽象路径名表示的文件或目录。(可以删除文件或删除空目录)删除成功,返回true,失败false。
boolean equals(Object obj):判断此抽象路径名与给定对象是否相等。
boolean mkdir() : 创建此抽象路径名指定的目录。(只能创建一级目录)必须确保父目录存在,否则创建失败。
boolean mkdirs(): 创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。 (可以创建多级目录)如果父目录不存在,会一同创建父目录
boolean renameTo(File dest) :重新命名此抽象路径名表示的文件。(可以给文件或目录重命名)
- 判断是文件还是目录
boolean isFile() :判断此抽象路径名表示的文件是否是一个标准文件。
boolean isDirectory():判断此抽象路径名表示的文件是否是一个目录。
- 获取目录的下一级
String[] list() :返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。
File[] listFiles() :返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。(获取下一级的文件/目录的File对象)
static` `File[] listRoots():列出可用的文件系统根。
9.3 案例(基本以及FileFilter过滤器)
代码演示:
public static void main(String[] args) throws Exception {
/**
* File类的使用
* (1)分隔符
* (2)文件操作
* (3)文件夹操作
*/
// separator();
// fileOpe();
directoryOpe();
}
//(1)分隔符
public static void separator(){
System.out.println("路径分隔符" + File.pathSeparator);//;
System.out.println("名称分隔符" + File.separator);//\
}
//(2)文件操作
public static void fileOpe() throws Exception {
//1.创建文件
File file = new File("E:\\newstart\\linshi\\file\\file.txt");
// System.out.println(file.toString());//E:\newstart\linshi\file\file.txt
if(!file.exists()){//判断是否存在
boolean b = file.createNewFile();
System.out.println("创建结果:" + b);
}
//2.删除文件
//2.1直接删除
// boolean delres = file.delete();
// System.out.println("删除结果:"+delres);
//2.2使用jvm退出时删除
// file.deleteOnExit();
// Thread.sleep(5000);//休眠5秒,方便看效果
//3.获取文件信息
System.out.println("获取文件的绝对路径:" + file.getAbsolutePath());
System.out.println("获取路径:" + file.getPath());
System.out.println("获取文件名称:" + file.getName());
System.out.println("获取父目录:" + file.getParentFile());
System.out.println("获取文件长度:" + file.length());//汉字占3个
System.out.println("文件创建时间:" + new Date(file.lastModified()).toLocaleString());//lastModified()默认是long类型
//4.判断
System.out.println("是否可写:" + file.canWrite());
System.out.println("是否是文件:" + file.isFile());
System.out.println("是否是隐藏:" + file.isHidden());
}
//(3)文件夹操作
public static void directoryOpe() throws Exception {
//1.创建文件夹
File dir = new File("E:\\newstart\\linshi\\file1");
System.out.println(dir.toString());
if(!dir.exists()){
dir.mkdirs();//mkdir()只能创建单级目录
}
//2.删除文件夹
//2.1直接删除
// boolean delres = dir.delete();//只能删除空目录
// System.out.println("删除结果:"+delres);
//2.2使用jvm退出时删除
// dir.deleteOnExit();
// Thread.sleep(5000);//休眠5秒,方便看效果
//3.获取文件信息
System.out.println("获取文件夹的绝对路径:" + dir.getAbsolutePath());
System.out.println("获取文件夹路径:" + dir.getPath());
System.out.println("获取文件夹名称:" + dir.getName());
System.out.println("获取父目录:" + dir.getParentFile());
System.out.println("文件夹创建时间:" + new Date(dir.lastModified()).toLocaleString());//lastModified()默认是long类型
//4.判断
System.out.println("是否是文件夹:" + dir.isDirectory());
System.out.println("是否是隐藏:" + dir.isHidden());
//5.遍历文件夹
File dir2 = new File("E:\\newstart\\linshi");
String[] files = dir2.list();//listFiles()返回File类型,list返回String类型
for (String file : files) {
System.out.println(file);
}
//FileFilter接口的使用(文件过滤器)
System.out.println("--------FileFilter接口的使用--------");
File[] files2 = dir2.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
if (pathname.getName().endsWith(".png")) {
return true;
}
return false;
}
});
for (File file : files2) {
System.out.println(file.getName());
}
}
9.4 递归遍历
代码演示:
//案例1 递归遍历文件夹
public static void listDir(File dir) throws Exception {
File[] files = dir.listFiles();
System.out.println(dir.getAbsoluteFile());
if(files != null && files.length > 0) {
for (File file : files) {
if(file.isDirectory()) {
listDir(file);
}else{
System.out.println(file.getAbsolutePath());
}
}
}
}
9.5 递归删除
代码演示:
//案例2 递归删除文件夹
public static void delDir(File dir) throws Exception {
File[] files = dir.listFiles();
if(files != null && files.length > 0) {
for (File file : files) {
if(file.isDirectory()) {
delDir(file);
}else{
System.out.println(file.getAbsolutePath()+"删除:"+file.delete());
}
}
}
System.out.println(dir.getAbsolutePath()+"删除:"+dir.delete());//删除文件夹
}
10 Properties
集合中提到过
Properties:属性集合,继承hashtable,线程安全
特点:
- 存储属性名和属性值
- 属性名和属性值都是字符串类型
- 没有泛型
- 和流有关
代码演示:
public static void main(String[] args) throws Exception {
/**
* 演示Properties集合的使用
*/
//1.创建集合
Properties properties = new Properties();
//2.添加元素
properties.setProperty("name", "张三");
properties.setProperty("age", "20");
System.out.println(properties.toString());
//3.删除 remove() clear()
//4.遍历
//4.1 keySet
//4.2 entrySet
//4.3 stringPropertyNames()
Set<String> strings = properties.stringPropertyNames();
for (String string : strings) {
System.out.println(string+":"+properties.getProperty(string));
}
//5.和流有关的方法
//5.1 list()
// PrintWriter pw = new PrintWriter("E:\\newstart\\linshi\\print.txt");
// properties.list(pw);
// pw.close();
//5.2 store() 保存
//可以使用FileOutputStream和FileInputStream(中文乱码会乱码),也可以使用FileWriter和FileReader(中文不乱码)
// FileWriter fw = new FileWriter("E:\\newstart\\linshi\\print.propertes");
// properties.store(fw,"注释");
// fw.close();
//5.3 load() 加载
Properties properties2 = new Properties();
FileReader fr = new FileReader("E:\\newstart\\linshi\\print.propertes");
properties2.load(fr);
fr.close();
System.out.println(properties2.toString());
}
总结
流的概念:
- 内存与存储设备之间传输数据的通道。
流的分类:
- 输入流、输出流;字节流、字符流;节点流、过滤流;
序列化、反序列化:
- 将对象通过流写入到文件,或将对象通过流读取到内存,必须实现Serializable接口。
File对象:
- 代表物理盘符中的一个文件或者文件夹。

浙公网安备 33010602011771号