2009-11-08 2 views
6

큰 이진 파일 (100,000,000 개의 부동 소수점이 있음)이 있으면 C 또는 C++에서 파일을 열고 (즉, 62,821,214 번째 플로트가 무엇인지 빠르게 찾을 수있는 방법) 전체 플로트를 메모리에로드 할 필요가 없습니다. 두 번째 질문은 전체 파일을 다시 작성하지 않고 파일의 특정 float를 변경하는 방법이 있습니까?C/C++에서 이진 파일의 읽기 및 쓰기

내가 좋아하는 기능을 구상하고 있습니다 : 당신은 부동의 크기를 알고

float readFloatFromFile(const char* fileName, int idx) { 
    FILE* f = fopen(fileName,"rb"); 

    // What goes here? 
} 

void writeFloatToFile(const char* fileName, int idx, float f) { 
    // How do I open the file? fopen can only append or start a new file, right? 

    // What goes here? 
} 
+0

글을 쓰려면 "+ +"모드가 아니라 "r +"모드로여십시오. 추가 모드에서는 어디에서 탐색할지에 관계없이 쓰기는 항상 파일의 끝으로 이동합니다. –

답변

19

sizeof(float), 그래서 곱셈가 올바른 위치에 당신을 얻을 수 있습니다 마찬가지로

FILE *f = fopen(fileName, "rb"); 
fseek(f, idx * sizeof(float), SEEK_SET); 
float result; 
fread(&result, sizeof(float), 1, f); 

, 당신은 쓸 수 있습니다 이 방법을 사용하여 특정 위치로

+0

좋습니다. 그것은 fread이어야합니다 (& result, sizeof (result), 1, f); 그래도? – Switch

+0

아, 네 말이 맞아. 나는 그것을 고쳐 줄 것이다. –

4

fopen은 fopenrb+ 또는 wb+ 모드를 사용하여 파일을 수정하기 위해 열지 못하게합니다. 여기를 참조하십시오 : http://www.cplusplus.com/reference/clibrary/cstdio/fopen/

특정 플로트에 파일을 배치하려면, 당신은 orign로 오프셋 광고 SEEK_SETindex*sizeof(float)를 사용하여 fseek을 사용할 수 있습니다. 여기를 참조하십시오 : http://www.cplusplus.com/reference/clibrary/cstdio/fseek/ 여기

+0

"rb +"는 작동하지만 "wb +"가 있으면 파일을 자릅니다. – marcin

3

는 예를 들어 당신이 C++ 스트림을 사용하고자하는 경우 :

#include <fstream> 
using namespace std; 

int main() 
{ 
    fstream file("floats.bin", ios::binary); 
    float number; 

    file.seekp(62821214*sizeof(float), ios::beg); 
    file.read(reinterpret_cast<char*>(&number), sizeof(float)); 
    file.seekp(0, ios::beg); // move to the beginning of the file 
    number = 3.2; 
    // write number at the beginning of the file 
    file.write(reinterpret_cast<char*>(&number), sizeof(float)); 
} 
0

한 가지 방법은 파일에 mmap()를 호출하는 것입니다. 일단 그렇게하면 파일이 메모리 내 배열 인 것처럼 읽고 수정할 수 있습니다.

물론이 방법은 파일이 프로세스의 주소 공간에 맞을 정도로 작을 때만 작동합니다 ... 64 비트 모드에서 실행 중이면 괜찮을 것입니다. 32 비트 모드에서 100,000,000 개의 부동 소수점을 가진 파일은 적합해야하지만, 그 이상의 크기와 크기의 또 다른 순서 또는 두 개는 문제가 될 수 있습니다.

-1

나는이 질문에 이미 답을했지만 Linux/Unix는 파일 중간에서 읽기/쓰기 (pread/pwrite)를 쉽게 호출 할 수 있음을 알고있다. 시스템 호출에 대한 커널 소스 코드 '&'pread '를 호출하면 결국 vfs_read()가 호출되고 vfs_read에는 OFFSET이 필요합니다. 즉, 파일에서 읽으려면 POSITION이 필요합니다. pread에서이 오프셋은 우리에 의해 주어지며 read()에서 오프셋은 커널에서 내부적으로 계산되고 파일 디스크립터에 대해 유지된다. pread()는 read()에 비해 뛰어난 성능을 제공하고 pread를 사용하면 파일의 다른 부분에있는 여러 스레드에서 동시에 동일한 파일 설명자를 읽고 쓸 수 있습니다. 내 겸손한 opionion, read() 또는 다른 파일 스트림을 사용하지 마십시오. pread()를 사용하십시오. Filestream 라이브러리가 read() 호출을 감싸고 있기를 희망합니다. 스트림은 시스템 호출을 줄임으로써 잘 수행됩니다.

#include <stdio.h> 
#include <unistd.h> 
#include <fcntl.h> 
int main() 
{ 
    char* buf; off_t offToStart = id * sizeof(float); size_t sizeToRead = sizeof(float); 
    int fd = open("fileName", O_RDONLY); 
    ret = pread(fd, buf, sizeToRead, offToStart); 
    //processs from the read 'buf' 
    close(fd); 
} 
+0

이 솔루션으로 이진 파일을 읽을 수 없습니다. – LOLKFC