2014-10-06 2 views
0

fgets를 사용하여 파일에서 몇 줄의 텍스트를 읽는 데 문제가 있습니다. 이 파일은 플러그인이 처음 실행될 때 번들 내의 파일에 기록되는 몇 가지 기본 사용자 데이터입니다. 이후에 플러그인을 실행하면 사용자 데이터가 읽혀지고 교차 참조되어 사용자 신원을 확인해야합니다.fgets는 줄의 시작을 읽지 않습니다.

데이터는 항상 3 행이며 frwite로 정확히 쓰여지고 fopen으로 열립니다.

원래 이론은 fgets를 각 행을 3 번 읽는 것을 데이터 구조체의 일부인 자체 char 배열로 호출하는 것이 었습니다. 문제는 첫 번째 라인이 올바르게 읽혀지고, 두 번째 라인은 위치 표시기가 다음 라인에서 시작되지만 라인 1에서 읽힌 문자 수만큼 오프셋 된 것처럼 읽혀집니다. 세 번째 라인은 전혀 읽히지 않습니다.

fgets는 오류를 반환하지 않으며, 그것이 있어야하는 데이터를 읽은 것처럼 행동합니다. 그래서 나는 분명히 뭔가를 놓치고 있습니다.

어쨌든 여기 내 코드의 일부가 있습니다. 누군가 내 실수에 대해 밝힐 수 있습니다! NULL 각 문자열의 마지막 문자를 설정

int length; 

fgets(var.n, 128, regFile); 
length = strlen(var.n); 
var.n[length-1] = NULL; 

fgets(var.em, 128, regFile); 
length = strlen(var.em); 
var.em[length-1] = NULL; 

fgets(var.k, 128, regFile); 
length = strlen(var.k); 
var.k[length-1] = NULL; 

fclose(regFile); 

단지 제거되는/N

이 코드 시퀀스는 라인 (1)의 전체를, 상기 제 2 행의 절반과 3 행의 없음을 출력한다. 이것에 대한 답에 대한 @alvits에

+0

해당 파일에 적절한 EOL 문자가 있는지 확인 했습니까? dos-text 파일은 유닉스 텍스트 파일이나 mac 텍스트 파일과 같은 것을 읽지 않습니다. –

+0

Note : 어떤 경우에는'strlen (var.n) -> 0'과'var.n [length-1] = anything'이 문제가됩니다. 'fgets()'의 결과를'NULL'에 대해 검사하고'var.n [length-1] = '\ 0''을하기 전에'length> 0'인지 테스트하는 것이 좋습니다. – chux

+2

1)'var.n'의 정의를 보여줍니다. 2) 'var.em [length-1] ='\ 0 ';에서'NULL'대신 '\ 0'을 사용하십시오. – chux

답변

0

Linux를 포함한 POSIX 시스템에서 바이너리 파일과 텍스트 파일은 구분되지 않습니다. 파일 스트림을 열 때, b 플래그는 무시됩니다. 자세한 내용은 fopen()에 설명되어 있습니다.

"어떻게 텍스트를 이진 파일과 구별하겠습니까?"라는 질문을 할 수 있습니다. 내용에 따라 내용이 다릅니다. 내용을 쓰는 방법에 따라 바이너리 또는 텍스트 파일이됩니다.

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)의 서명을 확인하십시오. *ptr의 내용을 각 구성원의 크기를 나타내는 size (nmemb)과 씁니다. 작성된 스트림은 문자열로 변환되지 않습니다. 97을 쓰려면 ascii로 A 인 이진수 97을 씁니다. 바이너리 데이터는 문자열 종료를 따르지 않습니다. 데이터에 존재하는 \n\0의 존재는 문자 그대로 그대로 쓰여집니다.

이제 int fputs(const char *s, FILE *stream)의 서명을 살펴보십시오. 문자열 내용을 *s으로 씁니다. 97을 쓰고 싶다면 A이 아닌 문자열 "97"이어야합니다. 문자열 종료는 준수됩니다. \n은 자동으로 O/S 지원 개행 문자 (CRLF 또는 LF)로 변환됩니다.

fwrite()fputs()처럼 동작하지만 다른 방법은 사용할 수 없습니다. 예를 들어, ptr을 string에 대한 포인터로 선언하고 문자열 terminator를 제외한 내용의 길이와 정확하게 같은 크기를 계산하면 이진수가 아닌 텍스트로 쓸 수 있습니다. 또한 \0\n을 처리하고 O/S 지원 개행 문자로 변환해야합니다. 전체 문자열 버퍼를 쓰면 문자열 종료자를 포함하여 모든 것을 씁니다.

+0

설명해 주셔서 감사합니다. 매우 도움이됩니다. 나는 지금 무슨 일이 일어나고 있는지 정확하게 알고 있습니다. – InfluentialAudio

1

감사 :

에 fwrite이는 fgets()와 호환되지 않습니다(). fwrite()와 fread() 모두 명시 적으로 and> 문자열로 변환되지 않는 한 바이너리 스트림에서 작동합니다. fgets()는 fputs()와 호환되며 모두 문자열에서 작동합니다.

대신 fputs()를 사용하여 데이터를 쓰고 완벽하게 다시 읽습니다.

+0

'fwrite()'와'fgets()'는 호환 가능합니다. 그것은 코드가 어떻게 사용하는지에 달려 있습니다. 이 질문은 코드 작성 방법을 게시하지 않았기 때문에, 작성한 데이터와 읽지 않은 데이터가 서로 호환되지 않는 이유를 확인하는 것은 어려운 일입니다. – chux

+0

"바이너리 및 텍스트 스트림에서 작동하는 경우 어떤 함수가 아닌 스트림/파일이 열린 모드에 따라 다릅니다. fwrite() 및 fread() (fgets()와 같은 함수는 바이너리 스트림과 텍스트 스트림을 가진'fgets()'에 더 잘 맞지만, 그 스트림 모드에 국한되지는 않는다. – chux

+0

@chux I 내 원래의 질문에 언급했는데 나는 frwite()를 사용했다. 그러나 위의 alvits에 대한 내 의견에 언급했듯이 나는 논리적 인 이유를 볼 수 없었다. 왜 그들이 호환되지 않는지 직접 알지 못했다. 나는 'b'플래그를 지정하지 않았다. fopen()에 대한 호출은 기본적으로 파일을 '텍스트'로 열어야합니다.이 모든 것을 제쳐두고 제안 된 문제가 문제를 해결했으며 fwrite() 호출을 fputs() 호출로 대체하여 진실이 있어야합니다. – InfluentialAudio

관련 문제