黑马程序员----IO基础知识1

本文深入探讨Java中的File类与IO流技术,详细介绍了File类的基本使用方法、文件与目录的操作、以及字节流和字节缓冲流的应用。通过实例演示,帮助开发者掌握如何高效地进行文件读写、复制、删除等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一讲 File类
1. File类的概述
  文件和目录路径名的抽象表示形式
2. File类的方法
 构造方法
File(String pathname):根据一个路径得到File对象
File(String parent, String child):根据一个目录和一个子文件/目录得到File对象
File(File parent, String child):根据一个父File对象和一个子文件/目录得到File对象

创建功能
public boolean createNewFile()创建文件,若存在,则不创建
public boolean mkdir()创建文件夹,若存在,则不创建
public boolean mkdirs()创建文件夹,若父文件夹不存在,则帮你创建

删除功能
public boolean delete()
注意:
A:如果你创建文件或者文件夹忘了写盘符路径,那么,默认在项目路径下。
B:Java中的删除不走回收站。
C:要删除一个文件夹,请注意该文件夹内不能包含文件或者文件夹
重命名功能
public boolean renameTo(File dest)
如果路径名相同,就是改名。
如果路径名不同,就是改名并剪切。

File类的成员方法
判断功能
  public boolean isDirectory():判断是否是目录
  public boolean isFile():判断是否是文件
  public boolean exists():判断是否存在
  public boolean canRead():判断是否可读
  public boolean canWrite():判断是否可写
  public boolean isHidden():判断是否隐藏

基本获取功能
  public String getAbsolutePath():获取绝对路径
  public String getPath():获取相对路径
  public String getName():获取名称
  public long length():获取长度。字节数
  public long lastModified():获取最后一次的修改时间,毫秒值

高级获取功能
public String[] list()获取指定目录下的所有文件或者文件夹的名称
public File[] listFiles()获取指定目录下的所有文件或者文件夹

3. File代码示例
需求:判断E盘目录下是否有后缀名为.jpg的文件,如果有,就输出此文件名称
  分析:
   A:封装e判断目录
   B:获取该目录下所有文件或者文件夹的File数组
   C:遍历该File数组,得到每一个File对象,然后判断
   D:是否是文件
   是:继续判断是否以.jpg结尾
   是:就输出该文件名称
   否:不搭理它
   否:不搭理它
public class FileDemo {
	public static void main(String[] args) {
		// 封装e判断目录
		File file = new File("e:\\");

		// 获取该目录下所有文件或者文件夹的File数组
		File[] fileArray = file.listFiles();

		// 遍历该File数组,得到每一个File对象,然后判断
		for (File f : fileArray) {
			// 是否是文件
			if (f.isFile()) {
				// 继续判断是否以.jpg结尾
				if (f.getName().endsWith(".jpg")) {
					// 就输出该文件名称
					System.out.println(f.getName());
				}
			}
		}
	}
}
上述的方法是先获取所有的文件或者文件夹,再判断是否满足条件
以下这种方式是通过文件名过滤器的方式先过滤满足条件的,再输出

文件名称过滤器的实现思想及代码
public String[] list(FilenameFilter filter)
public File[] listFiles(FilenameFilter filter)

分析: 判断E盘目录下是否有后缀名为.jpg的文件,如果有,就输出此文件名称
  A:先获取所有的,然后遍历的时候,依次判断,如果满足条件就输出。
  B:获取的时候就已经是满足条件的了,然后输出即可。
public class FileDemo2 {
	public static void main(String[] args) {
		// 封装e判断目录
		File file = new File("e:\\");

		// 获取该目录下所有文件或者文件夹的String数组
		// public String[] list(FilenameFilter filter)
		String[] strArray = file.list(new FilenameFilter() {
			@Override
			public boolean accept(File dir, String name) {
				// return false;
				// return true;
				// 通过这个测试,我们就知道了,到底把这个文件或者文件夹的名称加不加到数组中,取决于这里的返回值是true还是false
				// 所以,这个的true或者false应该是我们通过某种判断得到的
				// System.out.println(dir + "---" + name);
				// File file = new File(dir, name);
				// // System.out.println(file);
				// boolean flag = file.isFile();
				// boolean flag2 = name.endsWith(".jpg");
				// return flag && flag2;
				return new File(dir, name).isFile() && name.endsWith(".jpg");
			}
		});

		// 遍历
		for (String s : strArray) {
			System.out.println(s);
		}
	}
}
第二讲 递归 
1.递归概念
方法定义中调用方法本身的现象
如:public void XXX(){
   XXX();
}
2. 递归注意实现
要有出口,否则就是死递归
次数不能太多,否则就内存溢出
构造方法不能递归使用
3.简单递归实现
3.1 请用代码实现求5的阶乘。
递归实现注意事项:
a:做递归要写一个方法
b:出口条件
c:规律
public class DiGuiDemo {
	public static void main(String[] args) {
			
		System.out.println("5的阶乘是:"+jieCheng(5));
	}
	
	/*
	 * 做递归要写一个方法:
	 * 		返回值类型:int
	 * 		参数列表:int n
	 * 出口条件:
	 * 		if(n == 1) {return 1;}
	 * 规律:
	 * 		if(n != 1) {return n*方法名(n-1);}
	 */
	public static int jieCheng(int n){
		if(n==1){
			return 1;
		}else {
			return n*jieCheng(n-1);
		}
	}
}
3.2 用递归对文件进行操作
需求:递归删除带内容的目录,目录为demo
分析:
A:封装目录
B:获取该目录下的所有文件或者文件夹的File数组
C:遍历该File数组,得到每一个File对象
D:判断该File对象是否是文件夹
是:回到B
否:就删除

public class FileDeleteDemo {
	public static void main(String[] args) {
		// 封装目录
		File srcFolder = new File("demo");
		// 递归实现
		deleteFolder(srcFolder);
	}

	private static void deleteFolder(File srcFolder) {
		// 获取该目录下的所有文件或者文件夹的File数组
		File[] fileArray = srcFolder.listFiles();

		if (fileArray != null) {
			// 遍历该File数组,得到每一个File对象
			for (File file : fileArray) {
				// 判断该File对象是否是文件夹
				if (file.isDirectory()) {
					deleteFolder(file);
				} else {
					System.out.println(file.getName() + "---" + file.delete());
				}
			}

			System.out
					.println(srcFolder.getName() + "---" + srcFolder.delete());
		}
	}
}

第三讲 IO中的字节流和字节缓冲流
 1.  IO流的分类:
流向:
输入流 读取数据
输出流 写出数据
数据类型:
字节流
字节输入流 读取数据InputStream
字节输出流 写出数据OutputStream
字符流
字符输入流 读取数据Reader
字符输出流 写出数据Writer
 
注意:一般我们在探讨IO流的时候,如果没有明确说明按哪种分类来说,默认情况下是按照数据类型来分的。

2. 字节流概述
字节流的抽象基类:
InputStream ,OutputStream。
2.1 字节流写数据
由于OutputStream是抽象类,所以我们采用其子类FileOutputStream
FileOutputStream的构造方法:
FileOutputStream(File file) 
FileOutputStream(String name)
 字节输出流操作步骤:
         A:创建字节输出流对象
B:写数据
C:释放资源close()
注意:
为什么一定要close()呢?
 A:让流对象变成垃圾,这样就可以被垃圾回收器回收了
 B:通知系统去释放跟该文件相关的资源
字节输出流的写数据方法
public void write(int b):写一个字节
public void write(byte[] b):写一个字节数组
public void write(byte[] b,int off,int len):写一个字节数组,从off位置到len这么大长度

public class FileOutputStreamDemo {
	public static void main(String[] args) throws IOException {
		// 创建字节输出流对象
		FileOutputStream fos = new FileOutputStream("fos.txt");
		
		//写数据
		fos.write("hello,IO".getBytes());
		fos.write("java".getBytes());
		
		//释放资源
		//关闭此文件输出流并释放与此流有关的所有系统资源。
		fos.close();
	}
}

2.2 字节流读数据
 字节输入流操作步骤:
 A:创建字节输入流对象
 B:调用read()方法读取数据,并把数据显示在控制台
 C:释放资源

  读取数据的方式:
  A:int read():一次读取一个字节
  B:int read(byte[] b):一次读取一个字节数组,返回值其实是实际读取的字节个数。

代码示例:一次读取一个字节
public class FileInputStreamDemo {
	public static void main(String[] args) throws IOException {
		// FileInputStream(String name)
		// FileInputStream fis = new FileInputStream("fis.txt");
		FileInputStream fis = new FileInputStream("FileOutputStreamDemo.java");

		// // 调用read()方法读取数据,并把数据显示在控制台
		// // 第一次读取
		// int by = fis.read();
		// System.out.println(by);
		// System.out.println((char) by);
		//
		// // 第二次读取
		// by = fis.read();
		// System.out.println(by);
		// System.out.println((char) by);
		//
		// // 第三次读取
		// by = fis.read();
		// System.out.println(by);
		// System.out.println((char) by);
		// // 我们发现代码的重复度很高,所以我们要用循环改进
		// // 而用循环,最麻烦的事情是如何控制循环判断条件呢?
		// // 第四次读取
		// by = fis.read();
		// System.out.println(by);
		// // 第五次读取
		// by = fis.read();
		// System.out.println(by);
		// //通过测试,我们知道如果你读取的数据是-1,就说明已经读取到文件的末尾了

		// 用循环改进
		// int by = fis.read();
		// while (by != -1) {
		// System.out.print((char) by);
		// by = fis.read();
		// }

		// 最终版代码
		int by = 0;
		// 读取,赋值,判断
		while ((by = fis.read()) != -1) {
			System.out.print((char) by);
		}

		// 释放资源
		fis.close();
	}
}

代码示例:一次读取一个字节数组
public class FileInputStreamDemo2 {
	public static void main(String[] args) throws IOException {
		// 创建字节输入流对象
		// FileInputStream fis = new FileInputStream("fis2.txt");
		FileInputStream fis = new FileInputStream("FileOutputStreamDemo.java");

		// 读取数据
		// 定义一个字节数组
		// 第一次读取
		// byte[] bys = new byte[5];
		// int len = fis.read(bys);
		// // System.out.println(len);
		// // System.out.println(new String(bys));
		// // System.out.println(new String(bys, 0, len));
		// System.out.print(new String(bys, 0, len));
		//
		// // 第二次读取
		// len = fis.read(bys);
		// // System.out.println(len);
		// // System.out.println(new String(bys));
		// // System.out.println(new String(bys, 0, len));
		// System.out.print(new String(bys, 0, len));
		//
		// // 第三次读取
		// len = fis.read(bys);
		// // System.out.println(len);
		// // System.out.println(new String(bys));
		// // System.out.println(new String(bys, 0, len));
		// System.out.print(new String(bys, 0, len));
		//
		// // 第四次读取
		// len = fis.read(bys);
		// // System.out.println(len);
		// // System.out.println(new String(bys, 0, len));
		// System.out.print(new String(bys, 0, len));
		// // 代码重复了,用循环改进
		// // 但是,我不知道结束条件
		// // len = fis.read(bys);
		// // System.out.println(len);
		// // len = fis.read(bys);
		// // System.out.println(len);
		// // 如果读取到的实际长度是-1,就说明没有数据了

		// byte[] bys = new byte[115]; // 0
		// int len = 0;
		// while ((len = fis.read(bys)) != -1) {
		// System.out.print(new String(bys, 0, len));
		// // System.out.print(new String(bys)); //千万要带上len的使用
		// }

		// 最终版代码
		// 数组的长度一般是1024或者1024的整数倍
		byte[] bys = new byte[1024];
		int len = 0;
		while ((len = fis.read(bys)) != -1) {
			System.out.print(new String(bys, 0, len));
		}

		// 释放资源
		fis.close();
	}
}
2.3 复制文件(利用字节流可以复制文本文件,图片等各种字节组成的文件)
一次读取一个字节示例:
public class CopyFileDemo {
	public static void main(String[] args) throws IOException {
		// 封装数据源
		FileInputStream fis = new FileInputStream("a.txt");
		// 封装目的地
		FileOutputStream fos = new FileOutputStream("b.txt");

		//一次读取并复制一个字节
		int by = 0;
		while ((by = fis.read()) != -1) {
			fos.write(by);
		}

		// 释放资源(先关谁都行)
		fos.close();
		fis.close();
	}
}
也可以一次读取一个字节数组,这样复制的效率就会高一点
2.4 字节缓冲流
字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,
这是加入了数组这样的缓冲区效果,java本身在设计的时候,
也考虑到了这样的设计思想(装饰设计模式后面讲解),所以提供了字节缓冲区流

字节缓冲输出流
BufferedOutputStream
字节缓冲输入流
BufferedInputStream

四种情况效率比较问题:
基本字节流一次读写一个字节:共耗时:8908毫秒
基本字节流一次读写一个字节数组 :共耗时:16毫秒
高效字节流一次读写一个字节:共耗时:62毫秒
高效字节流一次读写一个字节数组 :共耗时:10毫秒
所以可以发现,在使用字节缓冲流并且一次读取一个字节数组最高效
计算出这四种情况下复制大容量的mp4文件需要的时长

public class CopyMp4Demo {
	public static void main(String[] args) throws IOException {
		long start = System.currentTimeMillis();
		 method1("e:\\yyy.mp4", "copy1.mp4");
		// method2("e:\\yyy.mp4", "copy2.mp4");
		// method3("e:\\yyy.mp4", "copy3.mp4");
//		method4("e:\\yyy.mp4", "copy4.mp4");
		long end = System.currentTimeMillis();
		System.out.println("共耗时:" + (end - start) + "毫秒");
	}

	// 高效字节流一次读写一个字节数组:
	public static void method4(String srcString, String destString)
			throws IOException {
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
				srcString));
		BufferedOutputStream bos = new BufferedOutputStream(
				new FileOutputStream(destString));

		byte[] bys = new byte[1024];
		int len = 0;
		while ((len = bis.read(bys)) != -1) {
			bos.write(bys, 0, len);
		}

		bos.close();
		bis.close();
	}

	// 高效字节流一次读写一个字节:
	public static void method3(String srcString, String destString)
			throws IOException {
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
				srcString));
		BufferedOutputStream bos = new BufferedOutputStream(
				new FileOutputStream(destString));

		int by = 0;
		while ((by = bis.read()) != -1) {
			bos.write(by);

		}

		bos.close();
		bis.close();
	}

	// 基本字节流一次读写一个字节数组
	public static void method2(String srcString, String destString)
			throws IOException {
		FileInputStream fis = new FileInputStream(srcString);
		FileOutputStream fos = new FileOutputStream(destString);

		byte[] bys = new byte[1024];
		int len = 0;
		while ((len = fis.read(bys)) != -1) {
			fos.write(bys, 0, len);
		}

		fos.close();
		fis.close();
	}

	// 基本字节流一次读写一个字节
	public static void method1(String srcString, String destString)
			throws IOException {
		FileInputStream fis = new FileInputStream(srcString);
		FileOutputStream fos = new FileOutputStream(destString);

		int by = 0;
		while ((by = fis.read()) != -1) {
			fos.write(by);
		}

		fos.close();
		fis.close();
	}
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值