JavaFile和IO流

本文详细介绍了Java中的File类和IO流。File类用于表示文件和目录,提供了创建、删除等操作。IO流分为字节流和字符流,按方向分为输入流和输出流,按单位分为字节和字符,按功能分为节点流和过滤流。字节流包括InputStream和OutputStream,字符流涉及Reader和Writer,以及它们的缓冲和转换流。此外,还讲解了对象流的序列化和反序列化,以及数据流、打印流、随机访问流和内存流的使用。

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

一、File

概念:代表物理盘符中的一个文件或者文件夹。

1.1文件\文件夹

常见方法:

方法名描述
createNewFile()创建一个新文件。
mkdir()创建一个新目录。
delete()删除文件或空目录。
exists()判断File对象所对象所代表的对象是否存在。
getAbsolutePath()获取文件的绝对路径。
getName()取得名字。
getParent()获取文件/目录所在的目录。
isDirectory()是否是目录。
isFile()是否是文件。
length()获得文件的长度。
listFiles()列出目录中的所有内容。
renameTo()修改文件名为。

案例演示:

public class TestFile {
	public static void main(String[] args) throws Exception {
		//separator();
		//fileOpe();
		directoryOpe();
	}
	//(1)分隔符
	public static void separator() {
		System.out.println("路径分隔符"+File.pathSeparator);
		System.out.println("名称分隔符"+File.separator);
	}
	//(2)文件操作
	public static void fileOpe() throws Exception {
		//1创建文件 createNewFile()
		File file=new File("d:\\file.txt");
		//System.out.println(file.toString());
		if(!file.exists()) {
			boolean b=file.createNewFile();
			System.out.println("创建结果:"+b);
		}
		//2删除文件
		//2.1直接删除
		//System.out.println("删除结果:"+file.delete());
		//2.2使用jvm退出时删除
		//file.deleteOnExit();
		//Thread.sleep(5000);		
		//3获取文件信息
		System.out.println("获取文件的绝对路径:"+file.getAbsolutePath());
		System.out.println("获取路径:"+file.getPath());
		System.out.println("获取文件名称:"+file.getName());
		System.out.println("获取父目录:"+file.getParent());
		System.out.println("获取文件长度:"+file.length());
		System.out.println("文件创建时间:"+new Date(file.lastModified()).toLocaleString());				
		//4判断
		System.out.println("是否可写:"+file.canWrite());
		System.out.println("是否时文件:"+file.isFile());
		System.out.println("是否隐藏:"+file.isHidden());
		
	}	
	//(3)文件夹操作
	public static void directoryOpe() throws Exception{
		//1 创建文件夹
		File dir=new File("d:\\aaa\\bbb\\ccc");
		System.out.println(dir.toString());
		if(!dir.exists()) {
			//dir.mkdir();//只能创建单级目录
			System.out.println("创建结果:"+dir.mkdirs());//创建多级目录
		}		
		//2 删除文件夹
		//2.1直接删除(注意删除空目录)
		//System.out.println("删除结果:"+dir.delete());
		//2.2使用jvm删除
		//dir.deleteOnExit();
		//Thread.sleep(5000);
		//3获取文件夹信息
		System.out.println("获取绝对路径:"+dir.getAbsolutePath());
		System.out.println("获取路径:"+dir.getPath());
		System.out.println("获取文件夹名称:"+dir.getName());
		System.out.println("获取父目录:"+dir.getParent());
		System.out.println("获取创建时间:"+new Date(dir.lastModified()).toLocaleString());		
		//4判断
		System.out.println("是否时文件夹:"+dir.isDirectory());
		System.out.println("是否时隐藏:"+dir.isHidden());		
		//5遍历文件夹
		File dir2=new File("d:\\图片");
		String[] files=dir2.list();
		System.out.println("--------------------------------");
		for (String string : files) {
			System.out.println(string);
		}		
	}	
}

递归删除指定文件夹

public class DeleteFile {
	public static void main(String[] args) {
		// 使用递归删除指定的文件夹
		File file = new File("Dir"); // 需要删除的文件夹
		deleteDir(file);
	}	
	// 递归删除指定文件夹 如果文件夹不为空,递归,
	// 直到文件夹为空,再删除指定文件夹
	public static void deleteDir(File file) {
		if (!file.exists()) {
			System.out.println("目标文件不存在");
			return;
		}
		deleteFile(file); // 调用清空文件夹的方法
		file.delete(); // 删除文件夹
		System.out.println(file.exists());
		System.out.println("已删除指定文件");
	}
	// 删除指定文件夹下的子文件夹和子文件 -- 清空文件夹 -- 便于删除文件夹
	public static void deleteFile(File file) {
		File[] files = file.listFiles();
		for (File f : files) { // 遍历
			if(f.isAbsolute()) {
				deleteFile(f); // 递归
			}else {
				f.delete(); // 删除文件
			}
		}
	}
}

二、流

在这里插入图片描述

2.1流的分类

2.1.1 按方向
  • 输入流:将<存储设备>中的内容读入到<内存>中。
  • 输出流:将<内存>中的内容写入到<存储设备>中。
2.1.2 按单位
  • 字节流:以字节为单位,可以读写所有数据 。

  • 字符流:以字符为单位,只能读写文本数据 。

2.1.3 按功能
  • 节点流:具有实际传输数据的读写功能。
  • 过滤流:在节点流的基础之上增强功能。

2.2字节流

处理二进制文件

2.2.1 字节抽象类

InputStream:字节输入流

  • public int read(){}。
  • .public int read(byte[] b){}。
  • public int read(byte[] b,int off,int len){}。

​ read():依次读取文件中的数据—每次读8位—ascii码,读完了返回-1

​ 文件中:123456789

​ 1:00110001-------49

​ 00110001 00110010 00110011 00110100 00110101 00110110 00110111

​ 00111000 00111001 11111111 11111111 11111111 11111111 11111111

​ 11111111 11111111 11111111 11111111 11111111 11111111 11111111

​ 11111111

​ read(byte[] buf):一次读取buf长度这么多个字节

​ 没读完返回实际读到的字节数,数据放在buf里

​ 读完返回-1

OutputStream:字节输出流

  • public void write(int n){}。
  • public void write(byte[] b){}。
  • public void write(byte[] b,int off,int len){}。

字节输出流,构造的时候如果加了true就是拼接

​ 常用 write(buf,0,length);

2.2.2文件字节

FileInputStream extends InputStream 文件字节输入流

FileOutputStream extends OutputStream 文件字节输出流

案例:FileInputStream读取文件

public class TestFileInputStream {
	public static void main(String[] args) throws Exception{
		//1创建FileInputStream,并指定文件路径
		FileInputStream fis=new FileInputStream("d:\\aaa.txt");
		//2读取文件
		//fis.read()
		//2.1单个字节读取
		//int data=0;
		//while((data=fis.read())!=-1) {
		//	System.out.print((char)data);
		//}
		//2.2一次读取多个字节
		byte[] buf=new byte[1024];
		int count=0;
		while((count=fis.read(buf))!=-1) {
			System.out.println(new String(buf,0,count));
		}		
		//3关闭
		fis.close();
		System.out.println();
		System.out.println("执行完毕");
	}
}

案例:FileOutputStream写入文件

public class TestFileOutputStream {
	public static void main(String[] args) throws Exception{
		//1创建文件字节输出流对象
		FileOutputStream fos=new FileOutputStream("d:\\bbb.txt",true);
		//2写入文件
		//fos.write(97);
		//fos.write('b');
		//fos.write('c');
		String string="helloworld";
		fos.write(string.getBytes());
		//3关闭
		fos.close();
		System.out.println("执行完毕");
	}
}

案例:

复制文件夹----包括子文件、子文件及其文件内容

copyDir(srcPath,descPath);

public class TestCopyDir {
	public static void main(String[] args) {
		// 复制文件夹(包括子文件夹和文件及其内容)
		String srcPath = "d:/Dir"; // 源文件夹路径
		String descPath = "d:/Dir1"; // 复制文文件夹路径
		copyDir(srcPath,descPath);
	}
	// 复制文件夹的方法
	public static void copyDir(String srcPath, String descPath) {		
		File file = new File(srcPath);
		File[] files = file.listFiles();
		
		File file2 = new File(descPath); 
		file2.mkdir(); // 创建文件夹
		
		for (File f : files) {
			String dPath = f.getAbsolutePath().replace("Dir", "Dir1"); // 更新路径
			if (f.isDirectory()) {
				new File(dPath).mkdir(); // 创建文件夹
				copyDir(f.getAbsolutePath(),dPath); // 递归
			}
			if (f.isFile()) { // 是文件就复制
				try {
					FileInputStream is = new FileInputStream(f.getAbsoluteFile());
					FileOutputStream os = new FileOutputStream(dPath);
					byte[] buf = new byte[1024*8];
					int length;
					while((length = is.read(buf)) != -1) {
						os.write(buf,0,length); // 复制
					}
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
2.2.3字节缓冲流

BufferedInputStream extends InputStream 带有缓冲区的字节输入流

BufferedOutputStream extends OutputStream 带有缓冲区的字节输出流

  • 提高IO效率,减少访问磁盘的次数。
  • 数据存储在缓冲区中,flush是将缓存区的内容写入文件中,也可以直接close。

默认缓冲区大小:8192字节

案例:

public class TestBufferedInputStream {
	public static void main(String[] args) throws Exception{
		//1创建BufferedInputStream
		FileInputStream fis=new FileInputStream("d:\\aaa.txt");
		BufferedInputStream bis=new BufferedInputStream(fis);
		//2读取
        //2.1单个字节读取
		//int data=0;
		//while((data=bis.read())!=-1) {
		//	System.out.print((char)data);
		//}
		//2.2一次读取多个字节
		byte[] buf=new byte[1024];
		int count=0;
		while((count=bis.read(buf))!=-1) {
			System.out.println(new String(buf,0,count));
		}		
		//3关闭
		bis.close();java		
	}
}
public class TestBufferedOutputStream {
	public static void main(String[] args) throws Exception{
		//1创建字节输出缓冲流
		FileOutputStream fos=new FileOutputStream("d:\\buffer.txt");
		BufferedOutputStream bos=new BufferedOutputStream(fos);
		//2写入文件
		for(int i=0;i<10;i++) {
			bos.write("helloworld\r\n".getBytes());//写入8K缓冲区 
			bos.flush();//刷新到硬盘
		}
		//3关闭(内部调用flush方法)
		bos.close();				
	}
}
2.2.4对象流

ObjectInputStream 对象输入流

ObjectOutputStream 对象输入流

  • 增强了缓冲区功能。
  • 增强了读写8种基本数据类型和字符串功能。
  • 增强了读写对象的功能:
    • readObject() 从流中读取一个对象。
    • writeObject(Object obj) 向流中写入一个对象。

序列化概念:

序列化:将程序中的对象写入到文件中 — 钝化

反序列化:将文件中的对象读取到程序中 — 活化

一个类的对象要想通过对象流写入到文件中,该类就必须实现序列化接口(Serializable)

Serializable叫做序列化接口,该接口没有让我们去实现任何的方法,这种接口叫做标记型接口

transient修饰属性后,该属性不会随着对象写入到文件中

static静态属性也不会随着对象写入到文件中

对象序列化的细节:

  • 必须实现Serializable接口。
  • 必须保证其所有属性均可序列化。
  • transient修饰为临时属性,不参与序列化。
  • 读取到文件尾部的标志:java.io.EOFException。

案例:

有一个学生对象,我们需要把这个学生存在文件中
//{name:“张三”,age:20,gender:“男”}

public class Student implements Serializable{ //实现序列化接口
	private static final long serialVersionUID = -9130056597294443988L; //
    //如果一个属性被transient修饰,意味着这个属性的值不能被序列化
	// transient String name;
    String name; 
	int age;
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public static long getSerialversionuid() {
		return serialVersionUID;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}	
}

// 测试类
public class TestStudent {
	public static void main(String[] args) throws Exception {
		
		Student s1 = new Student("张三", 20);
		Student s2 = new Student("李四", 20);
		Student s3 = new Student("王五", 20);
		ArrayList<Student> list = new ArrayList<Student>();
		list.add(s1);
		list.add(s2);
		list.add(s3);
		
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("d:/stu.txt"));
		
		for (int i = 0; i < list.size(); i++) {
			oos.writeObject(list.get(i));
		}
		oos.close();
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/stu.txt"));
		for (int i = 0; i < list.size(); i++) {
			Student stu = (Student)ois.readObject();
			System.out.println(stu.toString());
		}
		ois.close();
	}
}

2.2.5数据流

DataInputStream数据流入流

DataOutputStream数据流出流

案例:

public class TestDataStream {
	public static void main(String[] args) throws Exception {
		 FileInputStream fis = new FileInputStream("d:/a.txt");
		 DataInputStream dis = new DataInputStream(fis);//数据流
		 FileOutputStream fos = new FileOutputStream("d:/a.txt");
		 DataOutputStream dos = new DataOutputStream(fos);
		 //dos.writeUTF("数据");
		 //System.out.println(dis.readUTF());
		 dos.writeInt(49);
		 int num = dis.readInt();
		 System.out.println(num);
	}
}

(提一个异常 EOFE – EOF:end of file 读到文件末尾)
在这里插入图片描述

2.3字符流

2.3.1字符抽象类

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){}。
2.3.2字符集和字符编码

ASCII --0-127

ISO8859-1 — 128-255 能够表示的符号 256个

中文:

​ GB2312 GBK GB18030 BIG5

​ ANSI不是编码,微软为了让各地的用户感觉操作系统无差异 —ANSI

欧洲标准化组织:

​ UNICODE:万国码

UTF-8 UTF-16 UTF-32

UTF-16:不管你是什么字,我都编程16位

UTF-32:固定长度为32位

UTF-8:可变长的编码

utf-8编码规则:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m9NciU1G-1658564796557)(E:/学习/java一阶段-qf线下/课程/20220720-day23-IO流/笔记/images/image-20220720150454092.png)]

1字节utf:128个字符—ASCII

2字节:11

3字节:16 — 中文编码 20000-40000 19968-40869

4字节:21

案例:用字节流去读取UTF-8编码的中文

中—0800 < 4e2d <FFFF

public class TestEncode {

	public static void main(String[] args) throws Exception {
		
		FileInputStream fis = new FileInputStream("d:/a.txt");
		// 以 中 字为例子
		//中--100111000101101 4e2d
		//1110 0100--228  10 111000-184  10 101101-173
		System.out.println(fis.read()); // 228
		System.out.println(fis.read()); // 184
		System.out.println(fis.read()); // 173
		System.out.println(fis.read()); // -1
		fis.close();
	}
}
2.3.3文件字符流

FileReader extends InputStreamReader 文件字符输入流

FileWriter extends OutputStreamWriter 文件字符输出流

public class TestReader {
	public static void main(String[] args) throws Exception {
        FileReader fr = new FileReader("d:/a.txt");
        int data;
        while((data=fr.read())!=-1) {//读的时候要拿到本地编码
		System.out.print((char)data);
		}
	}
}
2.3.4字符转换流

InputStreamReader extends Reader 字符输入转换流(字节流转换字符流)

OutputStreamWriter extends Writer 字符输出转换流(字节流转换字符流)

应用场景:获取到的流是字节流,但是要去做字符操作

注意:使用转换流都加编码格式

用转换流解决乱码的问题

public class TestInReader {
	
public static void main(String[] args) throws Exception {
		//转换流----字节流转字符流
		FileInputStream fis = new FileInputStream("d:/a.txt");
		InputStreamReader  isr = new InputStreamReader(fis, "utf-8");
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d:/b.txt"));
		int length;
		char[] buf = new char[8];
		while((length=isr.read(buf))!=-1) {//读的时候要拿到本地编码
			System.out.print(new String(buf,0,length));
			osw.write(buf, 0, length);
		}
		//注意:字符流是有缓存的
		osw.flush();
		osw.close();
	}
}
2.3.5缓冲字符流

BufferedReader extends Reader 带有缓冲区的字符输入流

BufferedWriter extends Writer 带有缓冲区的字符输出流

public class TestBuffer {
	
public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("d:/a.txt"),"utf-8"));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("d:/c.txt",true),"utf-8"));
		String str = "";
		while((str=br.readLine())!=null) {
			System.out.println(str);
			bw.write(str);
			//bw.write("\n");
			bw.newLine();
		}
		bw.close();
		br.close();
	}
}

2.4各种流…

2.4.1打印流

注意:打印流只有一个方向,就是程序到文件

PrintStream - 字节打印流

PrintWriter - 字符打印流

PrintStream vs PrintWriter

PrintStream :可以将字节流转换为打印流

PrintWriter :可以将字节流/字符流转换为打印流

重定向:重新定义系统标准输入输出流的方向

系统标准的输入流(方向:控制台->程序)

System.setIn() -重定向 :(方向:文件->程序)

系统标准的输出流:(方向:程序->控制台)

System.setOut-重定向:(方向:程序->文件)

案例:

public class TestPrintWriter {
	public static void main(String[] args) throws Exception {
		//1创建打印流
		PrintWriter pw=new PrintWriter("d:\\print.txt");
		//2打印
		pw.println(97);
		pw.println(true);
		pw.println(3.14);
		pw.println('a');
		//3关闭
		pw.close();
		System.out.println("执行完毕");
	}
}
2.4.2随机访问流

RandomAccessFile随机访问流

含义:认为文件是一个大型的byte数组,底层有一个隐藏的指针,可以从指针的位置进行读取或者写入

模式:r-读 rw-读写

2.4.3内存流

ByteArrayInputStream 内存输入流

ByteArrayOutputStream 内存输出流

方向:程序 <----> 内存

应用场景:数据不重要但频繁使用,就将数据存到内存流中

注意:内存流是关不掉的

2.5总结

IO流大致可以分为字节流和字符流,这两种流又分为输入和输出,每个流的操作都大相径庭,学习时可以触类旁通,举一反三。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值