2017-11-18 14 views
0

다음 C 코드는 stdin에서 fgetws()을 사용하여 행을 읽고 stdout에 씁니다.fgetws() 및 UTF-8을 사용하는 EILSEQ

#include <stdio.h> 
#include <locale.h> 
#include <wchar.h> 

#define STR_LEN 128 

int main(int argc, char **argv) 
{ 
    FILE *infile = stdin, *outfile = stdout; 
    wchar_t str[STR_LEN]; 

    if (setlocale(LC_ALL, "en.UTF-8") == NULL) { 
     fprintf(stderr, "Cannot set locale\n"); 
     return 1; 
    } 


    for (;;) { 

     if (!fgetws(str, STR_LEN, infile)) { 
      if (feof(infile)) { 
       break; 
      } 
      perror("fgetws()"); 
      continue; 
     } 
     str[wcscspn(str, L"\r\n")] = L'\0'; 

     if (fwprintf(outfile, L"%ls\n", str) < 0) { 
      perror("fwprintf()"); 
     } 

    } 

    return 0; 
} 

그것은 항상 ASCII 파일을 완벽하게 작동하지만, UTF-8 데이터를 읽을 때 가끔 fgetws()에서 EILSEQ 오류 (잘못된 바이트 시퀀스)를 얻을, 나는 그 이유를 알아낼 수 없습니다.

출력 파일에서 오류를 일으키는 줄이 잘린 다음 일부 문자가 누락되고 나머지 부분은 다음 줄에 있습니다. 이상한 점은 내가 그 줄만 주면 아무런 오류가 없다는 것입니다.

예를 들어, 몇 줄의 UTF-8 라인 만 읽으면 괜찮습니다. 같은 줄을 여러 번 반복하면 EILSEQ이 나옵니다.

나는 파일이 정확하게 인코딩되었음을 확신한다.

나는 musl-libc와 함께 Linux를 사용합니다.

내 코드에 무슨 문제가 있습니까?

편집 : 내가 입력 크기에 따라 몇 EILSEQ 오류가 발생할 수 있지만 두 beetween 정확한 관계를 알 수 없습니다.

동일한 입력을 사용하면 같은 줄에서 동일한 오류가 발생합니다.

오류를 유발하는 특정 오프셋 또는 문자가 아닌 것 같지만 잘못된 것일 수 있습니다.

편집 2 : 나는이 코드를 OpenBSD에서도 테스트했으며 작동한다. 이 시점에서 저는이 문제가 Linux 나 musl-libc와 관련이 있다고 생각합니다.

+0

'STR = 0;'수 있습니다 더 좋은 방법. – wildplasser

+0

확실합니다. 고맙습니다. –

+0

파일의 같은 지점에서 항상 실패합니까? EILSEQ 하나 또는 두 개의 오류가 있습니까? 그 문자에 대한 utf-8 코드와 오류를 유발하는 문자의 정확한 바이트 오프셋은 무엇입니까? – rici

답변

0

UTF-8은 문자를 저장하는 데 char을 사용하며 ANSI와 같은 방식으로 작동합니다. 유일한 차이점은 언어 문자가 한 문자보다 길 수 있다는 것입니다.

wchar_t 및 wide-c 문자열 함수는 Windows의 UTF-16에 사용됩니다. Linux에서는 char16_t을 사용하여 UTF-16을 저장하지만 UTF-16 파일로 작업하는 경우에만 사용합니다. 그것은 분명히 여기에 해당하지 않습니다.

그냥 UTF-8, 당신은 ANSI 작업을 동일한 방식으로 처리 할 수 ​​char 기능을 사용 : [(STR, "\ 연구 \ n") 건 strcspn]

char str[STR_LEN]; 
while(fgets(str, STR_LEN, infile)) 
{ 
    str[strcspn(str, "\r\n")]; 
    fprintf(outfile, "%s\n", str); 
} 
+0

예, 위의 프로그램은'char' 문자열에서도 작동합니다. 하지만 독서 후에 하나의 문자를 조작해야한다면'wchar_t'가 필요할 것입니다. 맞습니까? 간단한 작업 만 수행하면되므로 외부 라이브러리 (예 : ICU)를 사용하지 않는 것이 좋습니다. –

+0

Linux를 사용하지 않습니까? 'whcar_t'는 Windows에서 사용되며 Linux에서는 거의 사용되지 않습니다. 그냥'char'을 사용하십시오. '\ n ''또는'',''와 같은 ANSI 문자를 검색하는 경우 텍스트를 구문 분석 할 수 있습니다. 그 문자는 다른 곳에서 반복되지 않기 때문입니다. 정규 ANSI 텍스트로 취급하십시오.그러나''ελληνικά ''과 같은 것을 가지고 있다면''η ''가 다른 문자들의 조합이기 때문에''η ''를 찾는 것이 매우 어렵습니다. 거의 옵션을 필요로하지 않을 것입니다. –

+0

불행히도 비 ASCII 문자에 대한 작업을 수행해야합니다. –