2012-12-09 5 views
6

C를 사용하면 의 마지막 줄만 읽을 수 있습니까? 전체 내용을 반복하지 않고 있습니까?C : 파일의 마지막 행만 읽습니다. 루프가 없음

그 파일에는 각각 수백만 개의 개의 정수가 포함되어 있습니다 (long long int). 파일 자체가 상당히 클 수 있으며 최대 1000MB까지 추정 할 수 있습니다. 나는 마지막 줄이 55 자리보다 길지는 않지만 두 자리 숫자도 될 수 있다는 것을 잘 알고있다. 그것은 모든 종류의 데이터베이스를 사용하는 옵션이 없어 ... 나는 이미 그것을 고려했습니다.

아마도 어리석은 질문 일지 모르지만 PHP 배경에서 나는 대답하기가 어렵습니다. 나는 도처에 보았다. 그러나 아무것도 발견하지 않았다 를 깨끗하게한다. 현재

내가 사용하고 있습니다 :

if ((fd = fopen(filename, "r")) != NULL) // open file 
{ 
    fseek(fd, 0, SEEK_SET); // make sure start from 0 
    while(!feof(fd)) 
    { 
     memset(buff, 0x00, buff_len); // clean buffer 
     fscanf(fd, "%[^\n]\n", buff); // read file *prefer using fscanf 
    } 
    printf("Last Line :: %d\n", atoi(buff)); // for testing I'm using small integers 
} 

이 방법을 나는 파일의 내용을 반복하고있어 즉시 파일 ~ 50 만 라인의 상황이 아주 나쁜 ....

감사를 느리게보다 더 큰수록 사전에. 최대

+1

http://stackoverflow.com/questions/5431941/while-feof-file-is-always-wrong –

+0

의견을 보내 주셔서 감사합니다. 솔루션을 다른 사람들이 링크하여 어떻게 해결했는지 볼 수 있습니다 : http : // stackoverflow.co.kr/a/13792375/979785 – AnyOneElse

답변

5

최대 줄 길이가있는 경우 끝에서 전에 찾으십시오. 끝까지 읽고 버퍼의 마지막 줄 끝을 찾습니다.

최대 줄 길이가 없으면 합리적인 값을 추측하고 끝에 그다지 읽지 말고 줄의 끝이 없으면 추측을 두 번하고 다시 시도하십시오. 귀하의 경우에는

:

/* max length including newline */ 
static const long max_len = 55 + 1; 
/* space for all of that plus a nul terminator */ 
char buf[max_len + 1]; 

/* now read that many bytes from the end of the file */ 
fseek(fd, -max_len, SEEK_END); 
ssize_t len = read(fd, buf, max_len); 

/* don't forget the nul terminator */ 
buf[len] = '\0'; 

/* and find the last newline character (there must be one, right?) */ 
char *last_newline = strrchr(buf, '\n'); 
char *last_line = last_newline+1; 
+0

괜찮아. 알았어. 감사. 모든 행이 55 문자 길이라는 보장이 없기 때문에 55 버퍼 내에 하나 이상의 "\ n"이있을 수 있습니다. 2 또는 20이지만 55를 초과 할 수 없습니다. 적어도 하나는 확실합니다. 하지만 그건 내 문제 중 가장 적은 것입니다. fseek()는 내가 찾고있는 것입니다. 고맙습니다! – MAXIM

+0

오류가 발생합니다 : 'FILE * {aka _iobuf *}'에서 'int'[-fpermissive]로 잘못 변환되었습니다. ssize_t len ​​= read (fd, buff, max_len); 내가 뭘 잘못하고 있단 말인가? – MAXIM

+0

아아,'size_t len ​​= fread (buf, max_len, 1, fd)'대신'FILE *'을 사용하지만, 정수 파일 기술자 (종종'fd'라고 부름)를 쓰는 것처럼 작성했습니다. – Useless

6

그냥 fseek에서 fileSize - 55까지 읽어주십시오.

+1

note SEEK_END는 파일 크기 계산을 처리합니다 – Useless

3

"rb"으로 열면 이진을 읽게됩니다. 그런 다음 fseek(..., SEEK_END)을 입력하고 첫 줄 구분자를 찾을 때까지 뒤에서 바이트를 읽기 시작합니다 (최대 줄 길이가 55자인 경우 55자를 읽습니다 ...).

+0

올바르게 이해했다면 55 문자 씩 뒤로 읽은 다음 "\ n"을 만나 자마자 읽은 내용을 뒤집습니다. 거꾸로 (그것이 내가 생각하는 다른 길 일 것 인 이래로). – MAXIM

+0

글자 단위로 읽을 필요가 없습니다 ... 마지막 56 글자를 읽고 마지막 줄 바꿈을 찾습니다. – Useless

1

확인. 그것은 모두 나를 위해 일했습니다. 나는 새로운 것을 배웠다. 41mb 크기의 파일과 마지막 500k 줄 이상의 파일이 즉시 읽혔습니다. 당신 덕분에 모든 사람들, 특히 '쓸모없는'(닉네임, btw)의 논란을 좋아합니다. 파일이 추가 된 새로운 라인이 방식을 구조화

: 파일의 마지막 라인을 읽기

: 여기 미래에 다른 사람이 혜택을 누릴 수 있다는 희망의 코드를 게시 할 예정입니다 어떤 줄이든 내 경우에는 55 자보다 짧을 것이라고 확신합니다.

file contents: 
------------------------ 
2943728727 
3129123555 
3743778 
412912777 
43127787727 
472977827 

------------------------ 

새 줄이 추가되었습니다.

FILE *fd;       // File pointer 
char filename[] = "file.dat";  // file to read 
static const long max_len = 55+ 1; // define the max length of the line to read 
char buff[max_len + 1];    // define the buffer and allocate the length 

if ((fd = fopen(filename, "rb")) != NULL) {  // open file. I omit error checks 

    fseek(fd, -max_len, SEEK_END);   // set pointer to the end of file minus the length you need. Presumably there can be more than one new line caracter 
    fread(buff, max_len-1, 1, fd);   // read the contents of the file starting from where fseek() positioned us 
    fclose(fd);        // close the file 

    buff[max_len-1] = '\0';     // close the string 
    char *last_newline = strrchr(buff, '\n'); // find last occurrence of newlinw 
    char *last_line = last_newline+1;   // jump to it 

    printf("captured: [%s]\n", last_line); // captured: [472977827] 
} 

건배! 최대

+0

도움이 되니 기쁩니다! 당신이 대답 중 하나를 수락 할 때까지 질문은 여전히 ​​답답함으로 나타납니다 (클릭 할 수있는 체크 표시가 나타납니다) – Useless

관련 문제