2011-04-01 52 views
8

大尺寸文件,我有以下格式的二进制文件:读/写在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个字节,其中包含和编号为的数据长度为

这个文件很大,可以包含3百万条记录。

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

我最初的计划是创建和索引文件从原始文件和每个记录,保持下一个和前一个记录地址轻松前进和后退导航。 (某种链接列表,但文件不在内存中)

  • 是否有库(java库)来帮助我实现这个要求?

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

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

感谢指导和建议,

一些更多的信息:

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

你还在推荐使用DataBase而不是普通的索引文件吗?

----------------- SECOND EDIT --------------------------- -------------------

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

非常感谢

+5

使用数据库中的JRecord溶液才起作用。甚至连sqlite也能让你安心使用这么多的数据。 – 2011-04-01 11:17:00

+0

似乎像向前导航已经很简单,但后向和随机访问不是。你想完成什么?您希望用户能够编辑记录,但是性能是一个问题? – JackWilson 2011-04-01 11:17:38

+0

@JackWilson:是的,正如你所说的,向前导航很简单,但是向后是一个问题,这就是我用自定义格式思考索引文件的方法。 – mhshams 2011-04-04 02:07:02

回答

2

说真的,你不应该使用这个二进制文件。你应该使用一个数据库。

试图将其作为常规文件实现的问题源于操作系统不允许您将额外字节插入到现有文件中。所以,如果你需要插入一条记录(任何地方,但年底),更新记录(具有不同大小)或删除记录,你将需要:

  • 重写其他记录(后添加/更新/删除点)制作或回收空间,或
  • 在文件内部实现某种空闲空间管理。

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

幸运的是,有一类软件实现了这种事情。它被称为数据库软件。有多种选择,从使用全面的RDBMS到像BerkeleyDB文件这样的轻量级解决方案。


为了回应您的第一次和第二次编辑,数据库仍然会更简单。

然而,这里是一个替代方案,可能执行此用例比使用DB ...没有做复杂的自由空间管理好

  1. 阅读文件,并建立一个内存指数映射的id到文件的位置。

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

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

    1. 加法被写入新的记录到第二个文件末尾,并添加它的索引条目进行处理。

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

    3. 通过删除记录密钥的索引条目来处理删除操作。

  4. 紧凑的文件,如下所示:

    1. 创建一个新文件。

    2. 阅读旧文件中的每条记录的顺序,并检查记录的关键指标。如果条目仍指向记录的位置,请将记录复制到新文件中。否则,跳过它。

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

  5. 如果我们完成了前面的成功,删除旧文件和第二个文件。

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

+0

请看看编辑后的版本。你是否仍然认为DB是更好的解决方案? – mhshams 2011-04-02 16:24:37

1

一般来说,你是关闭让库或数据库做的工作对你更好。

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

至少,如果你要写这个,我建议你阅读其中一个数据库的来源,看看它们是如何工作的。


根据记录的大小,300万是没有那么多,我建议你保持尽可能多的内存。

您可能遇到的问题是确保数据一致并在发生损坏时恢复数据。第二个问题是高效地处理碎片问题(在GC中处理最明智的问题)第三个问题可能是以源数据的交易方式维护索引以确保没有不一致。

尽管这看起来很简单,但确保数据的可靠性,可维护性以及可以高效地访问都有很大的复杂性。这就是为什么大多数开发人员使用现有的数据库/数据存储库并专注于应用程序所不具备的功能。

0

(注:我的答案是大约在一般情况下,不考虑任何Java库或问题 - 像其他的答案也建议 - 使用一个数据库(库),这可能是比重新发明轮子更好)

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

你也应该想想编辑功能。特别是插入和删除在如此大的文件上可能会非常慢,如果你做错了(例如,删除,然后移动所有下列条目来缩小差距)。

最好的办法是只大关删除的条目删除。插入时,可以覆盖其中的一个或追加到文件的末尾。

2

有一个数据文件和一个索引文件将是这种实现的基本思路,但是你几乎发现自己在重复数据更新/删除时处理数据碎片等。这种类型的项目,在本身,应该是一个单独的项目,不应该是你的主要应用程序的一部分。然而,从本质上讲,数据库是你所需要的,因为它是专门为这样的操作设计和使用的情况下,也可以让你搜索,排序和扩展(改变)你的数据结构,而无需重构一个内部的(自定义)解。

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

Apache Derby是一个单独的jar文件,您可以在项目中简单地包含和分发这些文件(如果在您的应用程序中可能存在任何法律问题,请检查license)。不需要数据库服务器或第三方软件;它都是纯Java。

底线为这一切都取决于有多大你的应用程序,如果你需要共享跨多个客户的数据,如果速度是你的应用程序的一个重要方面,等

对于单机,单用户项目,我推荐Apache Derby。对于n-tier应用程序,您可能需要查看MySQLPostgreSQL或(hrm)甚至Oracle。使用已经制造并经过测试的解决方案不仅非常智能,而且会缩短您的开发时间(以及维护工作)。

干杯。

0

插入/更新/删除记录

插入(而不是仅仅追加)和删除记录到文件中是昂贵的,因为你要移动的文件的全部内容如下,为创造空间新记录或删除它使用的空间。如果更新更改记录的长度(如果它们是可变长度),更新同样很昂贵。

您提出的文件格式基本上不适合您要执行的操作种类。其他人则建议使用数据库。如果你不想这么做,那么添加一个索引文件(如你所建议的)就是要走的路。我建议使索引记录的长度相同。

0

正如其他人所说的数据库似乎是一个更好的解决方案。如果你想如果有某种原因到对使用文件使用一个索引文件看Berkley DBNo Sql

,看JRecordH2DerbyHSQLDB

:下面是Java的SQL数据库的可用于。它有

  1. 用于读/写文件的可变长度二进制记录(它们为Cobol VB文件编写的)的几个类。任何Mainframe/Fujitsu/Open Cobol VB文件结构都应该完成这项工作。
  2. 编辑编辑JRecord文件。最新版本的编辑器可以处理大文件(它使用压缩/溢出文件)。编辑器不得不下载整个文件,只有一个用户可以一次编辑文件。

如果

  • 有一个有限数量(优选一个)用户全部位于一个位置
  • 快速信息结构