IO流知识汇总
前导:IO流看起来比较多比较杂,但用法就那几样,记住怎么用就好,学习时注意各个流的继承关系。
含义
注意:站在程序的角度
I:In ,输入流,read读取(读取文件中的数据)
O:Out,输出流,writer写入(向文件里写入数据)
流:一点点的读取或者写入
IO流分类
按照方向分:输入流、输出流
按照单位分:字节流、字符流
按照功能分:节点流/基础流、处理流
File
File类在创建时(用构造方法时) 存的 只是一个目录路径或文件路径,实际就是一字符串,而不会去管你这个路径是不是存在的。
File类有创建目录、文件的方法,在用这些方法时才考虑路径是否存在。
1. File概述、构造方法
File :它是文件的目录路径名的抽象表示
- 文件和目录是可以通过File封装的
- 对于File而言,其封装的并不是一个真正的文件,仅仅是一个路径名而已。它可以是存在的,也可以是不存在的。将来是要通过具体的操作把这个路径的内容转换为具体存在的。
构造方法:
其构造方法有4种,这里只写了3种,具体查API
构造方法名 | 说明 |
---|---|
File(String pathname) | 通过将给定的路径名字字符串转换为抽象路径名来创建新的File实例 |
File(String parent, String child) | 从父路径名字符串和子路径名字符串创建新的File实例 |
File(File parent, String child) | 从父抽象路径名和子路径名字符串创建新的File实例 |
File f1 = new File("D:\\cat_vc\\Java.txt");
//文件路径中的"\\"有一个是转义字符,所以其实只有一个斜杠
System.out.println(f1);
File f2 = new File("D:\\cat_vc", "Java.txt");
File f3 = new File("D:\\cat_vc");
File f4 = new File(f3, "Java.txt");
2. File创建文件或目录
方法名 | 说明 |
---|---|
public boolean createNewFile() | 当具有该名称的文件不存在时,创建一个由该抽象路径命名的新空文件 |
public boolean mkdir() | 创建由此抽象路径命名的目录 |
public boolean mkdirs() | 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录 |
File f1 = new File("D:\\cat_vc\\Java.txt");
System.out.println(f1.createNewFile());
//文件目录不存在会报错
//目录存在--文件不存在,创建文件返回true
//目录存在--文件存在,不创建,返回false
File f2 = new File("D:\\cat_vc\\JavaSE");
System.out.println(f2.mkdir());
//目录不存在,创建目录返回true
//目录存在,不创建,返回false
//其父目录不存在不会报错,但也不会创建成功
File f3 = new File("D:\\cat_vc\\JavaWEB\\H5");
System.out.println(f3.mkdirs());
//创建目录,父目录不存在就补全
File f3 = new File("D:\\cat_vc\\JavaWEB\\H5\\java.txt");
System.out.println(f3.mkdirs());
//这玩意创建的java.txt是目录不是文件
3.File类的判断和获取功能
方法名 | 说明 |
---|---|
public boolean isDirectory() | 测试此抽象路径名表示的File是否为目录 |
public boolean isFile() | 测试此抽象路径名表示的File是否为文件 |
public boolean exists() | 测试此抽象路径名表示的File是否存在 |
public String getAbsolutePath() | 返回此抽象路径名的绝对路径名字符串 |
public String getPath() | 将此抽象路径名转换为路径名字符串 |
public String getName() | 返回由此抽象路径名表示的文件或目录的名称 |
public String[] list() | 返回此抽象路径名表示的目录中的文件和目录的名称字符串数组 |
public File[] listFiles() | 返回此抽象路径名表示的目录中的文件和目录的File对象数组 |
System.out.println("是否可读:"+file.canRead());
System.out.println("是否可写:"+file.canWrite());
System.out.println("是否隐藏:"+file.isHidden());
System.out.println("获取文件的长度(字节):"+ file.length());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("最后修改时间:" + sdf.format(file.lastModified()));
4. File删除功能
方法名 | 说明 |
---|---|
public boolean delete() | 删除由此抽象路径名表示的文件或目录 |
目录下如果还有文件或子目录是删除不掉该目录的,要删除一个大文件夹,要使用递归从最底层删起走
案例 – 创建文件
需求:在不知道父目录是否存在的情况下创建文件
File file = new File("D:\\cat_vc\\JavaWEB\\H5\\javaee.txt");
//获取父目录
File parentFile = file.getParentFile();
if(!parentFile.exists()){//文件夹不存在
parentFile.mkdirs();
}
file.createNewFile();
案例 – 删除文件夹
需求:删除一个文件夹下的所有内容(用递归完成)
准备:随便在哪儿复制一个大小100、200 M左右的文件夹,放在指定路径(自己设定,就删这玩意)
public static void main(String[] args) {
File file = new File("D:\\cat_vc");
method(file);
}
public static void method(File file){
File[] listFiles = file.listFiles();
for (File f : listFiles) {
if(f.isDirectory()){//文件夹
method(f);
f.delete();
}else if(f.isFile()){//文件
f.delete();
}
}
}
案例 – 输出文件夹下的所有.txt文件
public static void main(String[] args) {
File file = new File("D:\\cat_vc");
method(file, ".txt");
}
public static void method(File file,String str){
File[] listFiles = file.listFiles();
for (File f : listFiles) {
if(f.isDirectory()){//文件夹
method(f, str);
}else if(f.isFile()){//文件
String name = f.getName();
if(name.endsWith(str)){
System.out.println(name);
}
}
}
}
字节流
注意:所有的输入流,文件不存在就报错
该抛异常的抛异常,快捷键alt + enter
1. InputStream和OutputStream
字节流抽象基类
2. FileInputStream和FileOutputStream
文件字节输入输出流
FileInputStream extends InputStream;
FileOutputStream extends OutputStream
//创建流对象,覆盖写
FileOutputStream fos = new FileOutputStream("io.txt");//相对路径是写到项目路径下的
//追加写
//FileOutputStream fos = new FileOutputStream("io.txt",true);
//fos.write(97);//写入ASCII
//fos.write("123abc".getBytes());//写入字节数组
fos.write("123abc".getBytes(),2,3);//写入字节数组,偏移量,写入字节个数
//3.关流
fos.close();
FileInputStream fis = new FileInputStream("io.txt");
//int read = fis.read();//读取第一个字节,返回ASCII
//System.out.println(read);
//int read;
//while((read=fis.read()) != -1){//read()依次读取单个字节
// System.out.print((char)read);
//}
byte[] bs = new byte[1024];
int len;
while((len = fis.read(bs)) != -1){//一次读入字节数组长度,提高效率
System.out.println(new String(bs, 0, len));
}
//关流
fis.close();
3. FilterInputStream和FilterOutputStream
过滤器字节输入输出流,少用。
FilterInputStream extends InputStream;
FilterOutputStream extends OutputStream
4. BufferedInputStream和BufferedOutputStream
带有缓冲区的字节输入输出流,效率高。默认缓冲区大小:8192字节,8192字节是8KB。
BufferedInputStream extends InputStream;
BufferedOutputStream extends OutputStream
//使用默认的缓冲区(大小:8192个字节)
//BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("io.txt"));
//自定义长度的缓冲区(大小:10000个字节)
//BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("io.txt"), 10000);
//在文件末尾追加数据
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("io.txt",true));
bos.write("123abc".getBytes());
bos.close();
//默认缓冲区大小:8192个字节
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("io.txt"));
//自定义缓冲区大小:10000字节
//BufferedInputStream bis = new BufferedInputStream(new FileInputStream("io.txt"),10000);
byte[] bs = new byte[1024];
int len;
while((len = bis.read(bs)) != -1){
System.out.println(new String(bs, 0, len));
}
bis.close();
//try...catch的方式
//复制文件
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream("柯南小学生.mp4"));
bos = new BufferedOutputStream(new FileOutputStream("copy.mp4"));
byte[] bs = new byte[1024];
int len;
while((len = bis.read(bs)) != -1){
bos.write(bs, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(bis != null){
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bos != null){
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
字符流
1. Reader 和Writer
字符流的抽象基类
2. InputStreamReader 和OutputStreamWriter
字符输入输出转换流(字节流转换字符流)
应用场景:获取到的流是字节流,但是要去做字符操作
注意:使用转换流都加编码格式
InputStreamReader extends Reader;
OutputStreamWriter extends Writer
//OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("io.txt"));
//设置编码格式
//OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("io.txt"),"GBK");
//设置编码格式 + 在文件末尾追加内容
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("io.txt",true),"GBK");
//osw.write(97);//写入ASCII
//osw.write("柯南小可爱,皇冠给你带~~~");//写入字符串
//osw.write("柯南小可爱,皇冠给你带~~~", 2, 9);//写入字符串,偏移量,写入字符个数
//osw.write("柯南小可爱,皇冠给你带~~~".toCharArray());//写入字符数组
osw.write("柯南小可爱,皇冠给你带~~~".toCharArray(),2,9);//写入字符数组,偏移量,写入字符个数
osw.close();
//InputStreamReader isr = new InputStreamReader(new FileInputStream("io.txt"));
//设置编码格式
InputStreamReader isr = new InputStreamReader(new FileInputStream("io.txt"),"GBK");
//读取数据 一个字符一个字符的读取
//int read;
//while((read = isr.read()) != -1){
// System.out.println((char)read);
//}
char[] cs = new char[1024];
int len;
while((len = isr.read(cs)) != -1){
System.out.println(new String(cs, 0, len));
}
isr.close();
//拷贝文件
InputStreamReader isr = new InputStreamReader(new FileInputStream("小说.txt"), "GBK");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("copy.txt"), "GBK");
char[] cs = new char[1024];
int len;
while((len = isr.read(cs)) != -1){
osw.write(cs, 0, len);
}
isr.close();
osw.close();
3. FileReader 和FileWriter
文件字符输入输出流
FileReader extends InputStreamReader;
FileWriter extends OutputStreamWriter
//FileWriter fw = new FileWriter("io.txt");
//在文件末尾追加内容
FileWriter fw = new FileWriter("io.txt",true);
fw.write("柯南小可爱,皇冠给你带~~~".toCharArray());
fw.close();
FileReader fr = new FileReader("io.txt");
char[] cs = new char[1024];
int len;
while((len = fr.read(cs)) != -1){
System.out.println(new String(cs, 0, len));
}
fr.close();
//拷贝文件
FileReader fr = new FileReader("小说.txt");
FileWriter fw = new FileWriter("copy.txt");
char[] cs = new char[1024];
int len;
while((len = fr.read(cs)) != -1){
fw.write(cs, 0, len);
}
fr.close();
fw.close();
4. BufferedReader 和BufferedWriter
带有缓冲区的字符输入输出流,默认缓冲区大小:8192字符。
BufferedReader extends Reader;
BufferedWriter extends Writer
//默认缓冲区:8192字符 (FileWriter->BufferedWriter)
//BufferedWriter bw = new BufferedWriter(new FileWriter("io.txt"));
//自定义缓冲区:10000 (FileWriter->BufferedWriter)
//BufferedWriter bw = new BufferedWriter(new FileWriter("io.txt"),10000);
//在文件末尾追加 (FileWriter->BufferedWriter)
//BufferedWriter bw = new BufferedWriter(new FileWriter("io.txt",true));
//(FileOutputStream -> OutputStreamWriter -> BufferedWriter)
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("io.txt"), "GBK"));
bw.write("柯南小可爱,皇冠给你带~~~".toCharArray());
bw.close();
BufferedReader br = new BufferedReader(new FileReader("io.txt"));
//BufferedReader br = new BufferedReader(new FileReader("io.txt"),10000);
// (FileInputStream -> InputStreamReader -> BufferedReader)
//BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("io.txt"),
//读取数据 一行一行的读取
//String line;
//while((line = br.readLine()) != null){
// System.out.println(line);
//}
char[] cs = new char[1024];
int len;
while((len = br.read(cs)) != -1){
System.out.println(new String(cs, 0, len));
}
br.close();
BufferedReader br = new BufferedReader(new FileReader("小说.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("copy.txt"));
char[] cs = new char[1024];
int len;
while((len = br.read(cs)) != -1){
bw.write(cs, 0, len);
}
br.close();
bw.close();
BufferedReader br = new BufferedReader(new FileReader("小说.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("copy.txt"));
String line;
while((line = br.readLine()) != null){
bw.write(line);
bw.newLine();//换行
}
br.close();
bw.close();
各种流
对象流
ObjectInputStream 对象输入流
ObjectOutputStream 对象输入流
对象流最重要的用法就是用于存对象(存进去的东西,直接打开文件是看不懂的,取出来可以看懂就算成功)
扩展:
序列化概念:
序列化:将程序中的对象写入到文件中 — 钝化
反序列化:将文件中的对象读取到程序中 — 活化
一个类的对象要想通过对象流写入到文件中,该类就必须实现序列化接口(Serializable)
Serializable叫做序列化接口,该接口没有让我们去实现任何的方法,这种接口叫做标记型接口
transient修饰属性后,该属性不会随着对象写入到文件中
static静态属性也不会随着对象写入到文件中
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("io.txt"));
oos.writeInt(1000);//写入int值
oos.writeDouble(123.123);//写入double值
oos.writeObject(new Date());//写入对象
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("io.txt"));
//注意:读取顺序和写入顺序必须一致
int readInt = ois.readInt();
double readDouble = ois.readDouble();
Date date = (Date) ois.readObject();
System.out.println(readInt);
System.out.println(readDouble);
System.out.println(date);
ois.close();
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("io.txt"));
oos.writeObject(new Student("张三", '男', 21, "2231", "001"));
oos.writeObject(new Student("李四", '男', 28, "2109", "002"));
oos.writeObject(new Student("王五", '男', 20, "2123", "003"));
oos.writeObject(null);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("io.txt"));
//读取数据(注意:读取顺序和写入顺序必须一致)
Student stu;
while((stu = (Student) ois.readObject()) != null){
System.out.println(stu);
}
ois.close();
打印流
PrintStream字节打印流
PrintWriter字符打印流
//PrintStream ps = new PrintStream("io.txt");
PrintStream ps = new PrintStream(new FileOutputStream("io.txt", true));//追加写
ps.println("兰小可爱,皇冠给你带~~~");
ps.close();
//PrintWriter pw = new PrintWriter("io.txt");
//PrintWriter pw = new PrintWriter(new FileOutputStream("io.txt", true));
PrintWriter pw = new PrintWriter(new FileWriter("io.txt", true));
pw.println("林2小可爱,皇冠给你带~~~");
pw.close();
扩展:重定向问题
//重定向 System.in
//重定向:(方向:文件->程序)
System.setIn(new FileInputStream("io.txt"));
//获取的是重定向后的InputStream
InputStream in = System.in;
Scanner scan = new Scanner(in);
String str = scan.next();
System.out.println(str);
scan.close();
//重定向 System.out
//重定向:(方向:程序->文件)
System.setOut(new PrintStream(new FileOutputStream("io.txt",true)));
//获取重定向的输出流
PrintStream out = System.out;
out.println("哈哈哈哈");
随机访问流
随机访问流并不是说就真的随机访问了
RandomAccessFile w = new RandomAccessFile("io.txt", "rw");
w.write("123abc木头人".getBytes());
w.close();
//在文件末尾追加内容
File file = new File("io.txt");
RandomAccessFile w = new RandomAccessFile(file, "rw");
//设置指针在文件末尾
w.seek(file.length());//填数字是指定位置开始写
w.write("123abc木头人".getBytes());
w.close();
RandomAccessFile r = new RandomAccessFile("io.txt", "r");
byte[] bs = new byte[1024];
int len;
while((len = r.read(bs)) != -1){
System.out.println(new String(bs, 0, len));
}
r.close();
//断点续传--网断了连上接着之前的位置下,而不是重新开始
RandomAccessFile r = new RandomAccessFile("水野朝阳.mp4", "r");
File file = new File("copy.mp4");
RandomAccessFile w = new RandomAccessFile(file, "rw");
//设置指针
r.seek(file.length());
w.seek(file.length());
byte[] bs = new byte[1024];
int len;
while((len = r.read(bs)) != -1){
w.write(bs, 0, len);
}
r.close();
w.close();
内存流
内存流是程序到内存,但程序本身就是在内存里边的,内存流用处不大,也关不掉
//创建内存输入流(创建流时就将数据放入到内存中)
ByteArrayInputStream bis = new ByteArrayInputStream("123abc".getBytes());
//获取数据
byte[] bs = new byte[1024];
int len;
while((len = bis.read(bs)) != -1){
System.out.println(new String(bs, 0, len));
}
//创建内存输出流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//写入数据
baos.write("123ABC木头人".getBytes());
//一次性读取数据
System.out.println(baos.toString());
System.out.println(new String(baos.toByteArray()));
注:考虑效率用带缓存的流