2014-06-18 56 views
0

所以我希望這個問題已經得不到解答,但我似乎無法弄清楚正確的搜索術語。ruby​​/python中的低級文件處理

首先一些背景: 我有表格式的文本數據文件,可以很容易地爬到10 GB的GB。處理它們的計算機已經從長時間的數據收集(高達30-50MB/s)中大量加載,因爲它正在進行設備處理和控制。因此,磁盤空間和訪問非常重要。由於空間限制,我們還沒有從旋轉磁盤轉移到SSD。

但是,我們正在尋找一些不需要每個數據點的剛剛收集的數據。我們希望能夠減少數據並收集每第1000個點。但是,加載這些文件(每個千兆字節)會給磁盤帶來巨大負載,這是不可接受的,因爲它可能會中斷實時採集系統。

我想知道是否有可能使用低級別的方法訪問文件中的每個第n個字節(或其他方法)(如數據庫一樣),因爲該文件定義得非常好(兩個64位雙精度每一行)。我知道太低的訪問權限可能無法正常工作,因爲硬盤驅動器可能是分散的,但最好的方法/方法是什麼?我更喜歡python或ruby的解決方案,因爲這就是處理的過程,但理論上R,C或Fortran也可以工作。

最後,升級計算機或硬件不是一種選擇,設置系統需要花費數百個工時,因此只能執行軟件更改。但是,這將是一個長期項目,但如果文本文件不是處理這些文件的最佳方式,我也可以接受其他解決方案。

編輯:我們生成(取決於使用情況)從50000行(記錄)/秒到500萬行/秒的任何地方數據庫不可行,無論如何。

+1

爲什麼不直接將數據直接收集到數據庫中? – MattDMo

+0

不幸的是,儀器控制和收集軟件有一個可怕的數據庫接口,速度非常慢,試圖創建一個記錄需要50毫秒,我們每秒產生500萬條記錄。我們可以在完成後將大數據文件放在一個blob中,但這並不能解決我們的問題,因爲數據正在被收集數小時。 – lswim

+1

你在什麼操作系統上?這是一個非常有趣的問題。 –

回答

1

這應該可以通過在文件對象上使用seek和read方法來實現。這樣做會阻止整個文件被加載到內存中,因爲您只能使用文件流。

另外,由於文件的定義和可預測性都很好,因此在向文件中的下一條記錄前進N個字節時不會遇到任何問題。

下面是一個例子。演示下面的代碼在http://dbgr.cc/o

with open("pretend_im_large.bin", "rb") as f: 
    start_pos = 0 
    read_bytes = [] 

    # seek to the end of the file 
    f.seek(0,2) 
    file_size = f.tell() 

    # seek back to the beginning of the stream 
    f.seek(0,0) 

    while f.tell() < file_size: 
     read_bytes.append(f.read(1)) 
     f.seek(9,1) 


print read_bytes 

上面的代碼假定pretend_im_large.bin是與內容的文件:

A00000000 
B00000000 
C00000000 
D00000000 
E00000000 
F00000000 

的代碼的輸出以上是:

['A', 'B', 'C', 'D', 'E', 'F'] 
+1

'f.seek()'保證不讀取任何中間字節?我想這是一個非常依賴平臺的東西。如果'f.seek()'知道如何提前9個字節而不實際讀取9個字節,我會有點驚訝。 –

+0

我想不到一個不支持文件查找的平臺,就像這裏使用的那樣。如果你找到一個,讓我知道?無論在幕後如何實現,關鍵是整個文件不會同時讀入內存(也不是整行)。作爲參考:linux中的lseek方法(http://linux.die.net/man/2/lseek)和窗口中的SetFilePointer方法(http://msdn.microsoft.com/en-us /library/windows/desktop/aa365541(v=vs.85).aspx)和mac上的'lseek'方法(https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/ man2/lseek.2.html) –

+0

僅僅因爲底層的操作系統支持它並不意味着'f.seek'已經以這樣一種利用它的方式實現了。我不認爲Python會提供任何使用這些操作系統功能的保證,所以我會猶豫依靠它(沒有檢查底層C實現或進行廣泛的測試) –

0

我不要以爲Python會給你一個強有力的保證,當你使用012時它不會真正讀取整個文件。我認爲這對於依賴於Python的平臺和特定實現來說太具有挑戰性了。您應該使用特定於Windows的工具,這些工具可以爲您提供隨機訪問而不是順序訪問的保證。

Here's a snippet of Visual Basic您可以修改以滿足您的需求。您可以定義自己的記錄類型,它是兩個64位整數長。或者,您可以使用C# FileStream object並使用其seek方法獲得您想要的。

如果這是性能至關重要的軟件,我認爲您需要確保您可以訪問所需的操作系統原語。我找不到任何表明Python的seek將會做你想做的任何引用。如果你走這條路線,你需要測試它以確保它看起來應該如此。

0

文件是人類可讀的文本還是以計算機的本機格式(有時稱爲二進制文件)?如果文件是文本,則可以通過切換爲本機格式來減少處理負載和文件大小。從浮點數的內部表示轉換爲人類閱讀數字是CPU密集型的。

如果文件是原生格式,那麼它應該很容易在文件中跳過,因爲每個記錄都是16個字節。在Fortran中,用包含form="unformated", access="direct", recl=16的公開聲明打開文件。然後,您可以在讀取語句中讀取任意記錄X,而不通過rec=X讀取中間記錄。如果文件是文本,您也可以直接讀取它,但它可能不是每兩個數字總是使用相同數量的字符(字節)。你可以檢查你的文件並回答這個問題。如果記錄總是相同的長度,那麼你可以使用相同的技術,只需要form="formatted"。如果記錄的長度不同,那麼您可以閱讀一個大塊並在大塊中找到您的數字。