2014-02-17 23 views
0

我有一個數據結構,我想讀取和寫入二進制文件中的隨機記錄。我已經嘗試使用NSFileManager/NSFileHandle,並不知道如何將我的數據類型轉換爲它喜歡看到的數據流到文件。我曾嘗試過pread和pwrite類似的問題。我認爲fread和fwrite將是最合適的,並且也有類似的問題。我的代碼很糟糕,不值得發佈。二進制結構到文件中的隨機記錄並再次返回

編輯 - 只是爲了顯示語法如何挑戰我,這是我想的結構的NSFileManager轉換爲一個NSString,然後NSData的,這樣我可以把它寫(有EXC_BAD_ACCESS錯誤???):

NSString *d = (__bridge NSString *) &b224; 
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:d]; 

請大家幫忙,我是C新手,迄今爲止我花了一天的時間來了解這個問題,但沒有成功。更糟糕的是,我認爲這些endians向我射箭。我找不到任何關於這樣做的教程,並希望那裏的人能指引我走向正確的方向。該結構覆蓋七個32位int32_t整數,並填充以便每個記錄爲224位或28位8位字節。

在結構中只使用幾位長的整數就可以使用int類型嗎?這似乎工作,甚至似乎保持標誌位,只要我給它一點點。

我想在iPhone應用程序的目標C代碼使用此,使用Xcode的5

速度和做的效率,這是一個重大問題。

編輯 - 文件最終會有成千上萬的記錄,隨機的單個記錄可能需要更新一到兩分鐘。

RESOLVED - 查看評論。要創建的NSData * d發送到文件:

NSData *d = [NSData dataWithBytes:(const void *) &b224 length:28]; 

從NSData的把數據* R,這是從文件中讀取,回結構:

[r getBytes:&b224 length:28]; 

注1 - 它似乎是非常重要的是要保持32位組的字段,並且沒有任何字段與任何32位邊界重疊,不知道爲什麼,我會讓專家來確定,至少在沒有字段重疊的情況下我能夠做到我想要的。一個邊界。注2 - 確保你永遠不會在位域範圍之外放入一個值,當你這樣做時,它們似乎不會被截斷,它們會移動所有其他位,並且你的記錄被破壞。

謝謝!卡門

struct bfbits{ 
    int lat:28; 
    BOOL real:1; 
    BOOL inuse:1; 
    BOOL inter:1; 
    BOOL turn:1; 

    int lon:29; 
    BOOL units:1; 
    BOOL onleft:1; 
    int free2:1; 

    int who:26; 
    int free3:6; 

    int day:16; 
    int heading:9; 
    int free4:7; 

    int limit:7; 
    int trucklimit:7; 
    int altlimit:7; 
    int warnft:10; 
    int free5:1; 

    int uses:16; 
    int rejects:16; 

    int starthr:5; 
    int endhr:5; 
    int beginday:4; 
    int finishday:4; 
    int beginmonth:5; 
    int finishmonth:5; 
    BOOL daynight:1; 
    BOOL weekday:1; 
    int free7:2; 
}; 
struct bfbits b224; 
+1

這是一個可怕的位域數量(以及在一個結構中可怕的變量數量)。 – Borgleader

+0

我不確定你的意思是 - 你正在試圖做的事是'cout << bfbits.lat'嗎? (其中'cout'可以代替一個指向打開文件的指針,''lat'是你的'struct'的成員) – OJFord

+0

我可以很容易地將它拆分爲7個32位結構,但我認爲它會更快地讀/寫,更簡單在一個代碼中引用。我的邏輯錯了嗎? – Carm100

回答

0

的幾點

  • 一般的成語是「讓它先工作,然後擔心使它快」
  • 從磁盤讀取文件很少導致讀取單個32位值。每次您訪問I/O時,很可能會有大量數據被拉取。多少取決於您的設備和O/S。但在這一點上,它將會比你的整個文件大
  • 此外,每次從I/O緩衝區讀取時,將會拉取整個緩存行,這也會大於單個32位值。

我想說的是,對所有這些使用位字段不會幫助你很多,而且可能會使事情複雜化。另外:現代的CPU和位域是......不完全是朋友。現代CPU的設計是爲了操作寄存器的大小,所以使用非靜態掩碼或者執行變量>>和< <將會非常慢。如果您確實必須使用位域,請使用常量掩碼。

此外,由於對齊,它很可能是您安排得很好的數據。由於上述高速緩存讀取,您的數據結構將被填充到最近的N個字節以保持高速緩存訪​​問的對齊很常見。所以任何5位結構最終都會被填充到任何對齊發生的位置(可能是8個字節)。

要做的最好的事情是,將文件數據作爲無符號字符*,然後查看緩衝區的內存內容。然後,將它與預先準備的預填充結構的內存內容進行比較,並查看各種事物的對齊方式。

此時。我只是把所有東西都做成int32,然後看看你是否可以通過這種方式直接將所有內容都直接寫入內存。如果這是有效的,那麼你試圖打包數據會導致你的問題。

+0

優秀信息!該文件最終會有成千上萬的記錄,隨機的單個記錄可能需要在一兩分鐘內更新。考慮到這一點,只要我只'看到'我的224位,讀取大量額外的字節並不重要。顯然,我只想要一個記錄的224位記錄受到影響。不知道你提到的數據填充如何影響224位數據的讀寫,當它們被讀取時它們是不會被剝離的,只有給予我的相關的224位? Carmen – Carm100

+2

您所描述的訪問模式就是我們開發數據庫的原因。那麼爲什麼不使用一個?也許SQLITE或內存中處理各種鎖定條件的東西? –

+0

我已經在其他平臺上使用SQL數據庫來處理其他事情,但這只是單個用戶,單個程序訪問文件,如果我能做我想做的事情,我不希望數據庫的開銷。 – Carm100