2015-04-03 86 views
0

說我有下面的代碼(這只是打開一個文件,獲取它的大小,並讀取所有一氣呵成):std :: ifstream/FILE *可以改變大小嗎?

std::ifstream file(path, std::ios_base::binary | std::ios_base::ate); 
std::istream::streampos file_size = file.tellg(); 
file.seekg(0); 
char* buffer = new char[file_size]; 
file.read(buffer, file_size); 

是否有可能在該文件中file.tellg()和之間改變大小file.read()調用(即另一個程序修改文件)?也就是說,如果file.read()成功,是否保證file.gcount() == file_size

這延伸到C *(即做fopen("rb")fseek()ftell()rewind()fread()),如果fread()成功,將它總是返回文件大小(如以前ftell()報道)?我傾向於這個正在實現的定義,但我很好奇,如果C++標準(或C標準,因爲C++標準指的是FILE相關函數)會在這裏做出任何保證或不做。

*我正在使用C++,並且有兩種方式可以使用文件:std::fstreamFILE*。 C++標準遵循有關FILE*函數的C標準,這就是爲什麼我在此明確提出C的原因。

+0

因爲這是C++代碼,建議刪除'c'標籤 – user3629249 2015-04-03 16:24:55

+0

@ user3629249:請參閱腳註。 C++標準遵循關於'FILE *'操作的C標準。由於我有兩種使用C++('std :: fstream'和'FILE *')的方式來處理文件,我想了解它們的保證,所以我不得不問C++和C. – Cornstalks 2015-04-03 16:26:01

回答

2

我寧願這取決於你打開的文件類型和操作系統的能力。

由於讀取操作不像您期望的那樣,文件必須在ftellfread之間縮小。你可以用ftruncate做另一個過程。而且我找不到任何說明打開文件的其他進程會發生什麼情況。但我不希望他們必須能夠讀取曾經存在的數據。

0

下面的實驗表明,std::ifstream/FILE*的確可以改變大小,而閱讀它:

Writer1.cpp

#include <fstream> 

int main() { 
    for (;;) { 
     std::ofstream file("file.txt", std::ios_base::binary | std::ios_base::trunc); 
     file.flush(); 
     file << "Hello world!\n"; 
    } 
} 

Reader1.cpp

#include <iostream> 
#include <fstream> 

int main() { 
    for (;;) { 
     std::ifstream file("file.txt", std::ios_base::binary | std::ios_base::ate); 
     std::streamsize file_size = file.tellg(); 

     if (!file || file_size == -1) continue; 

     file.seekg(0); 
     char* buffer = new char[file_size]; 
     file.read(buffer, file_size); 
     delete [] buffer; 

     if (file.gcount() != file_size) { 
      std::cout << file.gcount() << " != " << file_size << std::endl; 
      break; 
     } 
    } 
} 

編譯Writer1.cppReader1.cpp並且同時運行它們最終會產生0 != 13,這表明std::ifstream確實可以在tellg()read()之間更改大小。

Writer2.cpp

#include <iostream> 
#include <fstream> 
#include <cstdio> 

int main() { 
    for (;;) { 
     FILE* file = fopen("file.txt", "wb"); 
     fflush(file); 
     fwrite("Hello world!\n", 1, 13, file); 
     fclose(file); 
    } 
} 

Reader2。CPP

#include <iostream> 
#include <cstdio> 

int main() { 
    for (;;) { 
     FILE* file = fopen("file.txt", "rb"); 
     if (!file) continue; 

     fseek(file, 0, SEEK_END); 
     long file_size = ftell(file); 

     if (file_size == -1) { 
      fclose(file); 
      continue; 
     } 

     rewind(file); 

     char* buffer = new char[file_size]; 
     size_t nread = fread(buffer, 1, file_size, file); 
     fclose(file); 
     delete [] buffer; 

     if (nread != file_size) { 
      std::cout << nread << " != " << file_size << std::endl; 
      break; 
     } 
    } 
} 

同樣,編譯Writer2.cppReader2.cpp,並在同一時間運行它們最終產生0 != 13,顯示出一個FILE*可的確是一個ftell()fread()之間改變大小。

有趣的是,std::ifstream的失敗速度比FILE*的要快。這些測試是在OS X 10.9.5上使用3.5版進行的。

相關問題