2011-03-10 4 views
44

StreamWriter 및 Byte Order Marks에 문제가 있습니다. 설명서에는 Encoding.UTF8 인코딩의 바이트 순서 표시가 활성화되어 있지만 파일을 쓰는 중에는 다른 기호는 표시하지 않는 채 표시되어 있다고 나와 있습니다.StreamWriter 및 UTF-8 바이트 순서 표

나는 다음과 같은 방법으로 스트림 라이터를 만드는거야 : 극명하게 될 것이다 일이 될 수 있는지에

this.Writer = new StreamWriter(this.Stream , System.Text.Encoding.UTF8); 

어떤 아이디어.

+1

기술적으로 UTF-8로 허용되지만 BOM은 유니 코드에서 필수 또는 권장하지 않습니다 (참고 자료 [참조] (http://www.unicode.org/versions/Unicode5.0.0/ch02.pdf 참조).)). 한 가지는 UTF-16과는 달리 쓸모없는 것입니다. UTF-8 바이트 순서는 표준에 의해 지정됩니다. 또 다른 이유로는 텍스트 처리를 망칠 수 있습니다. 예를 들어, XML 프롤로그 앞에 문자가 있으면 많은 XML 파서가 질식합니다. –

+1

UTF8을 지정 하시겠습니까? 당신이 그것을 지정하지 않으면, 그것은 여전히 ​​UTF8을 쓰기하지만, 유니 코드 표준 5.0부터 BOM – xanatos

+0

하지 않고 있기 때문에 : * 유니 코드 표준은 또한 에게 명시 적으로 BIG-차별화 초기 바이트 순서 표시 (BOM)의 사용을 지정합니다 엔디안 인코딩 스키마의 엔디안 또는 리틀 엔디안 데이터 * –

답변

5

모든 파일에 대해 동일한 StreamWriter 생성자를 사용합니까? 설명서의 내용은 다음과 같습니다.

UTF-8 인코딩과 BOM을 사용하여 StreamWriter를 만들려면 StreamWriter (String, Boolean, Encoding)와 같은 인코딩을 지정하는 생성자를 사용하는 것이 좋습니다.

전 비슷한 상황이었습니다. 스트림이 위치에 0이 아닌 경우 내가 대신 StreamWriter를의 Stream.Write 방법을 사용하여 결국 나는 그 생성자가 UTF-8 BOM은 추가하지 본 적이 Encoding.GetBytes(stringToWrite)

11

유일한 시간을 쓰기 전에 Encoding.GetPreamble()의 결과를 썼다 전화 할 때. 예를 들어, 아래 코드에서 BOM이 기록되지 않습니다 : 당신은 인코딩을 지정하지 않고 StreamWriter(stream) 생성자를 사용하는 경우 다른 사람이 말했다

using (var s = File.Create("test2.txt")) 
{ 
    s.WriteByte(32); 
    using (var sw = new StreamWriter(s, Encoding.UTF8)) 
    { 
     sw.WriteLine("hello, world"); 
    } 
} 

으로, 당신은 BOM을 볼 수 없습니다.

0

제발 생산하지 않는 상황을 보여줄 수 있습니까? 내가 찾을 수있는 서문이없는 유일한 경우는 작가에게 아무 것도 쓰여지지 않은 경우입니다 (Jim Mischel은 다른 논리적이고 문제가 될 가능성이 더 높습니다. 답변을 참조하십시오).

내 테스트 코드 :

var stream = new MemoryStream(); 
using(var writer = new StreamWriter(stream, System.Text.Encoding.UTF8)) 
{ 
    writer.Write('a'); 
} 
Console.WriteLine(stream.ToArray() 
    .Select(b => b.ToString("X2")) 
    .Aggregate((i, a) => i + " " + a) 
    ); 
2

이 파일이 이미 존재하고 BOM을 포함하지 않은 경우, 다음 덮어 때 BOM을 유지 StreamWriter를 즉, BOM이 포함되지 않습니다 (또는 부재의) 것 같다 파일을 덮어 쓸 때.

61

누군가가 이미 지적했듯이 인코딩 인수없이 호출하면 트릭을 수행합니다. 당신이 명시하려면 그러나,이 시도 :

using (var sw = new StreamWriter("text.txt", new UTF8Encoding(false))) 

열쇠 대신 Encoding.UTF8Encoding를 사용하는 새로운 UTF8Encoding (거짓)를 구성하는 것입니다. BOM을 추가할지 여부를 제어하는 ​​것입니다.

이 내부적으로 그냥 같은 일을하고있어, 인코딩 인수하지 않고에서는 StreamWriter를 호출 한 것과 같은 상태가된다.

13

이 문제는 사용자가 Encoding class에 정적 UTF8 property을 사용하고 있기 때문에 발생합니다. GetPreamble methodUTF8 속성에서 반환 Encoding 클래스의 인스턴스라고

, 그것은 (세 문자의 바이트 배열) 바이트 순서 표시를 반환하고 다른 내용이 기록되기 전에 스트림에 기록됩니다 stream (새로운 스트림을 가정).

당신과 같이 자신을 UTF8Encoding class의 인스턴스를 생성하여이를 방지 할 수 있습니다 다음 default parameterless constructor (강조 광산)에 대한 설명서 당으로

// As before. 
this.Writer = new StreamWriter(this.Stream, 
    // Create yourself, passing false will prevent the BOM from being written. 
    new System.Text.UTF8Encoding()); 

:

이 생성자는 인스턴스를 생성 은 유니 코드 바이트 순서 표시을 제공하지 않으며 잘못된 인코딩이 감지되면 예외를 throw하지 않습니다.

즉, GetPreamble을 호출하면 빈 배열이 반환되므로 BOM이 기본 스트림에 기록되지 않습니다.

+0

인코딩은 (TCP를 통해 문자 메시지를 전송하는) ...이''ENC = Encoding.GetEncoding (...) 간단한 구문 분석과 검색있어 우리 프로그램에서 설정 사용자입니다. 주위에있는 유일한 방법은 실제로'if (enc is UTF8Encoding) enc = 새 UTF8Encoding (false); 뒤에 추가하는 것입니다. 꽤 더러운 수정,하지만 그것을 해결하는 다른 방법을 참조하십시오 ... – Nyerguds

+0

@ Nyerguds 그 유일한 방법은 아니에요. 매개 변수가 주어진 인터페이스로 인코딩 가져 오기를 추상화하여 인코딩을 가져올 수 있습니다. 그런 다음 해당 인터페이스의 구현을 코드에 전달/삽입합니다. 그런 다음 모든 것을 아주 깨끗하게 만듭니다. – casperOne

+0

그건 그냥 다른 클래스로 동일한 것을 이동합니다. 전반적으로 GetEncoding은 기본 생성자를 사용하지 않는다는 것이 완전히 기괴하다는 것을 알게되었습니다. 아, 그럼. – Nyerguds

9

내 대답은 필요한 모든 정보를 포함 HelloSam의 한을 기반으로합니다. OP가 요구하는 것은 BOM이 파일로 내보내 지는지 확인하는 것입니다.

그래서 대신에 당신이 진정한 통과해야 UTF8Encoding의 ctor에 거짓 전달합니다.

using (var sw = new StreamWriter("text.txt", new UTF8Encoding(true))) 

는 BOM 포함 않는하지 어느 헥스 편집기에서 생성 된 파일을 열어 볼, 아래의 코드를 사용해보십시오.

class Program 
{ 
    static void Main(string[] args) 
    { 
     const string nobomtxt = "nobom.txt"; 
     File.Delete(nobomtxt); 

     using (Stream stream = File.OpenWrite(nobomtxt)) 
     using (var writer = new StreamWriter(stream, new UTF8Encoding(false))) 
     { 
      writer.WriteLine("HelloПривет"); 
     } 

     const string bomtxt = "bom.txt"; 
     File.Delete(bomtxt); 

     using (Stream stream = File.OpenWrite(bomtxt)) 
     using (var writer = new StreamWriter(stream, new UTF8Encoding(true))) 
     { 
      writer.WriteLine("HelloПривет"); 
     } 
    } 
3
나는이 답변이 유용 (@Philipp Grathwohl 및 @Nik 덕분에) 발견

,하지만 내 경우에는 내가의 BOM을 생성하는 코드를 작업을 수행하여 FileStream을 사용하여, 그렇게하고있어 다음과 같이 진행됩니다

using (FileStream vStream = File.Create(pfilePath)) 
{ 
    // Creates the UTF-8 encoding with parameter "encoderShouldEmitUTF8Identifier" set to true 
    Encoding vUTF8Encoding = new UTF8Encoding(true); 
    // Gets the preamble in order to attach the BOM 
    var vPreambleByte = vUTF8Encoding.GetPreamble(); 

    // Writes the preamble first 
    vStream.Write(vPreambleByte, 0, vPreambleByte.Length); 

    // Gets the bytes from text 
    byte[] vByteData = vUTF8Encoding.GetBytes(pTextToSaveToFile); 
    vStream.Write(vByteData, 0, vByteData.Length); 
    vStream.Close(); 
} 
+1

나는 새로운 UTF8Encoding (true) 생성자를 발견했다. –