💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] # 文件操作 ## 什么是文件 文件是计算机中基本的数据存储形式,在实际的存储数据中,如果对数据的读写速度要求不高,而且存储的数据量也不是很大,此时,可以选择使用文件这种持久化的存储方式。 所谓**持久化**,就是当程序退出,或者计算机关机以后,数据还是存在的。但是在程序内存中的数据会在程序关闭或计算机退出时丢失。 文件的组成:路径+文件的全名(文件名和文件后缀)。 关于文件后缀:只是定义了文件的打开方式不一样,如果更改后缀不会对文件的内部数据产生变化。 在不同的操作系统中,文件的路径表示形式是不一样的。 比如: `windows c:\windows\system\driver.txt` `Linux /user/my/tomcat/startup.txt` > 如果程序需要在不同的操作系统中运行,那么如果出现文件路径相关的设置时,必须要进行操作系统的判断,特别是windows和Linux关于斜杠的区别。 ## 绝对路径和相对路径 绝对路径指文件的完整路径,例如:c:\hello\hello.java。该路径包含文件的路径和文件的文件名即后缀。 使用该路径可以唯一的找到该文件。但是,在不同的操作系统下,文件的绝对路径表现形式是不一样的。这样就会比较麻烦。 相对路径是书写文件的部分路径: 如下文件结构 ~~~ D └─test │ a.txt │ └─A b.txt ~~~ 如使用 `D:\test` 作为基准目录 * a.txt 相对路径:a.txt * b.txt 相对路径:A\b.txt 如使用D:\text\A作为基准目录 * a.txt的相对路径:..\a.txt * b.txt的相对路径:b.txt > 在Java中\是转义字符,如果要是\进行路径的描述时,要使用“\\”表示。 > 可以通过System.getProperty("file.separator")的通用方式获取不同操作系统的文件分隔符(如Linux/windows\) **相对路径** Java 中文件的相对路径是相对 JVM 的启动路径而言的。 表现当前路径的方式:`.` 、`.\`、 `不使用任何的符号`; 一个点表示当前路径,两个点”..”表示上级目录。 在大部分的应用程序中,我们都会使用相对路径去构建文件。 通过 `Clazz.class` 获取类的元数据,然后调用 `Clazz.class.getResource("相对路径")` 获取绝对路径,进行文件创建。 ## File 类 为了方便的通过Java对文件进行基本的处理,在 java.io 包中设计了 File 类。 > File只能表现文件本身和目录(文件中的内容不在File类的管理范畴内) ### 文件常用的操作方法 ~~~ public class FileClient1 { public static void main(String[] args) throws IOException { } /** * 创建一个新文件 * @param path * @throws IOException */ public static void createNewFile(String path) throws IOException { File file = new File(path); boolean createFlag = file.createNewFile(); System.out.println(createFlag); } /** * 删除一个文件 * @param path * @throws IOException */ public static void deleteFile(String path) throws IOException { File file = new File(path); boolean delteFlag = file.delete(); // 返回true表示删除成功 false表示删除失败,失败的原因大部分是文件不存在 System.out.println(delteFlag); } /** * 判断一个文件后者路径是否存在 * @param path */ public static void existsFile(String path) { File file = new File(path); System.out.println(file.exists()); } /** * 获取文件的绝对路径 * @param path */ public static void getAbsolutePath(String path) { File file = new File(path); System.out.println(file.getAbsolutePath()); } /** * 获取文件名 * @param path */ public static void getFileName(String path) { File file = new File(path); System.out.println(file.getName()); } /** * 获取父路径 */ public static void getParent(String path) { File file = new File(path); System.out.println(file.getParent()); } /** * 判断一个文件对象是否是目录 */ public static void isDirectory(String path) { File file = new File(path); System.out.println(file.isDirectory()); } /** * 判断一个文件对象是否是文件 * @param path */ public static void isFile(String path) { File file = new File(path); System.out.println(file.isFile()); } /** * 获取文件目录下的所有文件和目录清单 * @param path */ public static void list(String path) { File file = new File(path); String[] files = file.list(); for (String fileName : files) { System.out.println(fileName); } } /** * 获取文件目录下的所有文件和目录清单(文件名) * @param path */ public static void listFiles(String path) { File file = new File(path); File[] files = file.listFiles(); for (File fileName : files) { System.out.println(fileName.getAbsolutePath()); } } /** * 创建目录 * @param path */ public static void mkdir(String path) { File file = new File(path); System.out.println(file.mkdir()); } /** * 创建目录(如果父目录不存在,则创建父目录) * @param path */ public static void mkdirs(String path) { File file = new File(path); System.out.println(file.mkdirs()); } /** * 文件重命名 * @param oldFileName * @param newFileName */ public static void renameTo(String oldFileName, String newFileName) { File oldFile = new File(oldFileName); File newFile = new File(newFileName); System.out.println(oldFile.renameTo(newFile)); } /** * 设置文件只读 * @param path */ public static void setReadonly(String path) { File file = new File(path); System.out.println(file.setReadOnly()); } } ~~~ ### 文件的递归读取和递归删除 递归遍历文件 ~~~ public static void main(String[] args) { printAllFile(new File("D:\\test")); } public static void printAllFile(File file) { String filePath = file.getAbsolutePath(); System.out.println(filePath); if (file.isDirectory()) { File[] files = file.listFiles(); for (File lf : files) { printAllFile(lf); } } } ~~~ 递归删除文件 ~~~ public static void main(String[] args) { deleteAllFile(new File("D:\\test")); } public static void deleteAllFile(File file) { if (file.isFile()) { // 直接删除文件 file.delete(); } else { File[] files = file.listFiles(); for (File fl : files) { deleteAllFile(fl); } // 删除目录 file.delete(); } } ~~~ ## 文件读取 文件的类型:字符型文件(简单立即就是记事本可以打开的文件,比如.java文件)、二进制文件(可以简单理解为编译过的文件,如 .class 文件、 .jpg 等图片文件、 .exe 可执行文件...) 对于文件读取操作,使用输入对应的子类:FileInputStream 和 FileReader 实现。 在Java的IO编程中,读取文件分为: 1. 将文件中的数据转换为流; 2. 读取流内部的数据。 其中第一步是系统自动完成的,读取流内部数据需要程序控制; 在通过输入流进行编程时,分为3个部分 1. 创建流对象; 2. 读取流对象内部的数据; 3. 关闭流。 代码示例 ~~~ public static void main(String[] args) { // 声明一个流对象 FileInputStream fis = null; File file = new File("D:\\test1\\a.txt"); try { // 通过File对象构建一个流对象 fis = new FileInputStream(file); // 读取数据,并将读取的数据存储在数组中 byte[] data = new byte[(int)file.length()]; // 读取流中的第一个字节数据 int n = fis.read(); // 读取的游标位置 int i = 0; // 判断是否读到最后一个字符 while(n != -1) { data[i] = (byte)n; i++; n = fis.read(); } String rs = new String(data, "GBK"); System.out.println(rs); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { // 关闭流,释放资源 fis.close(); } catch (IOException e) { e.printStackTrace(); } } } ~~~ ## 文件写入 ~~~ public static void main(String[] args) { String s = "Hello,Java!"; // 声明一个输出流 FileOutputStream fos = null; File file = new File("d:\\test1\\a.txt"); try { // 根据文件创建一个输出流对象 fos = new FileOutputStream(file); byte[] data = s.getBytes(); fos.write(data); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } ~~~ ## Java中常见的编码格式 在计算机系统中,ASCII码是最基础的编码格式,8bit存储一个字节数据,能够表示的字符范围为 255。 由于 ASCII 所变现的字符较少,随后就出现了包括 `ISO-8859-1` 、`GB2312`、`GBK`、`GB18030`、`UTF-16`、`UTF-8` 等编码格式。 目前在应用开发中,使用 UTF-8 的编码方式是最常见的,其次为 GBK。 我们在标识符定义中所说的 unicode 字符集就是指的的 UTF 编码方式。 除了 ASCII 码是用一个字节表示数据的,其他都是 2-4 个字节表示。 在文件字节流中读取的 `byte[]` 数据,最后通过 `new String(byte[], charsetName)` 方法构建的对象,第二个参数就是文件的编码方式。(把一个字节数组转化为字符串,如果不显式的指明字节的编码方式,则用系统默认的编码方式)。 在控制台输入chcp命名可以查询到系统目前使用的文字编码方式 936 表示的是 GBK。 ~~~ String rs = new String(data, "GBK"); ~~~ ## 字节流和字符流 字符流其实是字节流的一种特殊表现。 在IO流中,字符流的输入输出使用的 Writer/Reader,字节流使用InputStream/OutputStream。 * 输入流:只能做读操作 * 输出流:只能做写操作 ## 使用RandomAccessFile类进行数据的追加 ~~~ File file = new File("D:\\work\\Trade\\ws01\\JAVA88-1\\src\\test0613\\a1.txt"); RandomAccessFile raf = new RandomAccessFile(file, "rw"); raf.seek(raf.length()); raf.writeBytes("\r\nend"); raf.close(); ~~~