2013-04-20 57 views
3

我有一個代碼,我正在訪問一個二進制文件幾次。每次我調用該函數時,它都會打開文件進行讀取,並只讀出所需的字節數(每次說明爲n字節)。保存函數調用之間的文件指針

二進制文件包含時間序列數據,我希望能夠做的是通過循環運行函數調用,並且每次調用函數打開同一個文件時,都需要讀取出下一塊數據,我不希望每次都重置文件指針。有沒有辦法做到這一點?

函數看起來像這樣:

int readBinary(float *binImage, int gelements) { 
    imageFile = fopen("tmpImageFile", "r"); 
    if (imageFile == NULL) { 
     fprintf(stderr, "Error opening file\n"); 
     return (1); 
    } 
    fread(binImage, sizeof(float), gelements, imageFile); 
    return 0; 
} 

而且在我主要的代碼,我想通過一個循環來運行它,給它每一次大小gelements的陣列binImage。如果這是可以避免的,我寧願不給它一個大小爲gelements * nLoop的數組。

+3

爲什麼你不斷重新打開文件?只需打開一次並繼續使用它。 – Barmar 2013-04-20 18:26:21

回答

6

拇指快速規則

生活變得更容易,如果功能之間你正確地分別承擔的責任」

的生活,如果你使用靜態或全局變量變得複雜 」。

在這種情況下,給予readBinary函數管理FILE和讀取數據的責任過多。

請注意,該功能不會關閉句柄。

如果句柄是函數中的局部靜態,那麼將無法關閉它。 這也意味着函數將被永久鎖定爲僅使用「tmpImageFile」(從函數的簽名或缺少文檔中不會立即顯示)

如果句柄是全局的,則可能過早關閉它。

請注意,如果您刪除「打開文件」職責readBinary函數只是致fread

處理此問題的最佳方法是完全跳過readBinary函數。

你說你有一個循環讀取數據的調用者。 讓此調用者負責打開FILE,直接在循環中使用fread,並在完成後關閉文件。

現在,這可能會給調用者太多的責任。只需讓主叫方接受FILE*作爲參數,並將文件管理責任交給主叫方。 或調用者的調用者的調用者,取決於管理文件的生命週期的意義。

1

您可以使文件指針爲靜態並將其初始化爲NULL。然後下一次如果它不是NULL,則它包含打開的文件。同時關閉文件時,確保將其重新設置爲NULL。同樣也有一個全球性的指針做也使您保留文件指針

int readBinary(float *binImage, int gelements) { 
static imageFile = NULL; 
if(imageFile == NULL) imageFile = fopen("tmpImageFile", "r"); 
if (imageFile == NULL) { 
    fprintf(stderr, "Error opening file\n"); 
    return (1); 
} 
fread(binImage, sizeof(float), gelements, imageFile); 
return 0; 
} 
6

使用一個靜態變量:

int readBinary(float *binImage, int gelements) { 
    static FILE *imageFile = NULL; 
    if (imageFile == NULL) { 
     imageFile = fopen("tmpImageFile", "r"); 
     if (imageFile == NULL) { 
      perror("Error opening file: "); 
      return (1); 
     } 
    } 
    fread(binImage, sizeof(float), gelements, imageFile); 
    return 0; 
} 
3

我會通過FILE*作爲參數傳遞給函數:

int readBinary(float *binImage, int gelements, FILE *imageFile) { 
    int bytes = fread(binImage, sizeof(float), gelements, imageFile); 
    return bytes != -1 ? 0 : 1; 
} 

我還爲fread返回值添加了簡單檢查並將其轉換爲您的返回值約定。雖然這個功能看起來很簡單,但您可以直接撥打fread,除非您想添加錯誤打印等內容。