为了账号安全,请及时绑定邮箱和手机立即绑定

在用户生成的 java 中创建/写入大文件的正确方法是什么?

在用户生成的 java 中创建/写入大文件的正确方法是什么?

UYOU 2021-12-18 15:47:58
我查看了一些说明文件写入/创建操作最佳实践的示例,但还没有看到考虑到我的要求的示例。我必须创建一个类来读取 1 个文件的内容,进行一些数据转换,然后将转换后的内容写入不同的文件,然后将文件发送到 Web 服务。这两个文件最终都可能非常大,例如高达 20 MB,而且这些文件的创建时间也是不可预测的,因为它们是由用户生成的。因此,此过程发生的时间之间可能相差 2 分钟,也可能在同一秒内发生多次。从某种意义上说,该系统并没有像在同一秒内进行数百个这样的操作一样疯狂,但也可能是多个。我的直觉告诉我要解决这个问题:在进程开始时创建一个单独的线程。读取第一个文件。进行数据转换。将内容写入新文件。将文件发送到服务。删除创建的文件。我错过了什么吗?是否有解决此类问题的最佳实践?
查看完整描述

3 回答

?
弑天下

TA贡献1818条经验 获得超8个赞

您应该问的第一个问题是您首先需要将文件写入磁盘的天气。即使您应该在处理阶段结束时将文件发送给使用者,您也可以将文件内容保存在内存中并发送。消费者并不关心文件是否存储在磁盘上,因为它只接收包含文件内容的字节数组

将文件存储在磁盘上的唯一情况是如果您通过磁盘文件在进程之间进行通信(即您的生产者将文件写入磁盘,向您的消费者发送一些通知,然后您的消费者读取该文件从磁盘 - 例如基于它从通知收到的文件名)。

关于 I/O 最佳实践,请确保使用缓冲区读取(并可能写入)文件。这可以大大减少内存开销(因为您最终只会在内存中保留一个块而不是整个 20 MB 文件)。

关于添加多个线程,您应该测试天气是否可以提高您的应用程序性能。如果您的应用程序已经是 I/O 密集型的,那么添加多个线程将导致在您的 I/O 流上增加更多的争用,从而导致性能下降。


查看完整回答
反对 回复 2021-12-18
?
忽然笑

TA贡献1806条经验 获得超5个赞

如果没有详细的情况,像这样的问题可能会用现有的软件更好地解决,比如Apache NiFi

一个易于使用、功能强大且可靠的系统来处理和分发数据。

它非常擅长获取文件、转换它们并将它们放在其他地方(以及发送电子邮件、生成分析等等)。NiFi 是一个非常强大的工具,但如果您需要额外设置的几个文件,则可能会有点过分。


查看完整回答
反对 回复 2021-12-18
?
蝴蝶不菲

TA贡献1810条经验 获得超4个赞

鉴于您给出的描述,我认为您应该在一个线程上对每个文件执行操作;即线程将下载文件,处理它,然后上传结果。

如果您需要并行性,则将下载/处理/上传实现为 aRunnable并将任务提交到ExecutorService具有有界线程池的 a 。并调整线程池的大小。(如果您将线程池大小作为配置属性公开,这很容易。)

为什么这样?

  1. 很简单。需要最少的同步。

  2. 三个子任务之一可能是您的性能瓶颈。因此,通过将所有三个任务合并为一个任务,您可以避免非瓶颈任务遥遥领先的情况。如果您在某些子任务上走得太远,您就有可能耗尽(本地)磁盘空间。


我将与 Alex Rolea 关于缓冲的说法相矛盾。是的,它可能会有所帮助。但是在典型现代机器上的现代(例如 Linux)操作系统中,内存 <-> 磁盘 I/O 不太可能是主要瓶颈。瓶颈更有可能是网络 I/O 或服务器端 I/O 性能(特别是如果服务器同时为其他客户端提供服务。)

所以,我不会过早地调整缓冲。使系统正常工作,对其进行基准测试,对其进行概要分析/分析,并根据这些结果找出真正的瓶颈所在以及如何最好地解决它们。

部分解决方案可能是根本不使用磁盘。(我知道您认为您需要这样做,但除非您的服务器及其协议真的很奇怪,否则您应该能够将数据流式传输到客户端内存不足的服务器。)


查看完整回答
反对 回复 2021-12-18
  • 3 回答
  • 0 关注
  • 220 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信