Java学习笔记(九)文件类、字节流 - FileInputStream、FileOutputStream、BufferedInputStream、BufferedOutputStream

目录

一、File类

1.1 File类的常用方法

1.2. 文件名过滤器

二、Java中的流

2.1 字节流

2.1.1 InputStream 的具体子类 FileInputStream

2.1.2 OutputStream 的具体子类FileOutputStream 

2.1.3 BufferedInputStream和BufferedOutputStream

2.2 字符流


一、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 不仅可以一次读取一个字节,也可以一次读取很多个字节;不仅可以读取纯文本文件,也可以读取图片、视频、音频等非纯文本文件。一切数据在计算机中都是以字节的形式在存储和计算

  1. 构造方法
    
    FileInputStream(File f);      //将File对象封装成字节输入流
    FileInputStream(String path); //可直接通过文件路径创建FileInputStream类
  2. 常用的方法
  • 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 

  1. 构造方法
    FileOutputStream(File f, boolean append);       //将f描述的路径文件封装成字节输出流对象
    FileOutputStream(String path, boolean append);  //将path描述的文件路径封装成字节输出流对象
    

    注意:append参数是 默认是false ,即重写整个文件,若文件内有内容将会被擦除;若为 ture,将会在原文件结尾后写入数据。

  2. 常用的方法 
  • 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,对其进行加强。

 

  1. BufferedInputStream高效的原理:在该类型中准备了一个数组存储字节信息,当外界调用 read() 方法想获取一个字节的时候,该对象从文件中一次性读取了8192个字节(默认大小)到数组中,只返回了第一个字节给调用者。将来调用者再次调用read方法时,当前对象就不需要再次访问磁盘,只需要从数组中取出一个字节返回给调用者即可,由于读取的是数组,所以速度非常快。当8192个字节全都读取完成之后,再需要读取一个字节,就得让该对象到文件中读取下一个8192个字节了。而原调用 FileInputStream 实例内的read() 方法,会反复进行访问磁盘,所以效率十分低。
  2. BufferedOutputStream高效的原理:在该类型中准备了一个数组,存储字节信息,当外界调用 write() 方法想写出一个字节的时候,该对象直接将这个字节存储到了自己的数组中,而不刷新到文件中。一直到该数组所有8192个位置全都占满,该对象才把这个数组中的所有数据一次性写出到目标文件中。如果最后一次循环过程中,没有将数组写满,最终在关闭流对象的时候,也会将该数组中的数据刷新到文件中
  3. BufferedInputStream和BufferedOutputStream的构造方法
    //BufferedInputStream的构造方法
    BufferedInputStream(InputStream in); 
    BufferedInputStream(InputStream in, int size); //size的默认大小为8192
    
    //BufferedOutputStream的构造方法
    BufferedOutputStream(OutputStream out); 
    BufferedOutputStream(OutputStream out, int size); //size的默认大小为8192

     

  4. 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

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值