一、File类
1、概念
File 类是 java.io 包中唯一代表磁盘文件本身的对象,也就是说,如果希望在程序中操作文件和目录,则都可以通过 File 类来完成。File 类定义了一些方法来操作文件,如新建、删除、重命名文件和目录等。
File 类不能访问文件内容本身,如果需要访问文件内容本身,则需要使用输入/输出流。
2、构造方法
File 类提供了如下三种形式构造方法。
File(String path):如果 path 是实际存在的路径,则该 File 对象表示的是目录;如果 path 是文件名,则该 File 对象表示的是文件。
File(String path, String name):path 是路径名,name 是文件名。
File(File dir, String name):dir 是路径对象,name 是文件名。
3、常用常量
File 类中有以下两个常用常量:
public static final String pathSeparator:指的是分隔连续多个路径字符串的分隔符,Windows 下指;
。例如java -cp test.jar;abc.jar HelloWorld。
public static final String separator:用来分隔同一个路径字符串中的目录的,Windows 下指/
。例如C:/Program Files/Common Files。
4、常用方法
public class Test02 {
public static void main(String[] args) {
String path = "D:/study/test"; // 指定文件所在的目录
File f = new File(path, "test.txt"); // 建立File变量,并设定由f变量引用
System.out.println("D:\\study\\test\\test.txt文件信息如下:");
System.out.println("============================================");
System.out.println("文件长度:" + f.length() + "字节");
//检测实例对象代表的是否是文件
System.out.println("文件或者目录:" + (f.isFile() ? "是文件" : "不是文件"));
//检测实例对象代表的是否是目录
System.out.println("文件或者目录:" + (f.isDirectory() ? "是目录" : "不是目录"));
//检测实例对象代表的是否能可读取
System.out.println("是否可读:" + (f.canRead() ? "可读取" : "不可读取"));
//检测实例对象代表的是否能可写入
System.out.println("是否可写:" + (f.canWrite() ? "可写入" : "不可写入"));
//检测实例对象代表的是否是隐藏文件
System.out.println("是否隐藏:" + (f.isHidden() ? "是隐藏文件" : "不是隐藏文件"));
//检测实例对象代表的最后修改日期
System.out.println("最后修改日期:" + new Date(f.lastModified()));
//获取实例对象代表的文件名字
System.out.println("文件名称:" + f.getName());
//获取实例对象代表的文件的实际路径
System.out.println("文件路径:" + f.getPath());
//获取实例对象代表的文件的绝对路径
System.out.println("绝对路径:" + f.getAbsolutePath());
}
}
二、IO的基本概念
1、概念
I和O,分别是Input和Output两个单词的缩写,Input是输入,Output是输出。
流:是一种抽象概念,是对数据传输的总称.也就是说数据在设备间的传输称为流,流的本质是数据传输。IO流就是用来处理设备间数据传输问题的。常见的应用: 文件复制、文件上传、文件下载等。
2、分类
从数据的流向:
输入流 : 从 硬盘读取数据到内存。
输出流 : 从内存输出数据保存到硬盘中。
从传输的数据类型:
字节流:以字节为单位进行数据的传输 -- 可以处理任何的数据(视频 音乐 图片 文本 ....)。
字符流:以字符为单位进行数据的传输 -- 只能处理文本数据(txt 文件 html文件 java文件) 使用记事本软件正常打开并识别就是文本文件。
从功能上进行分类:
节点流:负责传输数据的基本流。
过滤流(处理流):增强节点流功能的流。
抽象上分为两类:
堵塞式IO(BIO):同步并阻塞。服务器实现模式为一个连接一个线程,即用户端有连接请求时服务器就需要启动一个线程进行处理,如果这个连接不做任何事情就会造成不必要的线程开销。
非堵塞式io(NIO):同步非阻塞,服务器实现模式为一个线程处理多个请求连接,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询连接有I/O请求就进行处理。
非堵塞式io(AIO): 异步非阻塞。服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS完成了再通知服务器应用去启动线程进行处理,一般适用于连接数较多且连接市场较长的应用。
三、字节流
1、分类
InputStream:这个抽象类是表示字节输入流的所有类的超类。
OutputStream:这个抽象类是表示字节输出流的所有类的超类。
2、字节流的主要方法
OutputStream的主要方法
public void write(byte[] b):将指定的字节输出流。
public void flush():刷新此输出流并强制任何缓冲的输出字节被写出。
public void close():关闭此输出流并释放与此流相关联的任何系统资源。
public void write(byte[] b):将 b.length个字节从指定的字节数组写入此文件输出流。
public void write(byte[] b, int off, int len):将len个字节从位于偏移量 off的指定字节数组写入此文件输出流。
public void write(int b):将指定的字节写入此文件输出流。
public void close():关闭此文件输出流并释放与此流相关联的任何系统资源。
FileOutputStream(文件字节输出流):是 OutputStream 的子类。
FileOutputStream(File file):创建文件输出流以写入由指定的 File对象表示的文件。
FileOutputStream(File file, boolean append):创建文件输出流以写入由指定的 File对象表示的文件。
FileOutputStream(String name):创建文件输出流以指定的名称写入文件。
FileOutputStream(String name, boolean append):创建文件输出流以指定的名称写入文件。
InputStream的主要方法
public int read(byte[] b): 从输入流读取一个字节。
public int read(): 从输入流读取一个字节。
public void close() :关闭此输入流并释放与此流相关联的任何系统资源。
public int read():从该输入流读取一个字节的数据。
public int read(byte[] b):从该输入流读取最多 b.length个字节的数据为字节数组。
public int read(byte[] b, int off, int len):从该输入流读取最多len字节的数据为字节数组。
public void close():关闭此文件输入流并释放与此流相关联的任何系统资源。
FileInputStream(文件字节输入流):是 InputStream 的子类 。
FileInputStream(File file):通过打开与实际文件的连接创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。
FileInputStream(String name):通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。
注:进程结束的时候需手动关流,最好写在finally块中。
四、字符流
1、分类
字符输出流:Writer
字符输入流:Reader
2、主要方法
Writer的方法
void close():关闭流,先刷新。
void flush():刷新流。
void write(char[] cbuf):写入一个字符数组。
void write(char[] cbuf, int off, int len):写入字符数组的一部分。
void write(int c):写一个字符
void write(String str):写一个字符串
void write(String str, int off, int len):写一个字符串的一部分。
FileWriter文件字符输出流的构造方法:
FileWriter(File file):给一个File对象构造一个FileWriter对象。
FileWriter(File file, boolean append):给一个File对象构造一个FileWriter对象。
FileWriter(String fileName):构造一个给定文件名的FileWriter对象。
FileWriter(String fileName, boolean append):构造一个FileWriter对象。
Reader的主要方法:
public int read(): 从输入流读取一个字符
public int read(char[] cbuf): 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中 。每次最多读取cbuf.length个字符。返回实际读取的字符个数。如果已经到达流末尾,没有数据可读,则返回-1。
public void close():关闭此流并释放与此流相关联的任何系统资源。
FileReader文件字符输入流的构造方法:
FileReader(File file):创建一个新的 FileReader ,给出 File读取。
FileReader(String fileName):创建一个新的 FileReader ,给定要读取的文件的名称。
五、缓冲流
1、概念
缓冲流,也叫高效流。能够高效读写的数据流,能够转换编码的转换流,能够持久化存储对象的序列化对象等等。对文件或者其他目标频繁的操作,效率低,性能差。缓冲流目的是提高程序读取和写出的性能。缓冲流也分为字节缓冲流和字符缓冲流,其本质是通过缓冲区读写较少IO次数而提高效率的。
- 字节缓冲流:BufferedInputStream,BufferedOutputStream
- 字符缓冲流:BufferedReader,BufferedWriter
缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO读取次数,从而提高读写的效率。
2、执行过程
-
缓冲流把数据先写到缓冲区,默认情况下是当缓冲区满,或调用close,或调用flush这些情况才会把缓冲区的数据输出.
-
关闭时,默认先关闭外面的流,再关闭内部的流。
3、拓展
字符流可以针对文档内容进行选择性读取或者写入
-
BufferedReader:
public String readLine()
: 读一行文字 -
BufferedWriter:
public void newLine()
: 写一行行分隔符,由系统属性定义符号
4、效率测试
举例:不同方法,拷贝txt文件的速度,来测试效率
文件复制的步骤(不使用缓冲):
1.创建一个字节输入流对象,构造方法中绑定要读取的数据源。2.创建一个字节输出流对象,构造方法中绑定要写入的目的地。 3.使用字节输入流对象中的方法read,读取文件。 4.使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中。 5.释放资源。
文件复制的步骤(使用缓冲):
1.创建字节缓冲输入流对象,构造方法中传递字节输入流。2.创建字节缓冲输出流对象,构造方法中传递字节输岀流。3.使用字节缓冲输入流对象中的方法read,读取文件。 4.使用字节缓冲输出流中的方法wite,把读取的数据写入到内部缓冲区中。 5.释放资源(会先把缓冲区中的数据,刷新到文件中)。
/** * 不使用缓冲字节输入输出流, * 一个一个字节的方式。 */
public static void method1() throws IOException {
FileInputStream fis = new FileInputStream("D:/study/doc/sde.txt");
FileOutputStream fos = new FileOutputStream("D:/study/doc/copy1.txt");
int len = 0;
while ((len = fis.read()) != -1) {
fos.write(len);
}
fis.close();
fos.close();
}/** * 不使用缓冲字节输入输出流, * 一次读取多个字节的方式。 */
public static void method2() throws IOException {
FileInputStream fis = new FileInputStream("D:/study/doc/sde.txt");
FileOutputStream fos = new FileOutputStream("D:/study/doc/copy2.txt");
byte[] bytes = new byte[1024];
int len = 0;
while ((len = fis.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
fis.close();
fos.close();
}
/** * 使用缓冲字节输入输出流 */
public static void method3() throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:/study/doc/sde.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:/study/doc/copy3.txt"));
byte[] bytes = new byte[1024]; int len = 0; while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
bos.close();
bis.close();
}
public class DemoEfficiency {
public static void main(String[] args) throws IOException {
// 方法1效率测试
long method1StartTime = System.currentTimeMillis();
method1();
long method1EndTime = System.currentTimeMillis();
System.out.println("使用方法1,文件复制耗时(毫秒):" + (method1EndTime - method1StartTime));
// 方法2效率测试
long method2StartTime = System.currentTimeMillis();
method2();
long method2EndTime = System.currentTimeMillis();
System.out.println("使用方法2,文件复制耗时(毫秒):" + (method2EndTime - method2StartTime));
// 方法3效率测试
long method3StartTime = System.currentTimeMillis();
method3();
long method3EndTime = System.currentTimeMillis();
System.out.println("使用方法3,文件复制耗时(毫秒):" + (method3EndTime - method3StartTime));
}
}
控制台结果:
文件大小:20,867KB
运行程序,生成:copy1.txt、copy2.txt、copy3.txt三个文件
可以看出,使用缓冲字节输入输出流效率极高。