java中的文件操作

基础知识

1.File类对象的常用方法

一、 创建文件和目录
1.createNewFile()
用于创建一个新的文件,如果文件已经存在,则返回 false
File file = new File("C:\\Users\\P51\\Desktop\\file.txt");
file.createNewFile();
2.mkdir()
用于创建一个单一目录,无法创建不存在的父级目录的目录
File file = new File("C:\\Users\\P51\\Desktop\\files");
file.mkdir();
3.mkdirs()
创建目录以及所有不存在的父目录。如果目录已经存在,返回false
File file = new File("C:\\Users\\P51\\Desktop\\files\\test\\testa");
file.mkdirs();二、删除文件或目录
1.delete()
删除文件或空目录。删除成功返回 true,失败返回 false2.deleteOnExit()
文件在 JVM 退出时自动删除。删除临时文件的方法三、获取文件和目录信息
1.exists()
检查文件或目录是否存在。
2.isFile()
判断文件是否为普通文件。
3.isDirectory())
判断是否为目录。
4.length()
返回文件的字节长度。对于目录,返回 05.lastModified())
返回文件最后修改的时间,单位为毫秒。
6.getName()
获取文件或目录的名称。
7.getAbsolutePath()
获取文件或目录的绝对路径。
8.getParent()
获取文件的父目录路径。四、列出目录中的文件
1.file.listFiles()
返回目录中所有文件和子目录的 File 对象数组。
2.file.list()
方法仅返回目录下的文件名(不包括文件的属性)。这个方法通常比 listFiles() 更快速,因为它只返回文件名字符串,而不返回File 对象。
五、文件权限操作
1.setReadable(boolean readable)设置文件是否可读。
2.setWritable(boolean writable)设置文件是否可写。
3.setExecutable(boolean executable)设置文件是否可执行。(一般指的是脚本文件)
六、文件路径相关操作
1.renameTo(File dest)
重命名文件或将文件移动到目标路径。如果重命名成功,返回 true
2.toURI()获取文件的 URI

2.File类的静态方法

//创建临时文件
File tempFile = File.createTempFile("test", ".txt", new File("C:\\Users\\P51\\Desktop\\files\\test\\testa"));
//这里就可以调用以下方法,该方法会在JVM 退出时自动删除文件
tempFile.deleteOnExit();

一、将数据作为文件保存到本地(序列化)

Java 序列化是一种将对象状态转换为字节序列的过程,以便可以将其持久化到磁盘或通过网络发送到其他 JVM 实例。序列化是 Java 的一种内置机制,它允许你将对象转换为字节流,之后可以将这些字节流重新转换回对象。

步骤

1.实现 Serializable 接口

要使一个类的对象可序列化,该类需要实现 java.io.Serializable 接口。这是一个标记接口,不包含任何方法。

2. serialVersionUID

为了确保序列化和反序列化过程中的版本兼容性,建议在类中声明一个名为 serialVersionUID 的静态常量。如果类在序列化后被修改,而没有更新这个版本号,反序列化时可能会抛出InvalidClassException。

public class MyClass implements Serializable {private static final long serialVersionUID = 1L;private int id;private String name;// 构造函数、getter 和 setter}
3.定义输出编码格式(GBK,UTF-8等)进行输出
3.1基本的文件输出流(OutputStream)

使用 FileOutputStream 时,可以在写入数据之前将字符串转换为字节数组,并指定编码格式。

在 getBytes() 方法中传入 charset 参数来指定编码格式

public static void main(String[] args) {String data = "Hello, world!";String filePath = "path/to/your/output.txt";String charset = "UTF-8"; // 指定编码格式try (OutputStream outputStream = new FileOutputStream(filePath)) {byte[] bytes = data.getBytes(charset);outputStream.write(bytes);System.out.println("File exported successfully.");} catch (IOException e) {e.printStackTrace();} finally{outputStream.close();        }}
3.2BufferedWriter 和 FileWriter(推荐使用)

这种方法在处理大量数据时性能表现较好,因为它们使用了缓冲机制,可以减少频繁的磁盘访问。

在 OutputStreamWriter 的构造函数中传入 charset 参数来指定编码格式。

public static void main(String[] args) {String filePath = "path/to/your/output.txt";String charset = "UTF-8"; // 指定编码格式try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath), charset))) {writer.write("Line 1\n");writer.write("Line 2\n");writer.write("Line 3\n");System.out.println("File exported successfully.");} catch (IOException e) {e.printStackTrace();} finally{//关闭流write.close();        }}

demo示例

List<ClientLog> clientLogList = clientLogRepository.findAll();
DateTimeFormatter simpleDateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH-mm-ss");
String fileFullPath;
if(startDate != null && endDate != null) {fileFullPath = downloadPath + File.separator + "log-client" + File.separator +simpleDateFormat.format(startDate) + "-" + simpleDateFormat.format(endDate) + ".txt";
}else {fileFullPath = downloadPath + File.separator + "log-client" + File.separator +simpleDateFormat.format(LocalDateTime.now()) + ".txt";
}
File file = new File(downloadPath + File.separator + "log-client");
if(!file.exists()){file.mkdir();
}
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileFullPath), "GBK"));
StringBuilder stringBuilder = new StringBuilder();
for (Object line:clientLogList){//JSON解析,按需添加//String jsonString = JSON.toJSONString(line);stringBuilder.append(jsonString).append("\n");
}
writer.write(stringBuilder.toString());
//使用完流要关闭,否则可能没有内容
writer.close();

二、读取本地的指定文件内容并返回给前端文件流

步骤

1.读取文件

按照文件路径来进行读取。

注意读取指定文件时一定把文件名写全包括文件的后缀(txt,pdf,json等)

String filePath = "path_to_your_file"; 
// 替换为你的文件路径File file = new File(filePath);
方式1:使用 java.io 包(将内容存储为缓冲输入流
String filePath = "path_to_your_file.txt";try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF-8"))) {String line;while ((line = reader.readLine()) != null) {System.out.println(line);}} catch (IOException e) {e.printStackTrace();}
方式2:使用 java.nio.file 包(将内容存储为集合)
String filePath = "path_to_your_file.txt";try {List<String> lines = Files.readAllLines(Paths.get(filePath));for (String line : lines) {System.out.println(line);}} catch (IOException e) {e.printStackTrace();}
方式3:如果需要读取整个文件为字节数组(适用于二进制文件)

可以使用Files.readAllBytes 方法。

String filePath = "path_to_your_file.bin";try {byte[] bytes = Files.readAllBytes(Paths.get(filePath));System.out.println("File size: " + bytes.length + " bytes");} catch (IOException e) {e.printStackTrace();}
方式4:使用 java.util.Scanner
 String filePath = "path_to_your_file.txt";try (Scanner scanner = new Scanner(new File(filePath))) {while (scanner.hasNextLine()) {System.out.println(scanner.nextLine());}} catch (FileNotFoundException e) {e.printStackTrace();}
方式5: 使用第三方库如 Apache Commons IO
String filePath = "path_to_your_file.txt";File file = new File(filePath);try {List<String> lines = FileUtils.readLines(file, "UTF-8");for (String line : lines) {System.out.println(line);}} catch (IOException e) {e.printStackTrace();}
2.文件读取和返回
2.1检查文件是否存在

.exists()

if (file.exists()) { ... }
2.2设置响应类型和头部信息

这两行代码告诉浏览器返回的内容是一个二进制流,同时指定了下载文件时的文件名。

response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=" + file.getName());

响应类型(即MIME类型):常见 MIME 类型列表 - HTTP | MDN (mozilla.org)

application/x-download 是一种被废弃的 MIME 类型,用于指示要下载的文件类型。它在过去被广泛使用,但现在已经不推荐使用了。

MIME(Multipurpose Internet Mail Extensions)是一种互联网标准,用于标识文档的性质和格式。MIME类型通常由一种主要类型和一个子类型组成,中间使用斜杠分隔。主要类型表示文档的大类,例如文本、图像、音频等,而子类型则表示特定类型的细分,比如文本类型可以进一步细分为HTML、XML等。

MIME类型在互联网上的应用非常广泛,最常见的用途之一是通过HTTP协议来指示服务器发送的文件类型。这对于浏览器正确解释和展示不同类型的文件至关重要,比如指示浏览器一个链接指向的是图片、视频、文本还是其他类型的文件。

除了在Web开发中的应用外,MIME类型还被用于电子邮件系统中,以标识附件的类型,并确保接收者能够正确地打开或处理这些附件。MIME类型的标准化使得不同系统之间能够准确地识别和处理各种类型的文档,提高了互操作性和信息交换的可靠性。

2.3创建输入流和输出流

使用文件的输入流读取文件内容,然后使用响应的输出流将文件内容写入响应中。

 try (InputStream inputStream = new FileInputStream(file);
OutputStream outputStream = response.getOutputStream());
2.4通过循环读取和写入数据实现文件流返回

这个循环从输入流中读取数据到缓冲区,然后将数据写入到响应的输出流中。

 byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = inputStream.read(buffer)) != -1) {outputStream.write(buffer, 0, bytesRead);}
问题:为什么不能直接将输入流的数据写入到响应流中,而是需要使用缓冲区。

原因解析:

1.提高传输效率:

使用缓冲区可以减少 I/O 操作的次数,提高数据传输的效率。每次从输入流读取一定大小的数据块,然后再写入输出流,比每次只读写一个字节要高效得多。

2.减少系统调用次数:

每次对流进行读写操作都会涉及到系统调用,这些调用是有开销的。如果每次只读写一个字节,将会产生大量的系统调用,导致程序性能下降。使用缓冲区一次处理多个字节,可以显著减少系统调用次数。

3.兼容性和可移植性:

不同的底层实现可能对单字节读写操作有不同的优化程度。使用缓冲区适应性更强,能保证在各种环境下都能高效运行。

4.代码简洁性和可读性:

使用缓冲区使代码更加简洁明了,逻辑清晰。直接逐字节操作不仅繁琐,而且容易引入错误。

示例代码
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;public class StreamCopyUtil {public static void copyStream(InputStream inputStream, OutputStream outputStream) throws IOException {byte[] buffer = new byte[4096];int bytesRead;while ((bytesRead = inputStream.read(buffer)) != -1) {outputStream.write(buffer, 0, bytesRead);}}
}
缓冲区的作用

1.缓冲区大小:

在上面的例子中,缓冲区大小为 4096 字节(4KB)。这个大小是一个折衷,既不会太小以至于频繁地调用系统 I/O 操作,也不会太大造成不必要的内存占用。具体大小可以根据实际应用场景调整。

2.循环读取和写入:

循环读取输入流中的数据到缓冲区,然后将缓冲区中的数据写入输出流。每次读取和写入的字节数由 read() 方法返回的字节数决定。

直接逐字节操作的缺点

如果不使用缓冲区,直接逐字节操作的代码如下:

javaCopy Codepublic static void copyStreamUnbuffered(InputStream inputStream, OutputStream outputStream) throws IOException {int byteData;while ((byteData = inputStream.read()) != -1) {outputStream.write(byteData);}
}

这种方法虽然也能完成任务,但由于每次只读写一个字节,会造成频繁的系统调用,导致性能低下。

总结

使用缓冲区来进行数据传输是一种常见且有效的优化方式,可以显著提高数据传输的效率,减少系统调用的开销,并使代码更加简洁和易于维护。这也是为什么在实际开发中,通常会看到使用缓冲区来处理输入流和输出流的操作。

2.5 关闭流

关闭流是非常重要的,因为它可以释放系统资源并确保数据完全写入。在实际开发中,为了避免资源泄漏和确保数据完整性,我们应该在使用完流之后及时关闭它们。

这里在使用BufferedWriter写入文件时没有内容就是因为没有关闭流导致写入是无效的,因此一定要关闭流。(本人就因为忘记关闭流而导致写入的文件内容为空)。

JAVA-BufferedWriter写入文件没有内容_bufferedwriter写入后为空-CSDN博客

inputStream.close();
outputStream.flush();
outputStream.close();

在处理输出流时,除了关闭流以外,有时还需要使用 flush() 方法。

flush() 方法的作用是将缓冲区中的数据强制写出到目标设备(如文件、网络等)中。这个方法在某些情况下非常重要,例如在进行网络通信时,需要确保数据被及时发送出去。

关闭流时自动 flush。需要注意的是,当你调用 close() 方法关闭输出流时,流会自动调用 flush() 方法。所以,在大多数情况下,只要在完成写入操作后正确地关闭流,就已经隐式地完成了 flush 操作。

demo示例

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String filePath = "C:\Users\P51\Desktop\files\test.txt"; // 替换为你的文件路径File file = new File(filePath);if (file.exists()) {response.setContentType("application/octet-stream");response.setHeader("Content-Disposition", "attachment; filename=" + file.getName());//不是非必要response.setHeader("Content-Length", String.valueOf(file.length()));try (InputStream inputStream = new FileInputStream(file);OutputStream outputStream = response.getOutputStream()) {byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = inputStream.read(buffer)) != -1) {outputStream.write(buffer, 0, bytesRead);}}//一定要关闭流,不要忘记!!!!!inputStream.close();outputStream.flush();outputStream.close();} else {response.getWriter().write("File not found");}}

最后祝大家新的一年,事业有成,学有所成!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/498659.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【SpringMVC】拦截器

拦截器&#xff08;Interceptor&#xff09;是一种用于动态拦截方法调用的机制。在 Spring MVC 中&#xff0c;拦截器能够动态地拦截控制器方法的执行过程。以下是请求发送与接收的基本流程&#xff1a; 当浏览器发出请求时&#xff0c;请求首先到达 Tomcat 服务器。Tomcat 根…

python使用PyQt5,整套,桌面应用

安装 安装 pip install PyQt55.7.1 pip install PyQtWebEngine1、创建窗口&#xff0c;按百分比划分 from PyQt5.QtGui import QGuiApplication from PyQt5.QtWidgets import QApplication, QWidget # 创建应用程序实例 app QApplication([]) # 创建主窗口 window QWidget(…

018-spring-基于aop的事务控制

1 先配置平台事务管理器 2 在配置 spring提供的advice 3 事务增强的aop 总结&#xff1a; 事务就是要做2个配置&#xff1a; <!-- 1 开启事务管理器 不同的框架对应不同的事务管理器 --> <bean id"transactionManager" class"org.springframework.j…

《向量数据库指南》——Milvus Cloud 2.5:Sparse-BM25引领全文检索新时代

Milvus Cloud BM25:重塑全文检索的未来 在最新的Milvus Cloud 2.5版本中,我们自豪地引入了“全新”的全文检索能力,这一创新不仅巩固了Milvus Cloud在向量数据库领域的领先地位,更为用户提供了前所未有的灵活性和效率。作为大禹智库的向量数据库高级研究员,以及《向量数据…

2025决战智驾:从中阶卷到L3,车企需要抓好一个数据闭环

作者 |王博 编辑 |德新 全国都能开之后&#xff0c;智驾继续走向哪里&#xff1f; 2024年末&#xff0c;大部分主流车企已经实现了无&#xff08;高精度&#xff09;图全国都能开。而第一梯队的玩家&#xff0c;从以规则为主的算法框架&#xff0c;向神经网络模型为主的新架构…

优化大肠杆菌菌株和发酵工艺以提高L-赖氨酸生产-文献精读94

Optimizing Escherichia coli strains and fermentation processes for enhanced L-lysine production: a review 优化大肠杆菌菌株和发酵工艺以提高L-赖氨酸生产&#xff1a;综述 对比酵母酵母中de novo生物合成啤酒花活性类黄酮黄腐醇-文献精读93-CSDN博客 赖氨酸是一种重要…

如何在 Ubuntu 22.04 上安装 Varnish HTTP 教程

简介 在本教程中&#xff0c;我们将学习如何在 Ubuntu 22.04 服务器上安装和配置 Varnish HTTP。 Varnish 是一款高性能的 HTTP 加速器&#xff0c;旨在提高内容密集型动态网站的速度。它通过将网页缓存在内存中来工作&#xff0c;从而减少 Web 服务器的负载&#xff0c;并显…

CPT203 Software Engineering 软件工程 Pt.5 软件测试(中英双语)

文章目录 8. 软件测试8.1 Testing&#xff08;测试&#xff09;8.1.1 A note of testing under the V & A framework8.1.2 The Basics8.1.3 The Goals8.1.4 The Stages 8.2 Developing testing&#xff08;开发测试&#xff09;8.2.1 Unit testing&#xff08;单元测试&…

STM32配合可编程加密芯片SMEC88ST的防抄板加密方案设计

SMEC88ST SDK开发包下载 目前市场上很多嵌入式产品方案都是可以破解复制的&#xff0c;主要是因为方案主芯片不具备防破解的功能&#xff0c;这就导致开发者投入大量精力、财力开发的新产品一上市就被别人复制&#xff0c;到市场上的只能以价格竞争&#xff0c;最后工厂复制的产…

springcloud各个组件介绍

Spring Cloud 是一系列框架的集合&#xff0c;它基于 Spring Boot 提供了在分布式系统&#xff08;如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话和集群状态&#xff09;中快速构建一些常见模式的工具。下面是对 Sprin…

AAAI 2025论文分享┆一种接近全监督的无训练文档信息抽取方法:SAIL(文中附代码链接)

本推文详细介绍了一篇上海交通大学乐心怡老师课题组被人工智能顶级会议AAAI 2025录用的的最新论文《SAIL: Sample-Centric In-Context Learning for Document Information Extraction》。论文的第一作者为张金钰。该论文提出了一种无需训练的、以样本为中心的、基于上下文学习的…

基于JSP的健身俱乐部会员管理系统的设计与实现【源码+文档+部署讲解】

基于JSP的健身俱乐部会员管理系统的设计与实现 摘 要 目前我国虽然己经开发出了应用计算机操作的健身俱乐部管理系统&#xff0c;但管理软件&#xff0c;管理方法和管理思想三者往往相脱节。造成我国健身俱乐部信息管理系统极端化的缺陷。在国外健身俱乐部已经有了一整套涉猎了…

2024 年度总结

时光荏苒&#xff0c;2024 年即将画上句号&#xff0c;回顾这一年的写博历程&#xff0c;有付出、有收获、有成长&#xff0c;也有诸多值得回味与反思的瞬间。 一、内容创作 主题涉猎&#xff1a;这一年&#xff0c;我致力于探索多样化的主题&#xff0c;以满足不同读者群体的…

SonarQube相关的maven配置及使用

一、maven 全局配置 <settings><pluginGroups><pluginGroup>org.sonarsource.scanner.maven</pluginGroup></pluginGroups><profiles><profile><id>sonar</id><activation><activeByDefault>true</acti…

Python用K-Means均值聚类、LRFMC模型对航空公司客户数据价值可视化分析指标应用|数据分享...

全文链接&#xff1a;https://tecdat.cn/?p38708 分析师&#xff1a;Yuling Fang 信息时代的来临使得企业营销焦点从产品中心转向客户中心&#xff0c;客户关系管理成为企业的核心问题&#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。 客户关系管理的关键是客…

委外加工业务如何调整原材料的消耗-MIGO A11-后续调整

业务背景&#xff1a;用户反馈委外加工业务回收后&#xff0c;产品已经销售&#xff0c;但委外加工结算时要对原材料消耗时行调整。如果没有销售&#xff0c;准备采用收货冲销后重新收货&#xff0c;但现在已经是2024年最后一天了。。。销售业务已经做完。不可能再冲销。其实这…

工作中常用Vim的命令

Hi, 我是你们的老朋友&#xff0c;主要专注于嵌入式软件开发&#xff0c;有兴趣不要忘记点击关注【码思途远】 目录 0. ctags -R 1.认识 Vim的几种工作模式 2.高频使用命令 2.1 修改文件 2.2 关于行号 2.3 删除多行&#xff0c;删除部分 2.4 复制粘贴 2.5 光标移动 2.…

2、redis的持久化

redis的持久化 在redist当中&#xff0c;高可用的技术包括持久化&#xff0c;主从复制&#xff0c;哨兵模式&#xff0c;集群。 持久化是最简单的高可用的方法&#xff0c;作用就是备份数据。即将数据保存到硬盘&#xff0c;防止进程退出导致数据丢失。 redis持久化方式&…

QT----------常用界面组件的使用

一、QComboBox 类 主要功能&#xff1a;提供一个下拉列表&#xff0c;用户可以从中选择一个或多个选项。 #include <QApplication> #include <QComboBox> #include <QVBoxLayout> #include <QWidget> #include <QMessageBox>int main(int argc…

【GridView渐进全解】第四部分GridView分页进阶

目录 一、启用分页 二、修改GridView分页模板 1.进入控件模板修改视图&#xff1a; 2.进入页码模板&#xff08;PagerTemplate&#xff09;视图 3.添加导航按钮控件 4.修改导航控件属性 三、输入页号跳转 1.进入页码模板视图 2.添加文本框及按钮控件 3.编写代码 【接…