1. File
java.io.File类是文件和目录路径名的抽象表示形式,主要用于文件和目录的创建、查找和删除等操作。
1.1 File类概述和构造方法
File:它是文件和目录路径名的抽象表示
- 文件和目录可以通过File封装成对象
- File封装的对象仅仅是一个路径名。它可以是存在的,也可以是不存在的。
方法名 |
说明 |
File(String pathname) |
通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例 |
File(String parent, String child) |
从父路径名字符串和子路径名字符串创建新的 File实例 |
File(File parent, String child) |
从父抽象路径名和子路径名字符串创建新的 File实例 |
1.2 绝对路径和相对路径
- 绝对路径:从盘符开始
File file1 = new File(“D:\\snow\\a.txt”);
- 相对路径:相对当前项目下的路径
File file2 = new File(“a.txt”); File file3 = new File(“模块名\\a.txt”);
1.3 File 类的常用方法
创建和删除
方法名 | 说明 |
public boolean createNewFile() | 创建一个新的空的文件 |
public boolean mkdir() | 创建一个单级文件夹 |
public boolean mkdirs() | 创建一个多级文件夹 |
public boolean delete() | 删除由此抽象路径名表示的文件或目录 |
删除目录时的注意事项:
- delete方法直接删除不走回收站。
- 如果删除的是一个文件,直接删除。
- 如果删除的是一个文件夹,需要先删除文件夹中的内容,最后才能删除文件夹。
File类判断和获取功能
方法名 | 说明 |
public boolean isDirectory() | 测试此抽象路径名表示的File是否为目录 |
public boolean isFile() | 测试此抽象路径名表示的File是否为文件 |
public boolean exists() | 测试此抽象路径名表示的File是否存在 |
public String getAbsolutePath() | 返回此抽象路径名的绝对路径名字符串 |
public String getPath() | 将此抽象路径名转换为路径名字符串(File对象给定的路径) |
public String getName() | 返回由此抽象路径名表示的文件或目录的名称 |
File类高级获取功能
// 返回此抽象路径名表示的目录中的文件和目录的File对象数组 public File[] listFiles();
listFiles方法注意事项:
- 当调用者不存在时,返回null
- 当调用者是一个文件时,返回null
- 当调用者是一个空文件夹时,返回一个长度为0的数组
- 当调用者是一个有内容的文件夹时,将里面所有文件和文件夹的路径放在File数组中返回
- 当调用者是一个有隐藏文件的文件夹时,将里面所有文件和文件夹的路径放在File数组中返回,包含隐藏内容
1.4 递归删除文件夹及其下面的文件
public static void main(String[] args) { File f = new File("D:\\aaa"); deleteFiles(f); } private static void deleteFiles(File f) { File[] files = f.listFiles(); for (File file : files) { if (file.isDirectory()) { // 递归 deleteFiles(file); } else { // 删除文件 file.delete(); } } // 删除当前文件夹 f.delete(); }
2. IO
I 表示intput ,是数据从硬盘进内存的过程,称之为读数据。
O 表示output ,是数据从内存到硬盘的过程。称之为写数据。
在数据传输的过程中,是谁在读?是谁在写?这个参照物是谁?
IO的数据传输,可以看做是一种数据的流动,按照流动的方向,以内存为参照物,进行读写操作。
简单来说:内存在读,内存在写。
2.1 分类
2.2 字节输出流
OutputStream有很多子类,我们从最简单的一个子类开始。
java.io.FileOutputStream类是文件输出流,用于将数据写出到文件:
构造方法:
public FileOutputStream(File file)
:创建文件输出流以写入由指定的 File对象表示的文件。
public FileOutputStream(String name)
: 创建文件输出流以指定的名称写入文件。
import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; /* 字节输出流写数据快速入门 : 1 创建字节输出流对象。 2 写数据 3 释放资源 */ public class OutputStreamDemo1 { public static void main(String[] args) throws IOException { // 创建字节输出流对象 // 如果指定的文件不存在 , 会自动创建文件 // 如果文件存在 , 会把文件中的内容清空 FileOutputStream fos = new FileOutputStream("test\\a.txt"); // 写数据 // 写到文件中就是以字节形式存在的 // 只是文件帮我们把字节翻译成了对应的字符 , 方便查看 fos.write(97); fos.write(98); fos.write(99); // 释放资源 // while(true){} // 断开流与文件中间的关系 fos.close(); } }
字节流写数据的3种方式
方法名 | 说明 |
void write(int b) | 一次写一个字节数据 |
void write(byte[] b) | 一次写一个字节数组数据 |
void write(byte[] b, int off, int len) | 一次写一个字节数组的部分数据 |
public class OutputStreamDemo2 { public static void main(String[] args) throws IOException { // 创建字节输出流对象 FileOutputStream fos = new FileOutputStream("test\\a.txt"); // 写数据 // 1 void write(int b) 一次写一个字节数据 fos.write(97); fos.write(98); fos.write(99); // 2 void write(byte[] b) 一次写一个字节数组数据 byte[] bys = {65, 66, 67, 68, 69}; fos.write(bys); // 3 void write(byte[] b, int off, int len) 一次写一个字节数组的部分数据 fos.write(bys, 0, 3); // 释放资源 fos.close(); } }
字节流写数据的换行和追加写入
字节流写数据如何实现换行呢?
写完数据后,加换行符
windows : \r\n
linux : \n
mac : \r
字节流写数据如何实现追加写入呢?
public FileOutputStream(String name,boolean append)
创建文件输出流以指定的名称写入文件。如果第二个参数为true ,不会清空文件里面的内容。
2.3 字节输入流
InputStream
FileInputStream extends InputStream
FileInputStream 构造方法
- public FileInputStream(File file) : 从file类型的路径中读取数据
- public FileInputStream(String name) : 从字符串路径中读取数据
import java.io.FileInputStream; import java.io.IOException; /* 字节输入流写数据快速入门 : 一次读一个字节 第一部分 : 字节输入流类 InputStream类 : 字节输入流最顶层的类 , 抽象类 --- FileInputStream类 : FileInputStream extends InputStream 第二部分 : 构造方法 public FileInputStream(File file) : 从file类型的路径中读取数据 public FileInputStream(String name) : 从字符串路径中读取数据 第三部分 : 字节输入流步骤 1 创建输入流对象 2 读数据 3 释放资源 */ public class FileInputStreamDemo1 { public static void main(String[] args) throws IOException { // 创建字节输入流对象 // 读取的文件必须存在 , 不存在则报错 FileInputStream fis = new FileInputStream("day11_demo\\a.txt"); // 读数据 , 从文件中读到一个字节 // 返回的是一个int类型的字节 // 如果想看字符, 需要强转 int by = fis.read(); System.out.println((char) by); // 释放资源 fis.close(); } }
字节输入流 读多个字节
import java.io.FileInputStream; import java.io.IOException; /* 字节输入流写数据快速入门 : 读多个字节 第一部分 : 字节输入流类 InputStream类 : 字节输入流最顶层的类 , 抽象类 --- FileInputStream类 : FileInputStream extends InputStream 第二部分 : 构造方法 public FileInputStream(File file) : 从file类型的路径中读取数据 public FileInputStream(String name) : 从字符串路径中读取数据 第三部分 : 字节输入流步骤 1 创建输入流对象 2 读数据 3 释放资源 */ public class FileInputStreamDemo2 { public static void main(String[] args) throws IOException { // 创建字节输入流对象 // 读取的文件必须存在 , 不存在则报错 FileInputStream fis = new FileInputStream("day11_demo\\a.txt"); // 读数据 , 从文件中读到一个字节 // 返回的是一个int类型的字节 // 如果想看字符, 需要强转 // 循环改进 int by;// 记录每次读到的字节 while ((by = fis.read()) != -1) { System.out.print((char) by); } // 释放资源 fis.close(); } }
2.4 文件的拷贝
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; /* 需求 : 把 "图片路径\xxx.jpg" 复制到当前模块下 分析: 复制文件,其实就把文件的内容从一个文件中读取出来(数据源),然后写入到另一个文件中(目的地) 数据源: xxx.jpg --- 读数据 --- FileInputStream 目的地: 模块名称\copy.jpg --- 写数据 --- FileOutputStream */ public class CopyFile2 { public static void main(String[] args) throws IOException { // 创建字节输入流对象 FileInputStream fis = new FileInputStream("D:\\安装包\\好看的图片\\liqin.jpg"); // 创建字节输出流 FileOutputStream fos = new FileOutputStream("day11_demo\\copy.jpg"); // 一次读写一个字节 int by; while ((by = fis.read()) != -1) { fos.write(by); } // 释放资源 fis.close(); fos.close(); } }
2.5 文件拷贝效率优化
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; /* 需求 : 对复制图片的代码进行使用一次读写一个字节数组的方式进行改进 FileInputStream类 : public int read(byte[] b): 1 从输入流读取最多b.length个字节的数据 2 返回的是真实读到的数据个数 */ public class FileInputStreamDemo7 { public static void main(String[] args) throws IOException { // 创建字节输入流对象 FileInputStream fis = new FileInputStream("D:\\好看的图片\\liqin.jpg"); // 创建字节输出流 FileOutputStream fos = new FileOutputStream("day11_demo\\copy.jpg"); byte[] bys = new byte[1024]; int len;// 每次真实读到数据的个数 //int by;//好像没用上啊 while ((len = fis.read(bys)) != -1) { fos.write(bys, 0, len); } // 释放资源 fis.close(); fos.close(); } }
2.6 释放资源
JDK7版本优化处理方式 : 自动释放资源
JDK7优化后可以使用 try-with-resource 语句 , 该语句确保了每个资源在语句结束时自动关闭。简单理解 : 使用此语句,会自动释放资源 , 不需要自己在写finally代码块了
格式 : try (创建流对象语句1 ; 创建流对象语句2 ...) { // 读写数据 } catch (IOException e) { 处理异常的代码... } 举例 : try ( FileInputStream fis1 = new FileInputStream("day11_demo\\a.txt") ; FileInputStream fis2 = new FileInputStream("day11_demo\\b.txt") ) { // 读写数据 } catch (IOException e) { 处理异常的代码... }
代码实践
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; /* JDK7版本优化处理方式 需求 : 对上一个赋值图片的代码进行使用捕获方式处理 */ public class FileInputStreamDemo5 { public static void main(String[] args) { try ( // 创建字节输入流对象 FileInputStream fis = new FileInputStream("D:\\图片\\liqin.jpg"); // 创建字节输出流 FileOutputStream fos = new FileOutputStream("day11_demo\\copy.jpg") ) { // 一次读写一个字节 int by; while ((by = fis.read()) != -1) { fos.write(by); } // 释放资源 , 发现已经灰色 , 提示多余的代码 // 所以使用 try-with-resource 方式会自动关流 } catch (IOException e) { e.printStackTrace(); } } }
注意:自动释放的资源是实现了 AutoCloseable 接口的才可以。
2.7 缓冲流
字节缓冲流:
- BufferOutputStream:缓冲输出流
- BufferedInputStream:缓冲输入流
构造方法:
- 字节缓冲输出流:BufferedOutputStream(OutputStream out)
- 字节缓冲输入流:BufferedInputStream(InputStream in)
copy 文件实操
copyFile2("D:\\work\\test\\file_io\\xian.jpg", "D:\\work\\test\\file_io\\xian2.jpg"); static void copyFile2(String fileUrl1, String fileUrl2){ try( BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fileUrl1)); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fileUrl2)) ){ byte[] readArray = new byte[1024]; // 每次真实读到数据的个数 int len; while((len = bis.read(readArray)) != -1){ bos.write(readArray, 0 ,len); } } catch (FileNotFoundException e) { e.printStackTrace(); throw new RuntimeException("文件未找到!"); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("异常啦!"); } }
2.8 编码表
- 计算机中储存的信息都是用二进制数据表示的;我们在屏幕上看到的英文、汉字等字符是二进制数转换之后的结果
- 按照编码表规则,将字符存储到计算机中,称为编码。
- 按照同样的编码表规则,将存储在计算机中的二进制数据解析显示出来,称为解码 。
- 编码和解码使用的码表必须一致,否则会导致乱码。
常见编码表:
- ASCII码表:ASCII(American Standard Code for Information Interchange,美国信息交换标准码表):
包括了数字字符,英文大小写字符和一些常见的标点符号字符。
注意:ASCII码表中是没有中文的。
- GBK:window系统默认的码表。兼容ASCII码表,也包含了21003个汉字,并支持繁体汉字以及部分日韩文字。
注意:GBK是中国的码表,一个中文以两个字节的形式存储。但不包含世界上所有国家的文字。
- Unicode码表:
由国际组织ISO 制定,是统一的万国码表,计算机科学领域里的一项业界标准,容纳世界上大多数国家的所有常见文字和符号。
但是因为表示的字符太多,所以Unicode码表中的数字不是直接以二进制的形式存储到计算机的,会先通过UTF-7,UTF-7.5,UTF-8,UTF-16,以及 UTF-32的编码方式再存储到计算机,其中最为常见的就是UTF-8。
注意: Unicode是万国码表,以UTF-8编码后一个中文以三个字节的形式存储。
3. commons-io 工具包
3.1 API
org.apache.commons.io.IOUtils类
public static int copy(InputStream in, OutputStream out): //把input输入流中的内容拷贝到output输出流中,返回拷贝的字节个数(适合文件大小为2GB以下) public static long copyLarge(InputStream in, OutputStream out): //把input输入流中的内容拷贝到output输出流中,返回拷贝的字节个数(适合文件大小为2GB以上)
org.apache.commons.io.FileUtils
public static void copyFileToDirectory(final File srcFile, final File destFile): 复制文件到另外一个目录下。 public static void copyDirectoryToDirectory(File src , File dest ): 复制src目录到dest位置。