当前位置: 首页 > news >正文

java-文件IO

文件IO

操作系统有一个专门的模块-文件系统,来管理文件。并提供了 api 供我们使用。

文件系统 使用 N叉树 来组织文件。

操作系统使用 “路径” 来描述文件的位置。路径的表示又分为 绝对路径相对路径

绝对路径 :从树的的根节点(Windows 下的根节点是盘符,即 C、D 之类的)开始,一层一层的到目标文件;

相对路径 :从 当前目录(也称为 工作目录/基准目录)出发,到目标文件;

例如:D:/steam/appcache/httpcache 该路径即为 此 httpcache 文件的 绝对路径

D:/steam/appcache 如果这是当前目录,则此 bin 文件的 相对路径 ./bin . 表示是当前目录。

D:/steam/appcache/librarycache 如果这是当前目录,则此 bin 文件的 相对路径 …/httpcache 表示上层目录。可以进行多个上次目录操作。

路径中 优先使用 / ,写作 \ 在代码还需进行转义。

文件分为 文本文件二进制文件

文本文件, 是以 字符编码(如 ASCII、UTF-8 等) 存储数据的文件,(文件中的数据均在码表上可查)

二进制文件, 是以 二进制数据(0 和 1 的序列) 存储信息的文件

通过 记事本 打开文件,可以对文件是 文本文件 还是 二进制文件 进行判断。(乱码对应 二进制文件;反之,即为 文本文件

文本文档、.c 、.java、.cpp 等都是 文本文件

图片、音频、视频、可执行程序、动态库 等都是 二级制文件

常用的 .docx(word文档)、.slsx(excel)、 .pptx(PPT)富文本 ,是二进制文件。

java 对文件系统的操作 API 主要分为以下两类:

① 针对文件系统的操作

包括但不限于 创建文件、删除文件、重命名文件、列出目录内容……

② 针对文件内容的操作

读写文件

java中使用 File 类(位于 java.io 包下)对文件系统进行操作

File 属性,构造方法,方法

属性

修饰符及类型属性说明
static StringpathSeparator依赖于系统的路径分隔符,String 类型的表示
static charpathSeparator依赖于系统的路径分隔符,char 类型的表示

路径里的分隔符,根据操作系统的不同会自行调整。这里建议直接使用 /

构造方法

构造方法说明
File(File parent, String child)根据父目录 + 孩子文件路径,创建一个新的 File 实例
File(String pathname)根据文件路径创建一个新的 File 实例,路径可以是绝对路径或者相对路径。
File(String parent, String child)根据父目录 + 孩子文件路径,创建一个新的 File 实例,父目录用路径表示

File(String pathname) 最常用,除了相对路径和绝对路径外,这里的路径还可以是不存在的。写作相对路径时,①如果是在 idea 中运行,此时的工作目录为项目所在的目录。②如果是把代码打包成一个独立的 jar 包,此时工作目录是 jar 包所在的目录。

方法

返回值类型方法说明
StringgetParent()返回 File 对象的父目录文件路径
StringgetName()返回 FIle 对象的纯文件名称
StringgetPath()返回 File 对象的文件路径
StringgetAbsolutePath()返回 File 对象的绝对路径
StringgetCanonicalPath()返回 File 对象的修饰过的绝对路径
booleanexists()判断 File 对象描述的文件是否真实存在
booleanisDirectory()判断 File 对象代表的文件是否是一个目录
booleanisFile()判断 File 对象代表的文件是否是一个普通文件
booleancreateNewFile()根据 File 对象,自动创建一个空文件。成功创建后返回 true
booleandelete()根据 File 对象,删除该文件。成功删除后返回 true
voiddeleteOnExit()根据 File 对象,标注文件将被删除,删除动作会到JVM 运行结束时才会进行
String[]list()返回 File 对象代表的目录下的所有文件名
File[]listFiles()返回 File 对象代表的目录下的所有文件,以 File 对象表示
booleanmkdir()创建 File 对象代表的目录
booleanmkdirs()创建 File 对象代表的目录,如果必要,会创建中间目录
booleanrenameTo(File dest)进行文件改名,也可以视为我们平时的剪切、粘贴操作
booleancanRead()判断用户是否对文件有可读权限
booleancanWrite()判断用户是否对文件有可写权限

部分常见方法的使用示例:

public class Test {public static void main(String[] args) throws IOException {//File file = new File("C:/Users/lenovo/desktop/test.txt");File file = new File("./test.txt");System.out.println(file.getParent());System.out.println(file.getName());System.out.println(file.getPath());System.out.println(file.getAbsolutePath());System.out.println(file.getCanonicalPath());}
}

在这里插入图片描述

import java.io.File;
import java.io.IOException;public class Test {public static void main(String[] args) throws IOException {File f = new File("./test.txt");System.out.println(f.exists());System.out.println(f.isFile());System.out.println(f.isDirectory());System.out.println(f.createNewFile());}
}

在这里插入图片描述

public class Test{public static void main(String[] args) throws InterruptedException {File file = new File("./test.txt");//file.delete();file.deleteOnExit();//程序退出后删除Thread.sleep(3000);}
}

退出时再删除,这样的称为 “临时文件”。就像用 word 打开文件后,桌面上会出现一个虚的文件(在文件资源管理器中勾选显示隐藏文件,才能看见)。主要作用是应对·正在编辑的内容,没有保存,而意外退出(如:电脑突然断电)的情况,重新供电后这时临时文件依然存在,借助这个临时文件就可以恢复之前未保存的数据。就像word 中的自动保存。

public class Test {public static void main(String[] args) {File file = new File(".");//获取目录下文件文件名//String[] files = file.list();//获取目录的文件File[] files = file.listFiles();System.out.println(Arrays.toString(files));}
}

在这里插入图片描述

import java.io.File;public class Test {public static void main(String[] args) {File file = new File("./aaa/bbb/ccc"); //只有一个目录//boolean ret = file.mkdir();//一连串目录boolean ret = file.mkdirs();System.out.println(ret);}
}
import java.io.File;public class demo6_0525 {public static void main(String[] args) {File file1 = new File("./test2.txt");//File file2 = new File("./test2.txt");File file2 = new File("./aaa/test.txt");file1.renameTo(file2);}
}

除了重命名外,还可以用于更换文件的路径。

对文件内容的操作

通过 来对文件内容进行操作,

流就像水流一样,以接水为例:

接一杯1000ml水,可以一次接 1000ml;

亦可以分两次,一次 500ml;

也可以分五次,一次 200ml;

……

对文件内容的读写,和着类似;

1000字节的内容,也可以分多次读写;

流又分为 字节流字符流

字节流 以字节为单位进行读写,一次最少读写一个字节。

代表类 InputStreamOutputStream

字符流 以字符为单位进行读写,比如,如果是 utf8 表示汉字,3字节就是 1 汉字,每次读写以三字节为单位进行,不能一次读半个汉字。

代表类 ReaderWriter

:这里的读与写是相对于 CPU 而言的,假设你坐在 CPU 上,朝你来的 是 ;离你去的是

InputStream 概述

方法

返回值类型方法说明
intread()读取一个字节的数据,返回 -1 代表已经完全读完了
intread(byte[] b)尽量将 b 填满,返回实际读到的数量;-1 代表以及读完了
intread(byte[] b, int off, int len)从 offset 下标开始填,尽可能填 len 个,返回实际读到的数量;-1 代表以及读完了
voidclose()关闭字节流

在这里插入图片描述

观察上图我们发现 读到的数据(不是数据个数)就是 [0-255] 刚好是 1byte ,但是为什么这里使用 int 作为返回值呢?

原因:

1)保障能处理读完情况时,有余地表示 -1

2) 保障读到的数据都是正数,byte 类型有符号,使用 int 可以确保读出的数据都是正数

3) 虽然 short 类型也可以,甚至比 int 少了两个字节,但是建议使用 int ,就像建议使用 double 来代替 float

文件关闭 close

打开文件,就会在系统内核 PCB 结构体中,给 “文件描述符表” 添加一个新元素,记录当前打开的文件的相关信息。close() 就会释放对应元素。如果一直只是打开文件,而不关闭就会使 文件描述符表 被占满,后续打开文件就会失败。这种情况类似 内存泄漏称为 文件资源泄露 。 而且,在表未用完之前是不会出现问题的,很难发现,就像是 随时可能爆炸的雷。

说明

InputStream 只是一个抽象类,要使用还需要具体的实现类。关于 InputStream 的实现类有很多,基本可以认为不同的输入设备都可以对应一个 InputStream 类,我们现在只关心从文件中读取,所以使用 FileInputStream

FileInputStream 概述

构造方法

签名说明
FileInputStream(File file)利用 File 构造文件输入流
FileInputStream(String name)利用文件路径构造文件输入流

代码示例:

public class Test {public static void main(String[] args) throws IOException {InputStream inputStream = null;//inputstream 放在这里是为了能在 finally 中关闭。//放在 try 里面作用域仅在 try 代码块中,finally 够不到try {inputStream = new FileInputStream("./test.txt");} finally {inputStream.close();}}
}

inputstream 放在 try 是为了能在 finally 中关闭, 放在 try 里面作用域仅在 try 代码块中,finally 够不到。(避免忘记 close)

public class Test {public static void main(String[] args) throws IOException {try (InputStream inputStream = new FileInputStream("./test.txt")) {while (true) {int b = inputStream.read();if (b == -1) {break;}System.out.printf("%x ", b);}}}
}

除了在 close 放在 finally 里,还可以将 关闭操作 交给 try ,当出了 try 的 {} 后会自动 close

但是前提是实现了 closable 接口

上面是一个字节一个字节的读

读入 byte 数组

public class Test {public static void main(String[] args) throws IOException {try (InputStream inputStream = new FileInputStream("./test.txt")) {while (true) {byte[] b = new byte[1024];int n = inputStream.read(b);if (n == -1) {break;}for (int i = 0; i < n; i++) {System.out.printf("%x ",b[i]);}}}}
}

这里是将 b 中元素一个一个地打印出来

下面是转成 String 进行打印

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class Test {public static void main(String[] args) {try (InputStream inputStream = new FileInputStream("./test.txt")){while (true) {byte[] buffer = new byte[1024];int n = inputStream.read(buffer);if (n == -1) {break;}String s = new String(buffer,0,n);System.out.println(s);}} catch (IOException e) {throw new RuntimeException(e);}}
}

String s = new String(buffer,0,n); 第一个参数为要转的数组,第二个表示从 该下标 开始为转成 String ,第三个为截止下标 (左闭右开型 [参2,参三 )

OutputStreaam 概述

方法

返回值类型方法说明
voidwrite(int b)写入给出的字节的数据
voidwrite(byte[] b)将 b 这个字符数组中的数据全部写入 文件 中
intwrite(byte[] b, int off, int len)将 b 这个字符数组中从 off 开始的数据写入文件 中,一共写 len 个。
voidclose()关闭字节流
voidflush()重要:我们知道 I/O 的速度是很慢的,所以,大多的 OutputStream 为了减少设备操作的次数,在写数据的时候都会将数据先暂时写入内存的一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写入设备中,这个区域一般称为缓冲区。但造成一个结果,就是我们写的数据,很可能会遗留一部分在缓冲区中。需要在最后或者合适的位置,调用 flush(刷新)操作,将数据刷到设备中。

说明

OutputStream 同样只是一个抽象类,要使用还需要具体的实现类。我们现在还是只关心写入文件中,所以使用 FileOutputStream

代码示例:

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;public class demo9_0526 {public static void main(String[] args) {try (OutputStream outputStream = new FileOutputStream("./test.txt")) {byte[] buffer = new byte[] {97,98,99,100,101,102};outputStream.write(buffer);} catch (FileNotFoundException e) {throw new RuntimeException(e);} catch (IOException e) {throw new RuntimeException(e);}}
}

直接这样,每次 new 出来是都会清空对应文件的内容。

FileOutputStream 第二个参数给 true ,就不会清空了,而是在内容结尾,进行追加。

Reader 和 WriterInputStream 和 OutputStream 类似,不再做具体说明。看一下代码示例:

Reader

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;public class Test {public static void main(String[] args) {try (Reader reader = new FileReader("./test.txt")){while (true) {char[] buffer = new char[1024];int n = reader.read(buffer);if (n == -1) {break;}String s = new String(buffer,0,n);//System.out.println(s);for (int i = 0; i < n; i++) {System.out.print(buffer[i]);System.out.print(" ");}}} catch (IOException e) {throw new RuntimeException();}}
}

Writer

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;public class demo11_0527 {public static void main(String[] args) {try (Writer writer = new FileWriter("./test.txt",true)) {String s = "你好!!!";writer.write(s);} catch (IOException e) {throw new RuntimeException(e);}}
}

Scanner

使用 Scanner 也可以实现读文件

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;public class Test{public static void main(String[] args) {try (InputStream inputStream = new FileInputStream("./test.txt")){//传一个文件输入流Scanner scanner = new Scanner(inputStream);while (scanner.hasNext()) {String s = scanner.next();System.out.println(s);}} catch (FileNotFoundException e) {throw new RuntimeException(e);} catch (IOException e) {throw new RuntimeException(e);}}
}

完整使用示例

T1 : 在某个目录下查找文件

import java.io.File;
import java.util.Scanner;public class Test {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);System.out.println("请输入要搜索的文件名:");String filename = scanner.next();System.out.println("请输入要搜索的目录:");String rootPath = scanner.next();File rootfile = new File(rootPath);if (!rootfile.isDirectory()) {System.out.println("路径有误");return;}scanDir(rootfile,filename);}private static void scanDir(File rootfile, String filename) {File[] files = rootfile.listFiles();if (files == null) {return;}for (File f : files) {System.out.println("当前遍历到:" + f.getAbsoluteFile());if (f.isFile()) {if (filename.equals(filename)) {System.out.println("找到了");}} else if (f.isDirectory()) {scanDir(f,filename);} else {}}}
}

T2:文件复制

import java.io.*;
import java.util.Scanner;public class Test {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);System.out.println("请输入要复制的源文件: ");//E:\vs背景\风景.jpgString srcPath = scanner.next();System.out.println("请输入要复制的目标文件: ");//E:\vs背景\风景1.jpgString destPath = scanner.next();File file = new File(srcPath);if (!file.isFile()) {System.out.println("源文件路径有误!");return;}File destFile = new File(destPath);if (!destFile.getParentFile().isDirectory()) {System.out.println("目标路径有误!");return;}try (InputStream inputStream = new FileInputStream(srcPath);OutputStream outputStream = new FileOutputStream(destFile)){while (true) {byte[] buffer = new byte[1024];int n = inputStream.read(buffer);if (n == -1) {break;}outputStream.write(buffer,0,n);}} catch (FileNotFoundException e) {throw new RuntimeException(e);} catch (IOException e) {throw new RuntimeException(e);}}
}

T3:找出包含指定内容的文件

import java.io.*;
import java.util.Scanner;public class Test {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);System.out.println("请输入要搜索的路径: ");String rootPath = scanner.next();System.out.println("请输入要查询的词: ");String word = scanner.next();File rootFile = new File(rootPath);if (!rootFile.isDirectory()) {System.out.println("输入的要搜索的路径不正确!");return;}scanDir(rootFile, word);}public static void scanDir(File rootfile, String word) {File[] files = rootfile.listFiles();if (files == null) {return;}for (File f : files) {System.out.println("【debug】当前遍历到了" + f.getAbsoluteFile());if (f.isFile()) {searchInFile(f,word);} else if (f.isDirectory()) {scanDir(f,word);} else {}}}private static void searchInFile(File f, String word) {try (InputStream inputStream = new FileInputStream(f)){StringBuffer stringBuffer = new StringBuffer();while (true) {byte[] buffer = new byte[1024];int n = inputStream.read(buffer);if (n == -1) {break;}String s = new String(buffer,0,n);stringBuffer.append(s);}System.out.println("[debug] 文件内容: " + stringBuffer);if (stringBuffer.indexOf(word) == -1) {return;}System.out.println("找到了" + word + ":" + f.getAbsoluteFile());} catch (FileNotFoundException e) {throw new RuntimeException(e);} catch (IOException e) {throw new RuntimeException(e);}}
}

相关文章:

  • MySQL 的 super_read_only 和 read_only 参数
  • 深度刨析树结构(从入门到入土讲解AVL树及红黑树的奥秘)
  • AU6825集成音频DSP的2x32W数字型ClaSSD音频功率放大器(替代TAS5825)
  • 机器人变量类型与配置
  • 【maker-pdf 文档文字识别(包含ocr),安装使用完整教程】
  • 论文速读《UAV-Flow Colosseo: 自然语言控制无人机系统》
  • 使用 Akamai 分布式云与 CDN 保障视频供稿传输安全
  • 第二章 2.1 数据存储安全风险之数据存储风险点
  • 视频监控汇聚平台EasyCVR安防小知识:如何通过视频融合平台解决信息孤岛问题?
  • 每日c/c++题 备战蓝桥杯(Cantor 表)
  • AI生态警报:MCP协议风险与应对指南(下)——MCP Host安全
  • 【动手学深度学习】2.4. 微积分
  • AI系统提示词:DeepSeek R1(0528)
  • 基于Python的单斜式ADC建模与仿真分析
  • 【仿生机器人】极具前瞻性的架构——认知-情感-记忆“三位一体的仿生机器人系统架构
  • ubuntu系统安装Pyside6报错解决
  • 大语言模型中的注意力机制详解
  • openssl-aes-ctr使用openmp加速
  • Express教程【001】:Express创建基本的Web服务器
  • 云原生时代 Kafka 深度实践:03进阶特性与最佳实践
  • 磁县网站推广/广告联盟app
  • 北京给网站做系统的公司名称/百度收录权重
  • angularjs 做团购网站/兴安盟新百度县seo快速排名
  • 搭建一个平台需要什么/惠州seo代理商
  • 杭州网站建设设计公司/百度导航和百度地图
  • 重庆网站建站系统哪家好/google浏览器入口