2011-08-08 26 views
1

我有幾個(1-5)非常寬(〜50,000列).csv文件。文件大小(.5GB-1GB)(平均大小約500MB)。我需要對預先指定的列上的文件執行連接。效率當然是關鍵。任何可以擴展以有效地允許多個連接列的解決方案都是一種獎勵,儘管目前尚不需要。下面是我輸入:如何使用C/C++有效地連接巨大的csv文件(1000列x 1000行)?

-Primary文件

-secondary文件(S)

主文件(名稱或山坳位置。)

輔助文件 - 加入柱 - 加入柱(姓名或職位)

-Left加入或內部加入?

輸出= 1個文件與多文件的結果加入

我期待解決使用基於C語言的問題,但當然的算法解決方案也將是非常有益的。

+3

「Yikes」是我可以貢獻給這一個... – Alex

+3

有一個C++實現已經這樣做:http://code.google.com/p/csvfix/該源可供下載。 – Cheesebaron

+0

如果你的CSV文件很簡單(不需要引用,沒有逗號),而且你在Linux世界,你可以通過剪切,粘貼和排序來獲得 - 無需編寫C代碼。 – Arkadiy

回答

1

如果您需要使用C或C++,請打開該文件並將該文件直接加載到數據庫(如MySQL)中。 C和C++語言沒有足夠的數據表結構,也沒有用於處理數據的功能。電子表格應用程序可能很有用,但可能無法處理這些能力。

這就是說,我建議每個字段(列)的對象。將一個記錄(文件特定)定義爲字段集合。從文件讀取文本行到字符串。讓記錄從字符串中加載字段數據。將記錄存儲到vector

爲目標文件創建新記錄。對於來自輸入文件的每條記錄,使用這些字段加載新記錄。最後,對於每個記錄,使用分隔字符打印每個字段的內容。

另一種方法是掀起一個2維矩陣的矩陣。

您的性能瓶頸將是I/O。您可能想要讀取大量數據。效率的刺激是CSV文件的可變記錄長度。

我仍然建議使用數據庫。有很多免費的,如MySQl。

2

到目前爲止,你最好的選擇就像Sqlite,它有C++的綁定,它是爲照明快速插入和查詢量身定做的。

爲了實際讀取數據,您可以逐行訪問並在Sqlite中插入字段,不需要緩存破壞對象的對象:)作爲優化,您應該將多個插入操作合併到一個語句中(insert into table(...) select ... union all select ... union all select ...)。

+0

如果您打算使用SQLite,請注意'SQLITE_MAX_COLUMN'默認爲2000,所以您可能會遇到大約50k列的問題。它可以在編譯時設置爲最多32,767列。請參閱https://sqlite.org/limits.html – captainpete

0

這取決於你的意思是「加入」。文件1中的列是否與文件2中的相同?如果是這樣,你只需要一個合併排序。基於合併排序的解決方案很可能是「最好的」。但是我同意上面的@Bindy,你應該使用像Sqlite這樣的現有工具。這樣的解決方案可能更適合未來對列列表的更改。

3

假設你有一個很好的理由不使用數據庫(據我所知,這5萬列可能構成這樣一個原因),你可能別無選擇,只能咬緊牙關,爲自己建立一個索引文件。依次讀取它以填充散列表,其中每個條目僅包含鍵列和整個行開始的文件中的偏移量。索引本身應該很好地適應內存,如果你有足夠的地址空間(即,除非你被32位地址卡住),你應該對實際的文件數據進行內存映射,這樣你就可以訪問和輸出適當的行就像順着離開文件一樣。

+0

實際上,我將在32位體系結構上執行此操作。我的用戶預計不會超過32位或超過2GB的總內存。我認爲你必須對每個文件進行內存映射是正確的,因爲我可以有兩個以上的文件來執行加入/合併。你認爲我仍然可能用完地址空間?......是不是內存映射點? – Joel

+0

不知道如何不用完地址將是mmapping的點。如果映射5 GB,則32位地址中沒有足夠的位來告訴哪個字節要訪問哪個文件。在32位體系結構中,通常只有2 GB的用戶空間地址,這些地址受到在請求mmap之前已經映射的東西的影響。所以我會說這是一個折騰,你是否能夠mmap甚至一個1 GB的文件。您仍然可以在內存中使用索引,但是您必須在文件中來回查找記錄。 –

相關問題