流的分类
- 按方向
- 输入流:存储设备->内存
- 输出流:内存->存储设备
-
按单位
- 字节流:以字节为单位,可以读写所有数据
- 字符流:以字符为单位,只能读写文本数据(一个字符可能有好几个字节)
-
按功能
- 节点流:具有实际传输数据的读写功能
- 过滤流:在节点流的基础之上增强功能
字节流
InputStream
OutputStream
文件字节流
FileInputStream
-
一个字节一个字节地读取
//1.指定文件路径 FileInputStream fis = new FileInputStream("E:\\test.txt"); //2.一个字节一个字节地读取数据 int data=0; while((data=fis.read())!=-1){ System.out.print((char)data); } //3.关闭 fis.close();
-
一次读取多个字节
//1.指定文件路径 FileInputStream fis = new FileInputStream("E:\\test.txt"); //2.一次读取多个字节长度 int len = 0; byte[] buf = new byte[4]; while((len=fis.read(buf))!=-1){ System.out.print(new String(buf,0,len)); } //3.关闭 fis.close();
FileOutputStream
需要将字符串转为字节流再写入文件
getBytes()
FileOutputStream
构造方法的第二个参数为true
,则再文件末尾接着写入(不覆盖原有数据)
// 1. 指定文件路径
FileOutputStream fos = new FileOutputStream("E:\\a.txt");
//FileOutputStream fos = new FileOutputStream("E:\\a.txt",true);
// 2. 写入数据
fos.write(97); //写入字符‘a’
fos.write('b'); //写入字符‘b’
String str = "Hello FileOutputStream";
fos.write(str.getBytes()); //将字符串转为字节流写入文件
// 3. 关闭
fos.close();
案例:实现文件复制
// 1.文件字节输入
FileInputStream fis = new FileInputStream("E:\\photos\\head.jpg");
// 2.文件字节输出
FileOutputStream fos = new FileOutputStream("E:\\head.txt");
// 3.读写
byte[] buf = new byte[1024];
int count = 0;
while((count = fis.read(buf))!=-1){
fos.write(buf,0,count);
}
// 4.关闭
fos.close();
fis.close();
字节缓冲流
提高读取效率
BufferedInputStream
//1.创建BufferedInputStream
FileInputStream fis = new FileInputStream("E:\\test.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
//2.读取
int data = 0;
while((data=bis.read())!=-1){
System.out.print((char)data);
}
//3.关闭 关闭BufferedInputStream会自动关闭FileInputStream
bis.close();
BufferedOutputStream
先写到缓冲区,再写入内存设备
//1.创建BufferedOutputStream
FileOutputStream fos = new FileOutputStream("E:\\test.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
//2.写入缓冲区(缓冲区大小:8K)
for(int i=0;i<10;++i){
bos.write("hellow BufferedOutputStream\n".getBytes());
}
//3.写入硬盘
bos.flush();
//4.关闭
bos.close();
对象流
使用流传输对象的过程称为序列化、反序列化
注意事项:
- 被序列化的类必须实现
Serializable
接口 - 被序列化的类中的对象属性也必须实现
Serializable
接口 - 使用
transient
修饰的属性将不会被序列化,反序列化时该属性被赋值为默认值 - 静态属性不能被序列化
- 序列化多个对象可以使用集合
- 序列化版本号ID用于保证序列化和反序列化的类是同一个类
被序列化的类实现如下:
//实现Serializable接口才可序列化
public class Student implements Serializable {
//序列化版本号ID
private static final long serialVersionUID = 100L;
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
ObjectOutputStream
序列化
FileOutputStream fos = new FileOutputStream("E:\\student.dat");
ObjectOutputStream oos = new ObjectOutputStream(fos);
Student s1 = new Student("Jack",17);
oos.writeObject(s1);
oos.close();
ObjectInputStream
反序列化
FileInputStream fis = new FileInputStream("E:\\student.dat");
ObjectInputStream ois = new ObjectInputStream(fis);
Student s1 = (Student)ois.readObject();
ois.close();
System.out.println(s1);
字符流
仅能读写文本文件
Reader
Writer
文件字符流
类比文件字节流
FileReader
-
一次读取一个字符
FileReader fr = new FileReader("E:\\test.txt"); int data = 0; while((data=fr.read())!=-1){ System.out.print((char)data); } fr.close();
-
一次读取多个字符
FileReader fr = new FileReader("E:\\test.txt"); char[] buf = new char[1024]; int count = 0; while((count=fr.read(buf))!=-1){ System.out.print(new String(buf,0,count)); } fr.close();
FileWriter
FileWriter fw = new FileWriter("E:\\test.txt");
fw.write("你好");
fw.flush(); //刷新
fw.close();
案例:实现文件复制
只能复制文本文件
FileReader fr = new FileReader("E:\\test.txt");
FileWriter fw = new FileWriter("E:\\hhh.txt");
char[] buf = new char[1024];
int count = 0;
while((count=fr.read(buf))!=-1){
fw.write(buf,0,count);
fw.flush();
}
fw.close();
fr.close();
字符缓冲流
BufferedReader
FileReader fr = new FileReader("E:\\test.txt");
BufferedReader br = new BufferedReader(fr);
String data = null;
while((data=br.readLine())!=null){
System.out.println(data);
}
br.close();
BufferedWriter
FileWriter fw = new FileWriter("E:\\test.txt");
BufferedWriter bw = new BufferedWriter(fw);
for (int i=0;i<10;++i) {
bw.write("Hello BufferedWriter and BufferedReader");
bw.newLine(); //换行
bw.flush(); //将缓存写入文件
}
bw.close();
PrintWriter
PrintWriter pw = new PrintWriter("E:\\test.txt");
pw.println(97); //打印数字
pw.println(4.556);
pw.println('a'); //打印字符
pw.println("hello world");//打印字符串
pw.close();
转换流
字节流与字符流转换
InputStreamReader
是字节流通向字符流的桥梁
// 以utf-8编码方式读取
FileInputStream fis = new FileInputStream("E:\\test.txt");
InputStreamReader isr = new InputStreamReader(fis,"utf-8");
int data = 0;
while((data=isr.read())!=-1){
System.out.print((char)data);
}
isr.close();
OutputStreamWriter
是字符流通向字节流的桥梁
FileOutputStream fos = new FileOutputStream("E:\\test.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
for (int i = 0; i < 10; i++) {
osw.write("hello\n");
}
osw.close();
File类
代表物理盘符中的一个文件或文件夹
分隔符
-
路径分隔符:;
-
名称分隔符:\
System.out.println("路径分隔符:"+ File.pathSeparator); System.out.println("名称分隔符:"+ File.separator);
文件操作
// 1.创建文件对象
File file = new File("E:\\file.txt");
System.out.println(file.toString()); //打印文件路径
// 2.创建文件
if(!file.exists()){
boolean b = file.createNewFile();
System.out.println("创建结果:"+b);
}
// 3.删除文件
/// 3.1 直接删除
//file.delete(); //返回boolean
/// 3.2 JVM退出时删除
file.deleteOnExit();
Thread.sleep(3000); //休眠3秒便于观察
// 4.获取文件信息
System.out.println(file.getAbsoluteFile()); //绝对路径
System.out.println(file.getPath()); //获取创建文件对象时输入的路径
System.out.println(file.getName()); //获取文件名
System.out.println(file.getParent()); //父级名称
System.out.println(file.length()); //文件长度
System.out.println(new Date(file.lastModified()).toLocaleString());//创建时间
// 5.判断
System.out.println(file.canWrite()); //是否可写
System.out.println(file.isFile()); //是否是文件
System.out.println(file.isHidden()); //是否隐藏
文件夹操作
delete()
只能删除空文件夹(文件夹中不能有文件夹或者文件)
// 1. 创建文件夹对象
File dir = new File("E:\\test\\demo");
// 2. 创建文件夹
if(!dir.exists()){
//dir.mkdir(); //创建单级目录
System.out.println("创建结果:" + dir.mkdirs()); //创建多级目录
}
// 3. 删除文件夹 只能删除最底层的一级目录,而且该目录下不能有文件
/// 3.1 直接删除
//dir.delete();
/// 3.2 JVM关闭时删除
dir.deleteOnExit();
//Thread.sleep(3000);
// 4. 获取文件夹信息
System.out.println(dir.getAbsolutePath()); //绝对路径
System.out.println(dir.getPath()); //获取创建文件夹对象时输入的路径
System.out.println(dir.getName()); //文件夹名称
System.out.println(dir.getParent()); //父级目录
System.out.println(new Date(dir.lastModified()).toLocaleString());//创建时间
// 5. 判断
System.out.println(dir.isDirectory()); //是否是文件夹
System.out.println(dir.isHidden()); //是否隐藏
// 6. 遍历文件夹
File dir2 = new File("E://photos");
String[] filesName = dir2.list();
for(String str:filesName){
System.out.println(str);
}
FileFilter接口
实现FileFilter
接口的accept
方法可以实现对文件/文件夹的过滤
例:打印E:\photos下的所有jpg文件
File dir2 = new File("E://photos");
File[] files = dir2.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
if(pathname.getName().endsWith("jpg")){
return true;
}
return false;
}
});
for(File file : files){
System.out.println(file.getName());
}
案例1:递归遍历文件夹
public static void listDir(File dir){
File[] files = dir.listFiles();
if(files!=null && files.length>0){
for(File file : files){
if(file.isDirectory()){ //如果是文件夹,则递归遍历
listDir(file);
}
else{
System.out.println(file.getAbsolutePath());
}
}
}
else{
System.out.println("文件夹不存在或者为空文件夹");
}
}
案例2:递归删除文件夹
先删除文件夹中的文件再删除文件夹
public static void deleteDir(File dir){
File[] files = dir.listFiles();
if(files==null){
System.out.println("文件夹不存在");
return;
}
if(files.length>0){
for(File file : files){
if(file.isDirectory()){
deleteDir(file);
}
else{ //如果是文件,则直接删除
System.out.println("删除文件:"+file.getAbsolutePath()+" : "+file.delete());
}
}
}
//删除文件夹
System.out.println("删除文件夹:"+dir.getAbsolutePath()+" : "+dir.delete());
}
Properties属性集合
特点:
- 存储属性名和属性值
- 属性名和属性值都是字符串类型
- 和流有关
- 线程安全
Properties集合的基本使用
// 1.创建集合
Properties properties = new Properties();
// 2.添加数据
properties.setProperty("username","Jack");
properties.setProperty("age","21");
System.out.println(properties);
// 3.遍历
//可以使用keySet entrySet StringPropertyNames()遍历
Set<String> pronames = properties.stringPropertyNames();
for(String str:pronames){
System.out.println(str + " == "+properties.getProperty(str));
}
Properties集合与流有关的方法
- list方法
- store方法
- load方法
// list 列表
PrintWriter pw = new PrintWriter("E:\\print.txt");
properties.list(pw);
pw.close();
// store 保存
FileOutputStream fos = new FileOutputStream("E:\\print.properties");
properties.store(fos,"这里是注释");
fos.close();
// load 加载
Properties properties2 = new Properties();
FileInputStream fis = new FileInputStream("E:\\print.properties");
properties2.load(fis);
fis.close();
System.out.println(properties2);