I/O框架
流

流的分类:
按方向:
-
输入流:将存储设备的内容读入到内存中
-
输出流:将内存的内容写入到存储设备中
按单位:
-
字节流:以字节为单位,可以读取所有数据
-
字符流:以字符为单位,只能读写文本数据
按功能:
-
节点流:具有实际传输数据的读写功能
-
过滤流:在节点流的基础之上的增强功能
字节流
-
InputStream:字节输入流
-
OutputStream:字节输出流
文件字节流
FileInputStream
package com.fileIO.demo01;
import java.io.FileInputStream;
import java.io.IOException;
/*
* FileInputStream的使用
* 文件字节输入流
*
* */
public class Demo01 {
public static void main(String[] args) throws IOException {
//1.创建FileInputStream
FileInputStream fis = new FileInputStream("C:\\c_learning\\javaDemo01.txt");
//2.读取文件
//2.1单个字节读取
//fis.read(); //一个字节一个字节读
//
// int data = 0;
// while( (data = fis.read()) != -1 ) {
// System.out.print((char)data); //强制转换,data是int类型,返回ASCII
// }
//2.2 一次读取多个字节
byte[] buffer = new byte[1024];
int count = 0;
while ((count = fis.read(buffer)) != -1 ) {
System.out.println(new String(buffer, 0, count)); //0指的是从角标为0开始读
}
//3.关闭
fis.close();
System.out.println("\n执行结束");
}
}
FileOutputStream
package com.fileIO.demo01;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 演示文件字节输出流
* FileOutputStream
*
* */
public class Demo02 {
public static void main(String[] args) throws IOException {
//1.创建文件字节输出流对象
FileOutputStream fos = new FileOutputStream("C:\\c_learning\\javaDemo02.txt",true); //文件名后面加true,就能无限追加,执行两次,文件里就有两个abcHello world
//2.写入文件
fos.write(97); //写入a
fos.write('b'); //写入b
fos.write('c'); //写入c
String string = "Hello World";
fos.write(string.getBytes()); //getByte()获取字符串对应的字节数组
//3.关闭
fos.close();
System.out.println("执行完毕");
}
}
文件复制
package com.fileIO.demo01;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 使用文件字节流实现文件的复制,图片,视频都行
*
* */
public class Demo03 {
public static void main(String[] args) throws IOException {
//1.创建流
//1.1文件字节输入流
FileInputStream fis = new FileInputStream("C:\\c_learning\\javaDemo01.txt");
//1.2文件字节输出流
FileOutputStream fos = new FileOutputStream("C:\\c_learning\\javaDemo03.txt");
//2.一边读一边写
byte[] buffer = new byte[1024];
int count = 0;
while ((count = fis.read(buffer)) != -1) {
fos.write(buffer, 0, count);
}
//3.关闭
fis.close();
fos.close();
System.out.println("复制完毕");
}
}
字节缓冲流
-
缓冲流:BufferedInputStream/BufferedOutputStream
-
提高IO效率,减少访问磁盘的次数
-
数据存储在缓冲区中,flush是将缓冲区的内容写入文件中,也可以直接close
-
BufferedInputStream
package com.fileIO.demo01;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
/*
* 使用字节缓冲流读取
* BufferedInputStream
* */
public class Demo04 {
public static void main(String[] args) throws IOException {
//1.创建BufferedInputStream需要有节点流文件输入流就是一个节点流
FileInputStream fis = new FileInputStream("C:\\c_learning\\javaDemo01.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
//2.读取
int data = 0;
while ((data = bis.read()) != -1) {
System.out.print((char) data);
}
//3.关闭
bis.close();
}
}
BufferedOutputStream
package com.fileIO.demo01;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 使用字节缓冲流写入
* BufferedOutputStream
* */
public class Demo05 {
public static void main(String[] args) throws IOException {
//1.创建BufferedOutputStream
FileOutputStream fos = new FileOutputStream("C:\\c_learning\\buffer.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
//2.读取
for (int i = 0; i < 10; i++) {
bos.write("hello".getBytes()); //写入8k缓冲区
bos.flush(); //刷新到硬盘 防止数据丢失
}
//3.关闭
bos.close(); //close内部有flush方法
System.out.println("执行完毕");
}
}
对象流
-
增强了缓冲区功能
-
增强了读写8种基本类型数据和字符串功能
-
增强读写对象的功能
-
使用传输对象的过程为序列化、反序列化
序列化
package com.fileIO.demo02;
import java.io.Serializable;
/*
* 学生类
* */
public class Student implements Serializable { //该接口是标记接口什么内容都没有
//private static final long serialVersionUID = 100L; //serialVersionUID:序列化版本号ID 要保证序列化的和反序列化的一致
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
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 +
'}';
}
}
package com.fileIO.demo02;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
/*
* 使用ObjectOutputStream实现对象的序列化
*要求:序列化的类必须要实现Serializable
* */
public class Demo01 {
public static void main(String[] args) throws Exception {
//1.创建对象流
FileOutputStream fos = new FileOutputStream("c:\\c_learning\\stu.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
//2.序列化(写入操作)
Student s1 = new Student("Tom",1);
oos.writeObject(s1);
//3.关闭
oos.close();
System.out.println("序列化完毕");
//报错:NotSerializableException 要实现Serializable接口
}
}
反序列化
package com.fileIO.demo02;
import java.io.Serializable;
/*
* 学生类
* */
public class Student implements Serializable { //该接口是标记接口什么内容都没有
//private static final long serialVersionUID = 100L; //serialVersionUID:序列化版本号ID 要保证序列化的和反序列化的一致
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
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 +
'}';
}
}
package com.fileIO.demo02;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
/*
* 使用ObjectInputStream(读取重构成对象)
*
* */
public class Demo02 {
public static void main(String[] args) throws Exception {
//1.创建对象流
FileInputStream fis = new FileInputStream("c:\\c_learning\\stu.bin");
ObjectInputStream ois = new ObjectInputStream(fis);
//2.读取文件(反序列化)
Student s = (Student) ois.readObject();
//Student s2 = (Student) ois.readObject(); 读两个就会异常:EOFException
//3.关闭
ois.close();
System.out.println("执行完毕");
System.out.println(s);
}
}
注意事项
-
序列化类必须要实现Serializable接口
-
序列化类中对象属性必须要实现Serializable接口如private Address ad; Address就要实现接口
-
序列化版本ID,保证序列化的和反序列化的是同一个类,如果在序列化的时候没有加序列化版本ID(系统就会给一个默认的值),反序列化的时候加了自定义的且不和系统默认的一样就报错 解决方法就是重新序列化 再 反序列化
-
使用transient关键字(瞬间的)修饰属性 使其无法被序列化 如:private transient int age;
-
静态属性不能序列化 如public static String country = "China";
-
序列化多个对象 再反序列化时就能写Student s2 = (Student)ois.readObject(); 还能优化一下 使用集合来实现
package com.fileIO.demo02;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
/*
* 使用ObjectOutputStream实现对象的序列化
*要求:序列化的类必须要实现Serializable
* */
public class Demo01 {
public static void main(String[] args) throws Exception {
//1.创建对象流
FileOutputStream fos = new FileOutputStream("c:\\c_learning\\stu.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
//2.序列化(写入操作)
Student s1 = new Student("Tom",1);
Student s2 = new Student("Jack",2);
ArrayList<Student> students = new ArrayList<Student>();
students.add(s1);
students.add(s2);
oos.writeObject(students);
//3.关闭
oos.close();
System.out.println("序列化完毕");
//报错:NotSerializableException 要实现Serializable接口
}
}
package com.fileIO.demo02;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;
/*
* 使用ObjectInputStream(读取重构成对象)
*
* */
public class Demo02 {
public static void main(String[] args) throws Exception {
//1.创建对象流
FileInputStream fis = new FileInputStream("c:\\c_learning\\stu.bin");
ObjectInputStream ois = new ObjectInputStream(fis);
//2.读取文件(反序列化)
// Student s = (Student) ois.readObject();
//Student s2 = (Student) ois.readObject(); 读两个就会异常:EOFException
ArrayList<Student> students = (ArrayList<Student>) ois.readObject();
//3.关闭
ois.close();
System.out.println("执行完毕");
System.out.println(students);
}
}
字符流
当我们使用字节流的方式去读取文件,如果文件内容是中文,就会出现乱码 因为txt里面汉字是UTF-8 一个汉字3个字节,一个一个字节读当然就是乱码了
文件字符流
FileReader
package com.fileIO.demo03;
import java.io.FileReader;
import java.io.IOException;
/*
*
* FileReader读取文件
* */
public class Demo01 {
public static void main(String[] args) throws IOException {
//1.创建FileReader 文件字符输入流
FileReader fr = new FileReader("C:\\c_learning\\javaDemo01.txt");
//2.读取
//2.1单个字符
// int data = 0;
// while ((data = fr.read()) != -1) { //读取一个字符
// System.out.println((char) data);
// }
//2.2 使用字符缓冲区
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
package com.fileIO.demo03;
import java.io.FileWriter;
import java.io.IOException;
/*
* FileWriter写入文件
*
* */
public class Demo02 {
public static void main(String[] args) throws IOException {
//1.创键FileWriter对象
FileWriter fw = new FileWriter("c:\\c_learning\\writer.txt");
//写入方法
for (int i = 0; i < 10; i++) {
fw.write("java 是世界上最好的语言\n");
fw.flush();
}
fw.close();
System.out.println("Execution completed!");
}
}
复制文件
package com.fileIO.demo03;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* FileReader和FileWriter复制文本文件,不能复制图片或其他二进制文件 二进制文件变成字符就是一堆乱码(要字节流可以复制任意文件)
*
* */
public class Demo03 {
public static void main(String[] args) throws IOException {
//1.创建FileReader FileWriter
FileReader fr = new FileReader("C:\\c_learning\\writer.txt");
FileWriter fw = new FileWriter("C:\\c_learning\\writer2.txt");
//2.读写
int data = 0;
while ((data = fr.read()) != -1) {
fw.write(data);
fw.flush();
}
//3.关闭
fr.close();
fw.close();
System.out.println("Copy completed!");
}
}
字符缓冲流
BufferedReader
package com.fileIO.demo03;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
/*
* 使用字符缓冲流读取文件
* BufferedReader
*
* */
public class Demo05 {
public static void main(String[] args) throws IOException {
//创建缓冲流
FileReader fr = new FileReader("C:\\c_learning\\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.println(new String(buf,0, count));
// }
//2.2 一行一行读
String line =null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
//3.关闭
br.close();
}
}
BufferedWriter
package com.fileIO.demo03;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
/*
* BufferedWriter
*
*
* */
public class Demo04 {
public static void main(String[] args) throws IOException {
//1.创建BufferedWriter对象
FileWriter fw = new FileWriter("C:\\c_learning\\buffer.txt");
BufferedWriter bw = new BufferedWriter(fw);
//2.写入
for (int i = 0; i < 10; i++) {
bw.write("好好学习,天天向上");
bw.newLine(); //写入一个换行符 windows \r\n linux \n
bw.flush();
}
//3.关闭
bw.close();
System.out.println("Execution completed!");
}
}
打印流
package com.fileIO.demo04;
import java.io.IOException;
import java.io.PrintWriter;
/*
* PrintWriter的使用
*
*
* */
public class Demo01 {
public static void main(String[] args) throws IOException {
//1.创建打印流
PrintWriter pw = new PrintWriter("C:\\c_learning\\print.txt");
//2.打印
pw.println(97); //之前在字节流里是得到a
pw.println(true);
pw.println(3.14);
pw.println('a');
//3.关闭
pw.close();
}
}
转换流
-
桥转换流:InputStreamReader/OutputStreamWriter
-
可将字节流转换为字符流
-
可设置字符的编码方式
-
package com.fileIO.demo05;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
/*
*使用InputStreamReader 读取文件 指定使用的编码
*
*
* */
public class Demo01 {
public static void main(String[] args) throws IOException {
//1.创建InputStreamReader对象
FileInputStream fis = new FileInputStream("C:\\c_learning\\writer.txt");
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
//2.读取文件
int data = 0;
while ((data = isr.read()) != -1) {
System.out.print((char) data);
}
//3.关闭
fis.close();
}
}
package com.fileIO.demo05;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
/*
*使用OutputStreamWriter写入文件 指定编码
*
*
* */
public class Demo02 {
public static void main(String[] args) throws IOException {
//1.创建OutputStreamWriter
FileOutputStream fos = new FileOutputStream("C:\\c_learning\\info.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos, "gbk");
//2.写入
for (int i = 0; i < 10; i++) {
osw.write("我爱北京");
osw.flush();
}
//3.关闭
osw.close();
System.out.println("Execution completed!");
}
}
文件类
- 代表物理盘符中一个文件或者文件夹
文件类的使用
package com.fileIO.demo06;
import java.io.File;
import java.io.IOException;
import java.util.Date;
/*
* File类的使用
* 1.分隔符
* 2.文件操作
* 3.文件夹操作
* */
public class Demo01 {
public static void main(String[] args) throws IOException {
separator();
fileOperation();
directoryOperation();
}
//1.分隔符
public static void separator() {
System.out.println("路径分隔符"+ File.pathSeparator);
System.out.println("名称分割符"+ File.separator);
}
//2.文件操作
public static void fileOperation() throws IOException {
//1.创建文件
File file = new File("C:\\c_learning\\file.txt"); //如果不写成绝对路径形式只写file.txt就会在这个项创建
//System.out.println(file.toString());
if (!file.exists()) {
boolean b = file.createNewFile();
System.out.println("创建结果" + b); //不存在就创true 存在就不创false
}
//2.删除文件
//2.1 直接删除
//System.out.println("删除结果"+file.delete()); //删除true 没删除false
//2.2 jvm退出时删除
// file.deleteOnExit();
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// throw new RuntimeException(e);
// }
//3.获取文件信息
System.out.println("获取文件的绝对路径"+file.getAbsolutePath());
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()));
//4.判断
System.out.println("是否能写"+file.canWrite());
System.out.println("是否是文件"+file.isFile());
System.out.println("是否隐藏"+file.isHidden());
}
//3.文件夹操作
public static void directoryOperation(){
//1.创建文件夹
File dir = new File("C:\\aaa\\bbb\\ccc");
System.out.println(dir.toString());
if(!dir.exists()) {
//dir.mkdir(); //只能创建单级目录
System.out.println(dir.mkdirs()); //创建多级目录
}
//2.删除文件夹
//2.1直接删除(只能删除空目录)
//System.out.println("删除结果"+dir.delete()); //只删除最底层的,要求底层的是空目录
//dir.deleteOnExit();
//3.获取文件夹信息
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()));
//4.判断
System.out.println("是否是文件夹"+dir.isDirectory());
System.out.println("是否隐藏"+dir.isHidden());
//5.遍历文件夹
File dir2 = new File("C:\\c_learning");
String[] files = dir2.list();
for(String s : files) {
System.out.println(s);
}
}
}
FileFilter接口
在上面那个代码foreach循环后加上这串代码,实现只遍历后缀为txt的文件
System.out.println("--------------------------------FileFilter-----------------------------------------");
File[] file2 = dir2.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
if(pathname.getName().endsWith(".txt")) {
return true;
}
return false;
}
});
for (File file : file2) {
System.out.println(file.getName());
}
递归遍历和递归删除
package com.fileIO.demo06;
import java.io.File;
/*
*案例1:递归遍历文件夹
*案例2:递归删除文件夹
*
* */
public class listDemo {
public static void main(String[] args) {
listDir(new File("C:\\myFiles"));
deleteDir(new File("C:\\myFiles"));
}
//案例1:递归遍历文件夹
public static void listDir(File dir) {
File[] files = dir.listFiles();
System.out.println(dir.getAbsolutePath());
if (files != null && files.length > 0) {
for (File file : files) {
if (file.isDirectory()) {
listDir(file); //递归
}else {
System.out.println(file.getAbsolutePath());
}
}
}
}
//案例2:递归删除 只有文件夹是空的才能删掉文件夹
public static void deleteDir(File dir) {
File[] files = dir.listFiles();
if (files != null && 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
-
存储属性名和属性值
-
属性名和属性值都是字符串类型
-
没有泛型
-
和流有关
package com.fileIO.demo07;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Properties;
import java.util.Set;
/*
* Properties集合的使用
* */
public class Demo01{
public static void main(String[] args) throws IOException {
//1.创建集合
Properties prop = new Properties();
//2.添加数据
prop.setProperty("username", "Tom");
prop.setProperty("age", "20");
System.out.println(prop);
//3.遍历
//3.1keySet
//3.2entrySet
//3.3stringPropertyNames()
Set<String> proNames= prop.stringPropertyNames();
for (String pro : proNames) {
System.out.println(pro+"-------"+prop.getProperty(pro) );
}
//4.和流有关的方法
//4.1list
PrintWriter pw = new PrintWriter("C:\\c_learning\\printf.txt");
prop.list(pw);
pw.close();
//4.2store保存
FileOutputStream fos = new FileOutputStream("C:\\c_learning\\printf.properties");
prop.store(fos, "注释");
fos.close();
//4.3load加载
Properties prop2 = new Properties();
FileInputStream fis = new FileInputStream("C:\\c_learning\\printf.properties");
prop2.load(fis);
fis.close();
System.out.println(prop2);
}
}