2011-01-17 6 views
8

D의 텍스트 파일을 읽는 데있어 어느 정도 크기가 적당합니까?D의 텍스트 파일 읽기

함수는 인코딩을 자동 감지하고 string 또는 dstring과 같이 일관된 형식으로 파일의 전체 데이터를 제공해야합니다. BOM을 자동 감지하고 적절하게 해석해야합니다.

나는 std.file.readText()을 시도했지만 다른 인코딩은 제대로 처리하지 못했습니다.

(물론,이 0이 아닌 실패율이있을 것이다, 그리고 내 응용 프로그램 허용합니다.)

답변

8

을 나는 믿는다 나는이 시점에서 포보스에서/O (옆에서 파일에 대한 유일한 옵션 C 함수 호출)은 std.file.readTextstd.stdio.File입니다. readText은 파일에서 char, wchars 또는 dchars (기본값은 immutable (char) [] - 문자열)의 배열로 읽습니다. 필자는 소스 코드를 파헤쳐 야 할 필요가 있지만 인코딩은 UTF-8, UTF-16 및 UTF-32 (문자, 와카 및 dchars)가되어야한다고 생각합니다. 이러한 인코딩과 호환되는 인코딩 (예 : ASCII는 UTF-8과 호환 가능)은 정상적으로 작동합니다.

File을 사용하는 경우 readlnrawRead을 포함한 파일을 읽을 수있는 몇 가지 옵션이 있습니다. 그러나 기본적으로 파일은 readText처럼 UTF-8, UTF-16 또는 UTF-32 호환 인코딩을 사용하여 읽거나 바이너리 데이터로 읽고 직접 조작합니다.

D의 문자 유형은 각각 UTF-8, UTF-16 및 UTF-32 코드 단위 인 char, wchar 및 dchar이므로 이진 형식으로 데이터를 읽지 않으려면 파일 이 세 가지 유형의 유니 코드 중 하나와 호환되는 인코딩으로 인코딩되어야합니다. 특정 인코딩의 문자열이 주어지면 std.utf의 함수를 사용하여 다른 인코딩으로 변환 할 수 있습니다. 그러나, 특정 인코딩에서 파일을 읽고 시도하고 성공했는지 확인하기 위해 readText을 사용하는 것 이외의 인코딩 유형에 대해 파일을 쿼리하는 방법을 알지 못합니다.

그래서 파일을 직접 처리하고 인코딩에 어떤 인코딩이 포함되어 있는지 확인하지 않는 한 가장 좋은 방법은 성공한 첫 번째 문자열을 사용하여 각 연속 문자열 유형에 readText을 사용하는 것입니다. 그러나 텍스트 파일은 일반적으로 UTF-8 또는 UTF-8 호환 인코딩이므로 보통 문자열을 사용하는 readText은 거의 항상 잘 작동합니다. BOM을 확인 처리에 관해서는

+0

흠 ... 어떤 생각을 BOM으로 처리할까요? – Mehrdad

+1

@Lambert, 나는 어떤 검증도하지 않으므로 read()를 사용하는 것이 좋습니다.하지만 직접 할 수 있고 여러 번 파일을 읽지 않습니다. BOM의 경우 ubyte로 캐스팅하고 첫 번째 바이트를 비교 한 다음 나머지 슬라이스에 대해 캐스트를 수행 할 수 있습니다. –

+0

흠 ... 내가 원하는 해결책이 아닙니다. (수동으로 BOM을 확인하고 싶지 않았습니다.) 그러나 그것은 나쁘지 않다. 감사. – Mehrdad

4

:

char[] ConvertViaBOM(ubyte[] data) { 
    char[] UTF8() { /*...*/ } 
    char[] UTF16LE(){ /*...*/ } 
    char[] UTF16BE(){ /*...*/ } 
    char[] UTF32LE(){ /*...*/ } 
    char[] UTF32BE(){ /*...*/ } 

    switch (data.length) { 
    default: 
    case 4: 
     if (data[0..4] == [cast(ubyte)0x00, 0x00, 0xFE, 0xFF]) return UTF32BE(); 
     if (data[0..4] == [cast(ubyte)0xFF, 0xFE, 0x00, 0x00]) return UTF32LE(); 
     goto case 3; 

    case 3: 
     if (data[0..3] == [cast(ubyte)0xEF, 0xBB, 0xBF]) return UTF8(); 
     goto case 2; 

    case 2: 
     if (data[0..2] == [cast(ubyte)0xFE, 0xFF]) return UTF16BE(); 
     if (data[0..2] == [cast(ubyte)0xFF, 0xFE]) return UTF16LE(); 
     goto case 1; 

    case 1: 
     return UTF8(); 
    } 
} 

은 더 애매한 BOM의 독자를위한 운동으로 남아 추가.