I/O框架
流的概念
- 概念:内存与存储设备之间传输数据的通道。
流的分类
-
按方向【重点】
- 输入流:将<存储设备>中的内容读入到<内存>中。
- 输出流:将<内存>中的内容写入到<存储设备>中。
-
按单位
- 字节流:以字节为单位,可以读写所有数据
- 字符流:以字符为单位,只能读写文本数据
-
按功能
- 节点流:具有实际传输数据的读写功能。
- 过滤流:在节点流的基础之上增强功能。
字节流
字节流的父类(抽象类)
InputStream
OutPutStream
FilelnputStream的使用
- public int read(byte[] b) //从流中读取多个字节,将读到内容存入b数组,返回实际读到的字节数;如果达到文件的尾部,则返回-1。
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.String;
public class Demo06 {
public static void main(String[] args) throws IOException {
//1.创建FileInputStream,并指定文件路径
FileInputStream fis = new FileInputStream("D:\\aaa.txt");
//2.读取文件
//2.1单个字节读取
// int data = 0;
// //读完返回-1
// while ((data = fis.read()) != -1) {
// System.out.print((char) data);
// }
//2.2一次读取多个字节
byte[] buf = new byte[1024];
//count返回读取的长度
int count = fis.read(buf);
System.out.println(new String(buf, 0, count));
System.out.println(count);
//3.关闭
fis.close();
System.out.println("执行完毕");
}
}
/*
abcdefg
7
执行完毕
*/
File0utputStream的使用
- public void write(byte[] b) //一次写多个字节,将b数组中所有字节,写入输出流。
public class Demo07 {
public static void main(String[] args) throws IOException {
//1.创建文件字节输出流对象,ture的作用是如果已有内容,则追加,如果参数列表只有文件名,这会覆盖,而不是追加
FileOutputStream fos = new FileOutputStream("D:\\bbb.txt", true);
//2.写文件
fos.write(97);
fos.write(97);
fos.write('c');
String string = "helloworld";
fos.write(string.getBytes());
//3.关闭
fos.close();
System.out.println("执行完毕");
}
}
案例:文件复制
public class Demo08 {
public static void main(String[] args) throws IOException {
//1.创建流
//1.1 文件字节输入流
FileInputStream fis = new FileInputStream("D:\\001.jpg");
//1.2 文件字节输出流
FileOutputStream fos = new FileOutputStream("D:\\002.jpg");
//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("复制完毕");
}
}
字节缓冲流
-
缓冲流:BufferedInputStream/BufferedOutputStream
- 提高I0效率,减少访问磁盘的次数;
- 数据存储在缓冲区中,flush是将缓存区的内容写入文件中,也可以直接close(其中调用了flush)
-
BufferedInputStream
public class Demo09 { public static void main(String[] args) throws IOException { //1.创建BufferedInputStream FileInputStream fis = new FileInputStream("D:\\aaa.txt"); //相当于过滤流,增强节点流fis BufferedInputStream bis = new BufferedInputStream(fis); //2.读取 // int data = 0; // //bis里面其实已经有个缓冲区了,是先把一部分数据(8192byte)读入缓冲区,在一个字节一个字节的给data // while ((data = bis.read()) != -1) { // System.out.print((char) data); // } //也可以指定缓冲区 byte[] buf = new byte[1024]; int count = 0; while ((count = bis.read(buf)) != -1) { System.out.println(new String(buf, 0, count)); } //3.关闭,只关闭bis就行,带就把fis关了 bis.close(); System.out.println(); System.out.println("执行完毕"); } } /* abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefg 执行完毕 */
-
BufferedOutputStream
public class Demo10 { public static void main(String[] args) throws IOException { //1.创建字节输出缓冲流 FileOutputStream fos = new FileOutputStream("D:\\buffer.txt"); BufferedOutputStream bos = new BufferedOutputStream(fos); //2.写入文件 for (int i = 0; i < 10; i++) { bos.write("helloworld\n".getBytes());//写入8k缓冲区 bos.flush();//及时刷新到硬盘,避免数据丢失 } //3.关闭 bos.close(); System.out.println("输出完毕"); } }
对象流
-
对象流:0bjectOutputStream/0bjectInputStream
-
增强了缓冲区功能
-
增强了读写8种基本数据类型和字符串功能
-
增强了读写对象的功:
-
read0bject()从流中读取一个对象
-
write0bject(0bject obj)向流中写入一个对象编码方式
-
-
使用流传输对象的过程称为序列化(写文件)、反序列化(读取文件)
public class Test {
public static void main(String[] args) throws Throwable {
//1.创建对象流
FileOutputStream fos = new FileOutputStream("D:\\stu.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
//2.序列化(写入操作)
//注意,这里Student类要实现Serializable接口,用来标志该类可以序列号,否则报错
Student zhangsan = new Student("张三", 18);
oos.writeObject(zhangsan);
//3.关闭
oos.close();
System.out.println("序列化完毕");
//1.创建对象流
FileInputStream fis = new FileInputStream("D:\\stu.bin");
ObjectInputStream ois = new ObjectInputStream(fis);
//反序列化(读取操作)不能读多个
Student s = (Student) ois.readObject();
//3.关闭
ois.close();
System.out.println("反序列化完毕");
System.out.println(s);
}
}
/*
序列化完毕
反序列化完毕
Student{name='张三', age=18}
*/
序列化和反序列化注意事项
- 序列化类必须要实现Serializable接口
- 序列化类中对象属性(即对象的成员变量),这个类也要求实现Serializable接口
- 序列化版本号ID serialVersionUID,保证序列化的类和反序列化的类是同一个类,否则程序不认为是同一个类,会报错
- 使用transient(瞬间的,相对而言,序列化是持久的)修饰属性,这个属性不能序列化
- 静态属性不能被序列化
- 序列化多个对象,可以借助集合实现,也可以一个一个读,一个一个写,就是麻烦点
字符编码
- IS0-8859-1收录除ASCII外,还包括西欧、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号。
- UTF-8 针对Unicode码表的可变长度字符编码
- GB2312 简体中文
- GBK 简体中文、扩充
- BIG5 台湾,繁体中文
注意:当编码方式和解码方式不一致时,会出现乱码。
字符流
字符流的抽象类
案例
public class Demo16 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("D:\\hello.txt");
int data = 0;
//文件中为“你好世界”,12个字节4个汉字,而用字节流每个字节单独看,会产生乱码,这是要用到字符流
while ((data = fis.read()) != -1) {
System.out.print((char) data);
}
fis.close();
}
}
/*
ä½ å¥½ä¸ç
*/
- 字符流的父类(抽象类,即用子类实现功能)
- 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) {}
- Reader;字符输入流
文件字符流
- FileReader:
- publicint read(char[] c) //从流中读取多个字符,将读到内容存入c数组,返回实际读到的字符数;如果达到文件的尾部,则返回-1。
- FileWriter:
- public void write(String str) //一次写多个字符,将b数组中所有字符,写入输出流。
注意:使用FileReader和FileWriter复制文本文件,不能复制图片或二进制文件,因为图片是没有编码的,使用字符流读取写入会转码,会产生乱码,导致写入数据不一致。但使用字节流复制任意文件。
public class Demo17 {
public static void main(String[] args) throws IOException {
//1.创建FileReader 文件字符输入流
FileReader fr = new FileReader("D:\\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];
int count = 0;
while ((count = fr.read(buf)) != -1) {
System.out.println(new String(buf, 0, count));
}
//3.关闭
fr.close();
//1.创建FileWriter对象
FileWriter fw = new FileWriter("D:\\writerhello.txt");
for (int i = 0; i < 10; i++) {
// fw.write(buf);//也可以
fw.write("你好世界helloworld\n");
fw.flush();
}
fw.close();
}
}
/*
你好世界helloworld
*/
字符缓冲流
- 缓冲流:BufferedReader/BufferedWriter
- 高效读写
- 支持输入换行符。
- 可一次写一行、读一行。
public class Demo20 {
public static void main(String[] args) throws IOException {
//1.创建缓冲流
FileReader fr = new FileReader("D:\\writerhello.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;
// while ((line = br.readLine()) != null) {
// System.out.println(line);
// }
//3.关闭
br.close();
//1.创建缓冲流
FileWriter fw = new FileWriter("D:\\writerhello.txt");
BufferedWriter bw = new BufferedWriter(fw);
//2.写入
for (int i = 0; i < 10; i++) {
bw.write("好好学习,天天向上");
bw.newLine();
bw.flush();
}
//3.关闭
bw.close();
}
}
/*
你好世界helloworld
你好世界helloworld
你好世界helloworld
你好世界helloworld
你好世界helloworld
你好世界helloworld
你好世界helloworld
你好世界helloworld
你好世界helloworld
你好世界helloworld
*/
打印流
- PrintWriter:
- 封装了print()/println()方法,支持写入后换行,
- 支持数据原样打印
public class Demo22 {
public static void main(String[] args) throws IOException {
//1.创建打印流
PrintWriter pw = new PrintWriter("D:\\writerhello.txt");
//2.打印
//数据原样打印,不像字节流,输入97,打印出来是a,
pw.println(97);
pw.println(true);
pw.println(3.14);
pw.println('a');
//3.关闭
pw.close();
System.out.println("执行完毕");
}
}
/*文件内容
97
true
3.14
a
*/
转换流
- 桥转换流:InputStreamReader/OutputStreamWriter
- 可将字节流转换为字符流。需求,有点时候只提供字节流,而内容是字符流,常用于网络编程。
- 可设置字符的编码方式。
public class Demo24 {
public static void main(String[] args) throws IOException {
//1.创建InputStreamReader对象
FileInputStream fis = new FileInputStream("D:\\writerhello.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();
//1.创建InputStreamReader对象
FileOutputStream fos = new FileOutputStream("D:\\writerhello.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos, "gbk");
//2.写入
for (int i = 0; i < 10; i++) {
osw.write("成功!\n");
osw.flush();
}
//3.关闭
osw.close();
}
}
/*
打印输出
好好学习,天天向上 x10
文件内容
成功! x10
*/
File类
概述
- 概念:代表物理盘符中的一个文件或者文件夹。
- 方法:
- createNewFile() //创建一个新文件
- mkdir() //创建一个新目录
- delete() //删除文件或空目录
- exists() //判断File对象所对象所代表的对象是否存在
- getAbsolutePath() //获取文件的绝对路径
- getName()//取得名字
- getParent()//获取文件/目录所在的目录
- isDirectory()//是否是目录
- isFile()//是否是文件
- length()//获得文件的长度
- listFiles()//列出目录中的所有内容
- renameTo()//修改文件名为
文件操作
/**
*File类使用
* (1)分隔符
* (2)文件操作
* (3)文件夹操作
*/
public class Demo26 {
public static void main(String[] args) throws Exception {
System.out.println("路径分隔符:" + File.pathSeparator);//环境变量中的分号
System.out.println("名称分隔符:" + File.separator);//win中的/
File file = new File("file.txt");
// create(file);
// delete(file, 1);
// info(file);
}
//创建文件
public static void create(File file) throws Exception {
//如果不存在就创建
if (!file.exists()) {
boolean b = file.createNewFile();
System.out.println("创建结果:" + b);
} else {
System.out.println("文件已经存在");
}
}
//删除文件
public static void delete(File file, int i) throws InterruptedException {
if (i == 1) {
//2.1直接删除
System.out.println("删除结果:" + file.delete());
} else {
//2.2使用jvm退出时删除
file.deleteOnExit();
Thread.sleep(5000);
}
}
//获取文件信息
public static void info(File file) {
System.out.println("获取文件绝对路径:" + file.getAbsolutePath());//返回绝对路径,当只给文件名时,会在当前目录创建文件
System.out.println("获取路径:" + file.getPath());//file中写的什么路径就是什么路径
System.out.println("获取文件名称:" + file.getName());
System.out.println("获取父目录:" + file.getParent());
System.out.println("获取文件长度:" + file.length());
System.out.println("文件创建时间:" + new Date(file.lastModified()).toLocaleString());
System.out.println("是否可写:" + file.canWrite());
System.out.println("是否是文件:" + file.isFile());
System.out.println("是否隐藏:" + file.isHidden());
}
}
文件夹操作和FileFilter接口
public class Demo27 {
public static void main(String[] args) throws Exception {
File dir = new File("d:\\aaa\\bbb\\ccc");
// create(dir);
// delete(dir, 2);
// info(dir);
look(dir);
}
//创建文件夹
public static void create(File dir) throws Exception {
//如果不存在就创建
if (!dir.exists()) {
//只能创建单级目录
//System.out.println("创建结果:" + dir.mkdir());
//创建多久目录
System.out.println("创建结果:" + dir.mkdirs());
} else {
System.out.println("文件夹已经存在");
}
}
//删除文件夹
public static void delete(File dir, int i) throws InterruptedException {
//只能删除最深层的一个文件夹
if (i == 1) {
//2.1直接删除(如果目录中有文件,则会删除失败)
System.out.println("删除结果:" + dir.delete());
} else {
//2.2使用jvm退出时删除
dir.deleteOnExit();
Thread.sleep(5000);
}
}
//获取文件夹信息
public static void info(File dir) {
System.out.println("获取文件夹绝对路径:" + dir.getAbsolutePath());//返回绝对路径,当只给文件名时,会在当前目录创建文件
System.out.println("获取路径:" + dir.getPath());//file中写的什么路径就是什么路径
System.out.println("获取文件夹名称:" + dir.getName());
System.out.println("获取父目录:" + dir.getParent());
System.out.println("文件夹创建时间:" + new Date(dir.lastModified()).toLocaleString());
System.out.println("是否是文件夹:" + dir.isDirectory());
System.out.println("是否隐藏:" + dir.isHidden());
}
//遍历文件夹
public static void look(File dir) {
String[] files = dir.list();
for (String string : files) {
System.out.println(string);
}
System.out.println("-------------FileFilter接口-------------");
//也可以用listFiles()方法,直接获取File对象数组
//可以用FileFilter接口根据条件过滤出想要的文件给到File对象数组
File[] files1 = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
if (pathname.getName().endsWith(".jpg")) {
return true;
}
return false;
}
});
for (File file : files1) {
System.out.println(file.getName());
}
}
}
递归遍历和递归删除
public class Demo29 {
public static void main(String[] args) {
File dir = new File("d:\\aaa");
listDir(dir);
deleteDir(dir);
}
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());
}
}
}
}
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.print(file.getAbsolutePath());
System.out.println("删除:" + file.delete());
}
}
}
System.out.print(dir.getAbsolutePath());
System.out.println("删除:" + dir.delete());
}
}
本文作者:韩熙隐ario
本文链接:https://www.cnblogs.com/arioya/p/18684724
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· 单线程的Redis速度为什么快?
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码