IO流

本文围绕Java展开,介绍了File类,它是对文件进行操作的类,定义了与平台无关的操作方法,还提及了常用构造方法和属性。同时详细阐述了IO流,包括其概念、分类、基类,如InputStream、OutputStream等,以及节点流如FileInputStream等,最后介绍了文件复制的实现。

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

1. File类

1、 文件可认为是相关记录或放在一起的数据的集合。文件一般存放在存储介质上:硬盘、u盘、光盘、软盘、云盘等。(云管段)

2、 java.io.File 类是专门对文件进行操作的类。(只能对文件本身进行操作,不能对文件内容操作)

3、 File类是“文件和目录路径名的抽象表示”。而不是指文件的内容。

4、 File类定义了一些与平台无关的方法操作,如:创建、删除文件和重命名等。

5、 Java中目录被看成是一个特殊的文件。List()方法可以返回目录中所有的子目录和文件。

6、 在linux下路径分隔符为(/),而在windos中则是为(\),在java中可以正确的处理不同系统中的分隔符。

1.1 File类常用构造方法和属性

常用构造方法:

1、public File(Stringpathname)

​ 以pathname为路径创建File对象,如果pathname是相对路径,则是相对于Java的系统属性user.dir中的路径。(对eclipse创建的java工程来说,就是该工程的根目录。)

属性:

2、public static finalString separator 存储了当前系统的名称分隔符

​ 在 LINUX和Mac系统上,此字段的值为 '/';在 Windows 系统上,它为 '\'.为了程序的跨平台特性,文件的路径应该用这个属性值来代表。

3、public static final char pathSeparator 存储了当前系统默认路径分割符号

​ Windows系统是 ; 即path环境变量中,不同的路径的分割符号。LINUX系统是:

1.2 File类的常用方法

常用方法1:文件属性:

import java.io.File;

public class Test {
	public static void main(String[] args) {
		File file = new File("C:\\Users\\zhangwendi\\Desktop\\111.txt");

		System.out.println("file.separator:" + file.separator);
		System.out.println("file.exists(),判断对象所对应的目录或文件是否存在:" + file.exists());
		System.out.println("判断对象是否是一个目录(file.isDirectory()):" + file.isDirectory());
		System.out.println("判断是否是一个文件(file.isFile()):" + file.isFile());
		System.out.println("判断是否是隐藏文件或目录(file.isHidden()):" + file.isHidden());
		System.out.println("最后修改时间(file.lastModified()):" + file.lastModified());
		System.out.println("文件长度(以字节为单位):" + file.length());
		System.out.println("获取文件名字:" + file.getName());
		System.out.println("获取文件路径:" + file.getPath());
	}
}

输出结果: 

file.separator:\
file.exists(),判断对象所对应的目录或文件是否存在:true
判断对象是否是一个目录(file.isDirectory()):false
判断是否是一个文件(file.isFile()):true
判断是否是隐藏文件或目录(file.isHidden()):false
最后修改时间(file.lastModified()):1536500887582
文件长度(以字节为单位):10
获取文件名字:111.txt
获取文件路径:C:\Users\zhangwendi\Desktop\111.txt

常用方法2:对于文件的操作:

import java.io.File;

public class Test {
	public static void main(String[] args) {
		File file = new File("C:\\Users\\zhangwendi\\Desktop");
		boolean bool = file.mkdir();// 可以创建文件对象的上一级目录
		boolean morebool = file.mkdirs();// 判断路径是否存在,如果不存在,就创建对应目录(多级)
		// boolean isDelete = file.delete();
		// System.out.println("是否删除成功:"+isDelete);
		if (file.isDirectory()) {
			File[] allfile = file.listFiles();// 得到目录下所有的直接子目录和文件
			for (int i = 0; i < allfile.length; i++) {
				System.out.println(allfile[i].getPath());
			}
		} else {
			System.out.println("不是一个目录");
		}
	}
}

 在获取文件和目录过程中,还可以对文件和目录进行筛选(或者过滤):

import java.io.File;
import java.io.FileFilter;

public class Test {
	public static void main(String[] args) {
		File file = new File("C:\\Users\\zhangwendi\\Desktop");
		// 判断是否是一个目录
		if (file.isDirectory()) {
			File[] all = file.listFiles(new FileFilter() {
				@Override
				public boolean accept(File myfile) {
					// 判断是否是一个目录,是就通过
					if (myfile.isDirectory()) {
						return true;
					}
					// 判断文件是否是以.txt结尾的,是就通过
					if (myfile.getName().endsWith(".txt")) {
						return true;
					}
					return false;
				}
			});
			for (int i = 0; i < all.length; i++) {
				System.out.println(all[i].getPath());
			}
		}
	}
}

 

2. IO流

2.1 什么是IO流

​ IO指的是Input/Output,IO流:输入输出流。 统称为数据流(IO Stream)

​ 在Java程序中,对于数据的输入 / 输出操作以流的方式进行;流是从起源到接收的有序数据。JDK提供了各种各样的流类,用以获取不同种类的数据;

2.2 IO流的分类

按流向分:

◦ 输入流:程序可以从中读取数据的流

◦ 输出流:程序能向其中写入数据的流

按数据传输单位分:

◦ 字节流:以字节为单位传输数据的流

◦ 字符流:以字符为单位传输数据的流

按功能分:

◦ 节点流:用于直接操作目标设备的流

◦ 处理流:是对一个已存在的流的连接和封装,通过对数据的处理为程序提供更强大、灵活的读写功能。

2.3 IO流的基类

分类字节输出流字节输入流字符输出流字符输入流
抽象基类OutputStreamInputStreamWriterReader
访问文件FileOutputStreamFileInputStreamFileWriterFileReader
访问数组ByteArrayOutputStreamByteArrayInputStreamCharArrayWriterCharArrayReader
访问管道PipedOutputStreamPipedInputStreamPipedWriterPipedReader
访问字符串  StringWriterStringReader
缓冲流BufferedOutputStreamBufferedInputStreamBufferedWriterBufferedReader
转换流  OutputStreamWriterInputStreamReader
对象流ObjectOutputStreamObjectInputStream  
抽象基类FilterOutputStreamFilterInputStreamFilterWriterFilterReader
打印流PrintStream PrintWriter 
推回输入流 PushbackInputStream PushbackReader
特殊流DataOutputStreamDataInputStream  

2.3.1 InputStream字节输入流

​ 继承自InputStream的流都是用于向程序中输入数据的,且数据的单位为字节(8位),红色框为节点流,黑色框为处理流

InputStream基本方法:

public abstract int read() throws IOException

​ 从输入流中读取数据的下一个字节, 返回读到的字节值.若遇到流的末尾,返回-1

public int read(byte[] b) throws IOException

​ 从输入流中读取 b.length 个字节的数据并存储到缓冲区数组b中.返回的是实际读到的字节总数

public int read(byte[] b, int off, int len)throws IOException

​ 读取 len 个字节的数据,并从数组b的off位置开始写入到这个数组中

public void close() throws IOException

​ 关闭此输入流并释放与此流关联的所有系统资源

public int available() throws IOException

​ 返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数

public skip(long n) throws IOException

​ 跳过和丢弃此输入流中数据的 n 个字节,返回实现路过的字节数。

2.3.2 OutputStream字节输出流

​ 继承自OutputStream的流是程序用于向外输出数据的,且数据的单位为字节(8位),红色边框是节点流,黑色边框是处理流

OutputStream主要方法:

public abstract void write(int b) throws IOException

​ 将指定的字节写入此输出流

public void write(byte[] b) throws IOException

​ 将 b.length 个字节从指定的 byte 数组写入此输出流

public void write(byte[] b, int off, intlen) throws IOException

​ 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流

public void flush() throws IOException

​ 刷新此输出流并强制写出所有缓冲的输出字节

pulbic void close() throws IOException

​ 关闭此输出流并释放与此流有关的所有系统资源

2.3.3 Reader字符输入流

​ 继承自Reader的流都是用于向程序中输入数据的,且数据的单位为字符(16位),红框着色为节点流,黑框着色为处理流:

public int read() throws IOException

​ 读取单个字符,返回作为整数读取的字符,如果已到达流的末尾返回-1

public int read(char[] cbuf) throws IOException

​ 将字符读入数组,返回读取的字符数

public abstract int read(char[] cbuf,int off, int len) throws IOException

​ 读取 len 个字符的数据,并从数组cbuf的off位置开始写入到这个数组中

public abstract void close() throws IOException

​ 关闭该流并释放与之关联的所有资源

public long skip(long n) throws IOException

​ 跳过n个字符。

2.3.4 Writer字符输出流

​ 继承Writer的流都是向程序中输出数据,且数据的单位为字符(16 bit);下图中红框着色为节点流,黑框着色为处理流

public void write(int c) throws IOException

​ 写入单个字符

public void write(char[] cbuf) throws IOException

​ 写入字符数组

public abstract voidwrite(char[] cbuf, int off, int len) throws IOException

​ 写入字符数组的某一部分

public void write(String str) throwsIOException

​ 写入字符串

public void write(String str,int off, int len) throws IOException

​ 写字符串的某一部分

public abstract void close() throwsIOException

​ 关闭此流,但要先刷新它

public abstract void flush() throwsIOException

​ 刷新该流的缓冲,将缓冲的数据全写到目的地

2.4 节点流

2.4.1 FileInputStream

FileInputStream 类创建一个能从文件读取字节的InputStream类,它的两个常用的构造方法如下:

FileInputStream(String filepath)

FileInputStream(File fileObj)

这两个构造方法都能引发FileNotFoundException异常。这里,filepath是文件的绝对路径,也可是相对路径。fileObj是描述该文件的File对象。

下面的例子创建了两个使用同样磁盘文件且各含一个上面所描述的构造方法的FileInputStreams类:

InputStreamf0 = new FileInputStream("c:\test.txt");

Filef = new File("c:\test.txt");

InputStreamf1 = new FileInputStream(f);

尽管第一个构造方法可能更常用到,而第二个构造方法则允许在把文件赋给输入流之前用File方法更进一步检查文件。当一个FileInputStream被创建时,它可以被公开读取

2.4.2 FileOutputStream

FileOutputStream创建了一个可以向文件写入字节的类OutputStream,它常用的构造方法如下:

FileOutputStream(String filePath)

FileOutputStream(String filePath, boolean append)

FileOutputStream(File fileObj)

FileOutputStream(File fileObj, boolean append)

​ 它们可以引发IOException或SecurityException异常。这里filePath是文件的绝对路径,也可以是相对路径。fileObj是描述该文件的File对象。如果append为true,则表示追加。FileOutputStream 的创建不依赖于文件是否存在。在创建对象时,FileOutputStream会在打开输出文件之前就创建它。这种情况下如果试图打开一个只读文件,会引发一个IOException异常

2.4.3 FileReader

FileReader类创建了一个可以读取文件内容的Reader类。它最常用的构造方法显示如下:

FileReader(String filePath)

FileReader(File fileObj)

每一个都能引发一个FileNotFoundException异常。

2.4.4 FileWriter

​ FileWriter 创建一个可以写文件的Writer类。它最常用的构造方法如下:

FileWriter(String filePath)

FileWriter(String filePath, boolean append)

FileWriter(File fileObj)

FileWriter(File fileObj, boolean append)

​ 它们可以引发IOException或SecurityException异常。这里,filePath是文件的绝对路径,fileObj是描述该文件的File对象。如果append为true,输出是附加到文件尾的。FileWriter类的创建不依赖于文件存在与否。在创建文件之前,FileWriter将在创建对象时打开它来作为输出。如果试图打开一个只读文件,将引发一个IOException异常。

2.5 文件复制

实现文件复制(使用字节流):

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class Test {

	public static void main(String[] args) {
		File source = new File("D:\\zhiling\\java25班\\Java高级\\day06\\myfile\\a.txt");
		File target = new File("D:\\zhiling\\java25班\\Java高级\\day06\\myfile\\b.txt");
		copyFileByStream(source, target);
	}

	public static void copyFileByStream(File sourceFile, File targetFile) {
		// 判断源文件是否存在,如果不存在,就退出程序
		if (!sourceFile.exists()) {
			System.out.println("源文件不存在,程序退出");
			System.exit(0);
		}
		// target.getParentFile()表示用来获取目标对象的父目录对象
		// 如果目标文件路径不存在,就创建
		if (!targetFile.getParentFile().exists()) {
			targetFile.getParentFile().mkdirs();
		}
		InputStream is = null;
		OutputStream os = null;
		try {
			// 准备输入流
			is = new FileInputStream(sourceFile);
			// 准备输出流
			os = new FileOutputStream(targetFile);
			// 准备一个数组,用来存放读写的数据
			byte[] b = new byte[1024];
			int len = -1;
			// read(b)实现读取操作,数据存入b数组,返回读取长度给len,当所有内容都读取完毕,len=-1
			while ((len = is.read(b)) != -1) {
				// 实现写的操作
				os.write(b, 0, len);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (is != null) {
					is.close();
				}
				if (os != null) {
					os.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

实现文件复制(通过字符流):

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;

public class Test {

	public static void main(String[] args) {
		File source = new File("C:\\Users\\zhangwendi\\Desktop\\111.txt");
		File target = new File("C:\\Users\\zhangwendi\\Desktop\\b.txt");
		copyFileByWriter(source, target);
	}

	public static void copyFileByWriter(File source, File target) {
		// 判断源文件是否存在
		if (!source.exists()) {
			System.out.println("源文件不存在,程序退出");
			System.exit(0);
		}
		// 判断目标文件路径是否存在,不存在就创建
		if (!(target.getParentFile().exists())) {
			target.getParentFile().mkdirs();
		}
		Reader reader = null;
		Writer writer = null;
		try {
			reader = new FileReader(source);
			writer = new FileWriter(target);
			char c[] = new char[1024];
			int len = 0;
			while ((len = reader.read(c)) != -1) {
				writer.write(c, 0, len);
			}
			writer.flush();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				// 多个资源需要关闭时,原则上应该是先开的后关
				if (writer != null) {
					writer.close();
				}
				if (reader != null) {
					reader.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}

 

### Java IO概述 Java IOInput/Output)用于处理数据输入和输出操作。它提供了多种类来实现文件、网络和其他设备的数据传输功能。这些类主要位于 `java.io` 包中。 #### 文件读写的两种基本方式 Java 中的 IO 分为两大类:字节和字符。 - **字节**:适用于二进制数据的操作,例如图片、音频等文件。 - **字符**:专门针对文本文件设计,提供更方便的编码转换支持。 以下是常见的几种及其用途: | 类型 | 输入 | 输出 | |--------------|----------------------------------|-------------------------------| | 字节 | `InputStream` | `OutputStream` | | 字符 | `Reader` | `Writer` | --- ### 示例代码展示 #### 1. 使用字节复制图片文件 下面是一个完整的例子,展示了如何通过字节完成图片文件的复制[^2]。 ```java import java.io.*; public class ByteStreamExample { public static void main(String[] args) { try (InputStream is = new FileInputStream("source_image.png"); OutputStream os = new FileOutputStream("destination_image.png")) { byte[] buffer = new byte[1024]; int length; while ((length = is.read(buffer)) > 0) { os.write(buffer, 0, length); } } catch (IOException e) { System.err.println("Error occurred during file copy: " + e.getMessage()); } } } ``` 此代码片段实现了从源路径到目标路径的文件拷贝过程。其中使用了缓冲区技术以提高性能。 #### 2. 缓冲字节的应用 为了进一步提升效率,可以引入带缓冲机制的子类——`BufferedInputStream` 和 `BufferedOutputStream`[^3]。 ```java import java.io.*; public class BufferedByteStreamExample { public static void main(String[] args) { try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("input.txt")); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("output.txt"))) { int data; while ((data = bis.read()) != -1) { bos.write(data); } } catch (IOException e) { System.err.println("I/O error encountered: " + e.getMessage()); } } } ``` 上述程序利用缓冲特性减少了底层磁盘访问次数,从而加快了执行速度。 #### 3. 对象序列化与反序列化 如果需要保存复杂结构的对象至外部存储介质,则需要用到对象 `ObjectInputStream` 和 `ObjectOutputStream`[^1]。 ```java // 序列化对象 try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.ser"))) { MySerializableClass obj = new MySerializableClass(); oos.writeObject(obj); } catch (Exception ex) { System.out.println(ex.toString()); } // 反序列化对象 try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.ser"))) { MySerializableClass restoredObj = (MySerializableClass) ois.readObject(); System.out.println(restoredObj); } catch (Exception ex) { System.out.println(ex.toString()); } ``` 注意:要使某个类能够被序列化,该类需实现 `java.io.Serializable` 接口。 --- ### 总结 以上介绍了三种典型场景下的 Java IO 应用实例,分别是基于字节的基础文件操作、借助缓存优化后的高效版本以及面向对象持久化的高级技巧。每种情况都体现了不同层次的需求满足能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值