目录
2.1.1 InputStream 的具体子类 FileInputStream
2.1.2 OutputStream 的具体子类FileOutputStream
2.1.3 BufferedInputStream和BufferedOutputStream
一、File类
java里file类是可以用来处理文件目录问题
1.1 File类的常用方法
- File(String pathname) - 通过给定路径的字符串来创建一个表示对应文件的File实例
- exists() - 判断File实例对应的文件是否存在
- isFile() - 判断File实例是否是一个标准文件
- isDirectory() - 判断File实例是否是一个文件夹
- getName() - 获取File实例对应的文件或文件夹的名称
- getAbsolutePath() - 获取File实例对应文件或文件夹的绝对路径
- lastModified() - 返回此File实例的最后修改时间
- length() - 返回File实例的长度,以字节为单位
- String[] list() - 获取当前文件夹下的所有文件和文件夹的名称,到一个字符串数组中
- File[] listFiles() - 获取当前文件夹下的所有文件和文件夹的Filed对象,到一个File对象数组中
1.2. 文件名过滤器
在程序设计中,常常会通过文件名或文件的后缀类过滤掉出一些所需要的文件,而这就需要FilenameFilter接口来实现,而实现这个接口只需要实现其主要的 accept 方法即可,如:
public class PyFilesFilter implements FilenameFilter{
@Override
public boolean accept(File dir, String name) {
// TODO Auto-generated method stub
if(name.endsWith("py"))
return true;
return false;
}
}
这里是将后缀为 py 的文件过滤出来,其他则排除
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
String docPath = "D:\\PyQt5Project\\opencv_vcom\\myopencv";
File MyDoc = new File(docPath);
String[] files = MyDoc.list(new PyFilesFilter());
for(String pyFile : files) {
System.out.println(pyFile);
}
}
}
而在 main 方法里调用了File类的list方法来打印出过滤出的文件名,其入参为FilenameFilter的实现类
处理结果:
二、Java中的流
在java中将数据的输入输出抽象为流,而在操作IO流时,主要是在内存的角度上看待,从其他设备进入内存的,都是输入(包括硬盘),而从内存带其他设备的都是输出。
而IO流主要由两大类组成两类都分为输入和输出操作,流中保存的实际上全都是字节文件,字符流中多了对编码的处理:
- 字节流:其IO流类为 InputStream 和 OutputStream,其主要处理字节或二进制对象
- 字符流:其IO流类为 Reader 和 Writer,其主要处理字符或字符串对象
2.1 字节流
字符流时可以直接操作字节信息的流对象,InputStream 和 OutputStream 为顶层的抽象父类,根据交互设备的不同,有不同的具体子类
2.1.1 InputStream 的具体子类 FileInputStream
字符输入流的顶层抽象父类,其不能直接创建对象,只能由子类创建对象,如常用的 FileInputStream
FileInputStream 不仅可以一次读取一个字节,也可以一次读取很多个字节;不仅可以读取纯文本文件,也可以读取图片、视频、音频等非纯文本文件。一切数据在计算机中都是以字节的形式在存储和计算
- 构造方法
FileInputStream(File f); //将File对象封装成字节输入流 FileInputStream(String path); //可直接通过文件路径创建FileInputStream类
- 常用的方法
- int read() - 从该输入流中读取一个字节的数据
- int read(byte[] b) - 从该输入流中读取b.length()长度的单位到字节数组b中
- int available() - 返回此输入流中可以读取的剩余字节数的估计值
- void close() - 关闭此文件输入流并释放与流相关的任何系统资源
3. 文件读取操作
1.一次性全部读取(不推荐,太消耗系统内存)
byte[] bytes = new byte[fileInput.available()];//创建文件字节数大小的byte数组
fileInput.read(bytes); //一次性将文件中所有的字节读取出来
String str = new String(bytes);
System.out.println(str);
fileInput.close();
2. 逐个字节读取,可结合带资源的try语句使用,在 try 语句块执行完毕会自动调用资源的 close() 方法释放资源。
try(FileInputStream fileInput = new FileInputStream(filePath)){
byte aByte;
while((aByte = (byte) fileInput.read()) != -1) {
System.out.print((char)aByte);
}
}catch(IOException e) {
e.printStackTrace();
}
2.1.2 OutputStream 的具体子类FileOutputStream
字符输出流的顶层抽象父类,其不能直接创建对象,只能由子类创建对象,如常用的 FileOutputStream
- 构造方法
FileOutputStream(File f, boolean append); //将f描述的路径文件封装成字节输出流对象 FileOutputStream(String path, boolean append); //将path描述的文件路径封装成字节输出流对象
注意:append参数是 默认是false ,即重写整个文件,若文件内有内容将会被擦除;若为 ture,将会在原文件结尾后写入数据。
- 常用的方法
- void write(int b) - 将制定的字节写入此文件输出流
- void write(byte[] b) - 将 b.length() 个字节从制定的字节数组写入此文件输出流
- close() - 关闭此输出流并释放与此流相关联的任何系统资源
3. 文件写入操作
FileOutputStream fileoutput = new FileOutputStream(filePath, true); //追加模式,在原文件结尾写入字节
String content = "import cv2\n";
fileoutput.write(content.getBytes());
2.1.3 BufferedInputStream和BufferedOutputStream
BufferedInputStream和BufferedOutputStream分别是FileInputStream和FileOutputStream的强化版,它们能明显提高文件读写的速度。它们是包装类,本身不具备读写的功能,只是在某个具体的流对象的基础上,例如FileInputStream和FileOutputStream,对其进行加强。
- BufferedInputStream高效的原理:在该类型中准备了一个数组,存储字节信息,当外界调用 read() 方法想获取一个字节的时候,该对象从文件中一次性读取了8192个字节(默认大小)到数组中,只返回了第一个字节给调用者。将来调用者再次调用read方法时,当前对象就不需要再次访问磁盘,只需要从数组中取出一个字节返回给调用者即可,由于读取的是数组,所以速度非常快。当8192个字节全都读取完成之后,再需要读取一个字节,就得让该对象到文件中读取下一个8192个字节了。而原调用 FileInputStream 实例内的read() 方法,会反复进行访问磁盘,所以效率十分低。
- BufferedOutputStream高效的原理:在该类型中准备了一个数组,存储字节信息,当外界调用 write() 方法想写出一个字节的时候,该对象直接将这个字节存储到了自己的数组中,而不刷新到文件中。一直到该数组所有8192个位置全都占满,该对象才把这个数组中的所有数据一次性写出到目标文件中。如果最后一次循环过程中,没有将数组写满,最终在关闭流对象的时候,也会将该数组中的数据刷新到文件中。
- BufferedInputStream和BufferedOutputStream的构造方法
//BufferedInputStream的构造方法 BufferedInputStream(InputStream in); BufferedInputStream(InputStream in, int size); //size的默认大小为8192 //BufferedOutputStream的构造方法 BufferedOutputStream(OutputStream out); BufferedOutputStream(OutputStream out, int size); //size的默认大小为8192
- BufferedInputStream、BufferedOutputStream 和 FileInputStream、FileOutputStream 效率对比
对比的思路是对同一个文件进行读取再写入不同的文件中。(代码写得不严谨,但能体现出效率的对比即可)
首先利用多态写一个文件复制的方法。
package iodemo;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class MyCopyFile {
public MyCopyFile() {
}
public void copyFile(InputStream input, OutputStream output) throws IOException {
byte aByte;
while((aByte = (byte)input.read()) != -1) {
output.write(aByte);
}
}
}
接着便是分别创建BufferedInputStream、BufferedOutputStream 和 FileInputStream、FileOutputStream的实例对象,再调用此方法计时测试
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
String pyFile = "D:\\PyQt5Project\\opencv_vcom\\myopencv\\capture.py"; // 原文件
String pyFile1 = "D:\\PyQt5Project\\opencv_vcom\\myopencv\\capture1.py"; // 目标文件1
String pyFile2 = "D:\\PyQt5Project\\opencv_vcom\\myopencv\\capture2.py"; // 目标文件2
FileInputStream finput = new FileInputStream(pyFile);
FileOutputStream foutput = new FileOutputStream(pyFile1); // 用FileOutputStream写目标文件1
BufferedInputStream binput = new BufferedInputStream(new FileInputStream(pyFile));
// 用BufferedOutputStream写目标文件2
BufferedOutputStream boutput = new BufferedOutputStream(new FileOutputStream(pyFile2));
MyCopyFile mycopy = new MyCopyFile(); //自定义的实现方法
long startTime = System.currentTimeMillis();
mycopy.copyFile(finput, foutput);
long endTime = System.currentTimeMillis();
System.out.println("FileStream: " + (endTime - startTime) + "ms");
finput.close();// 关闭原文件的资源
startTime = System.currentTimeMillis();
mycopy.copyFile(binput, boutput);
endTime = System.currentTimeMillis();
System.out.println("BufferedStream: " + (endTime - startTime) + "ms");
binput.close();
boutput.close();
foutput.close();
}
结果如图:
可见使用BufferedInputStream、BufferedOutputStream进行读写文件可以提高很多的效率
2.2 字符流
https://blog.csdn.net/weixin_38987137/article/details/104096545