繁体   English   中英

读取/写入Java中的大文件

[英]read/write to a large size file in java

我有以下格式的二进制文件:

[N bytes identifier & record length] [n1 bytes data] 
[N bytes identifier & record length] [n2 bytes data] 
[N bytes identifier & record length] [n3 bytes data]

如您所见,我有不同长度的记录。 在每条记录中,我固定了N个字节,其中包含和id以及记录中数据的长度

该文件非常大,可以包含300万条记录。

我想通过应用程序打开此文件,并允许用户浏览和编辑记录。 (插入/更新/删除记录)

我的最初计划是从原始文件创建文件并为文件建立索引,对于每个记录,保留下一个和上一个记录地址,以轻松地前后导航。 (某种链表,但在文件中不在内存中)

  • 是否有库(java库)可以帮助我实现此要求?

  • 您认为有用的任何建议或经验?

-----------------编辑-------------------------------- --------------

感谢您的指导和建议,

一些更多的信息:

原始文件及其格式超出了我的控制(这是第三方文件),我无法更改文件格式。 但是我必须阅读它,让用户浏览记录并编辑其中的一些记录(插入新记录/更新现有记录/删除记录),最后将其保存回原始文件格式

您是否仍建议使用数据库而不是普通索引文件?

-----------------第二编辑------------------------------- ---------------

更新模式下的记录大小是固定的。 这意味着更新的(编辑的)记录的长度与原始记录的长度相同,除非用户删除该记录并创建另一个具有不同格式的记录。

非常感谢

严重的是,您不应为此使用二进制文件。 您应该使用数据库。

尝试将其作为常规文件实现的问题源于以下事实:操作系统不允许您在现有文件的中间插入额外的字节。 因此,如果您需要插入一条记录(除结尾处之外的任何地方),更新一条记录(使用其他大小)或删除一条记录,则需要:

  • 重写其他记录(在插入/更新/删除点之后)以腾出或回收空间,或者
  • 在文件中实现某种可用空间管理。

所有这些都是复杂和/或昂贵的。

幸运的是,有一类软件可以实现这种功能。 它称为数据库软件。 从使用完整的RDBMS到诸如BerkeleyDB文件的轻量级解决方案,范围广泛。


响应您的第一次和第二次编辑,数据库将仍然更加简单。

但是,这里有可能更好地发挥这个用例比使用DB ...没有做复杂的自由空间管理的替代品。

  1. 读取文件并建立一个将ID映射到文件位置的内存索引。

  2. 创建另一个文件来保存新的和更新的记录。

  3. 执行记录的添加/更新/删除:

    1. 通过将新记录写入第二个文件的末尾并为其添加索引条目来处理添加。

    2. 通过将更新后的记录写入第二个文件的末尾,并更改现有索引条目以指向该文件来处理更新。

    3. 通过删除记录键的索引条目来处理删除。

  4. 压缩文件,如下所示:

    1. 创建一个新文件。

    2. 依次读取旧文件中的每条记录,并检查记录键的索引。 如果条目仍然指向记录的位置,请将记录复制到新文件。 否则跳过它。

    3. 对第二个文件重复步骤4.2。

  5. 如果我们成功完成了上述所有操作,请删除旧文件和第二个文件。

请注意,这依赖于能够将索引保留在内存中。 如果那不可行,那么实现将变得更加复杂……更像是数据库。

拥有数据文件和索引文件将是这种实现的基本概念,但是您会发现自己经常在重复数据更新/删除等过程中处理数据碎片。这种项目本身应该是一个单独的项目,不应属于您的主应用程序。 但是,从本质上讲,数据库正是您所需要的,因为它是专门为此类操作和用例设计的,并且还允许您搜索,排序和扩展(更改)数据结构,而无需重构内部(自定义)解。

我可以建议您下载Apache Derby并创建一个本地嵌入式数据库(derby这样做是为了您希望在运行时创建一个新的嵌入式连接)。 它不仅会比您自己编写的任何东西都要快,而且会使您的应用程序更易于维护。

Apache Derby是一个jar文件,您可以简单地将其包含在项目中并随项目一起分发(如果您的应用程序中可能存在任何法律问题,请检查许可证 )。 无需数据库服务器或第三方软件; 全部都是纯Java。

总而言之,这取决于应用程序的大小,是否需要在许多客户端之间共享数据,速度是否是应用程序的关键方面等。

对于独立的单用户项目,我建议使用Apache Derby。 对于n层应用程序,您可能需要研究MySQLPostgreSQL什至Oracle的hrm )。 使用已经制造和测试的解决方案不仅很聪明,而且可以减少您的开发时间(和维护工作)。

干杯。

通常,最好让库或数据库为您完成工作。

您可能不想拥有SQL数据库,并且有很多不使用SQL的简单数据库。 http://nosql-database.org/列出了其中的122个。

至少,如果要编写这篇文章,建议您阅读这些数据库之一的源代码,以了解它们如何工作。


根据记录的大小,300万不是那么多,我建议您在内存中保留尽可能多的内存。

您可能遇到的问题是确保数据一致,并在发生损坏时恢复数据。 第二个问题是有效地处理碎片(在GC上最聪明的人正在处理的事情)第三个问题可能是与源数据以事务方式维护索引,以确保没有不一致。

虽然这乍看起来很简单,但是要确保数据可靠,可维护并且可以有效访问,就存在很大的复杂性。 这就是为什么大多数开发人员使用现有的数据库/数据存储库并专注于对他们的应用程序不利的功能的原因。

(注意:我的回答是关于一般问题的,不考虑任何Java库,也未考虑其他提议的问题,而是使用数据库(库),这可能比重新发明轮子要好)

创建索引的想法很好,并且在性能方面非常有用(尽管您编写了“索引文件”,但我认为应该将其保存在内存中)。 如果您读取ID并记录每个条目的长度,然后仅使用文件搜索跳过数据,则生成索引应该会非常快。

您还应该考虑编辑功能。 如果您做错了,尤其是在这样大的文件上插入和删除可能会非常慢(例如删除然后移动以下所有条目以缩小间隔)。

最好的选择是仅将已删除的条目标记为已删除。 插入时,您可以覆盖其中之一或附加到文件末尾。

插入/更新/删除记录

在文件中插入(而不是仅仅添加和删除)记录非常昂贵,因为您必须移动文件的以下所有内容来为新记录创建空间或删除其使用的空间。 如果更新更改了记录的长度(您说它们是可变长度),则更新的代价同样昂贵。

您建议的文件格式从根本上来说不适合您要执行的操作类型。 其他人建议使用数据库。 如果您不想走那么远,可以按照您的建议添加索引文件。 我建议使索引记录的长度都相同。

正如其他人所说, 数据库似乎是一个更好的解决方案。 以下是可以使用的Java SQL DB: H2DerbyHSQLDB

如果要使用索引文件,请查看Berkley DBNo Sql

如果出于某些原因使用文件,请查看JRecord 它有

  1. 几种用于读取/写入具有可变长度二进制记录的文件的类(在为Cobol VB文件编写的地方)。 任何大型机/富士通/ Open Cobol VB文件结构都可以完成此工作。
  2. 用于编辑JRecord文件的编辑器。 最新版本的编辑器可以处理大文件(它使用压缩/溢出文件)。 编辑者不得不下载整个文件,并且一次只能有一个用户编辑文件。

JRecord解决方案仅在以下情况下有效

  • 有限的(最好是一个)用户全部位于一个位置
  • 快速的信息结构

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM