2011-04-01 55 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文件。最新版本的編輯器可以處理大文件(它使用壓縮/溢出文件)。編輯器不得不下載整個文件,只有一個用戶可以一次編輯文件。

如果

  • 有一個有限數量(優選一個)用戶全部位於一個位置
  • 快速信息結構