2014-12-16 14 views
2

내 목표는 .NET 문자열 (유니 코드)을 Windows-1252로 변환하고 필요한 경우 Base64 엔터티에 원래 UTF-8 문자열을 저장하는 것입니다.Windows-1252 문자열과 UTF-8 문자열 비교

예를 들어 1252로 변환 된 "DJ Doena"문자열은 여전히 ​​"DJ Doena"입니다.

그러나 나무 (木)의 일본어 간지를 1251로 변환하면 물음표가 생깁니다.

이이 내 테스트 문자열 :

String doena = "DJ Doena"; 
String umlaut = "äöüßéèâ"; 
String allIn = "< ä ß á â & 木 >"; 

내가 처음에 문자열을 변환하는 방법이 있습니다 : 문자열 비교를 디버깅하는 것은 모두가 실제로 동일 함을 주장하면서

using (MemoryStream ms = new MemoryStream()) 
{ 
    using (StreamWriter sw = new StreamWriter(ms, Encoding.UTF8)) 
    { 
     sw.Write(decoded); 
     sw.Flush(); 
     ms.Seek(0, SeekOrigin.Begin); 
     using (StreamReader sr = new StreamReader(ms, Encoding.GetEncoding(1252))) 
     { 
      encoded = sr.ReadToEnd(); 
     } 
    } 
} 

문제가있다, 따라서 간단한 == 또는 .Equals()으로 충분하지 않습니다.

내가 base64로 필요하면 찾아 시도를 생산하는 방법이 있습니다 :

private static String GetBase64Alternate(String utf8Text, String windows1252Text) 
{ 
    Byte[] utf8Bytes; 
    Byte[] windows1252Bytes; 
    String base64; 

    utf8Bytes = Encoding.UTF8.GetBytes(utf8Text); 
    windows1252Bytes = Encoding.GetEncoding(1252).GetBytes(windows1252Text); 
    base64 = null; 
    if (utf8Bytes.Length != windows1252Bytes.Length) 
    { 
     base64 = Convert.ToBase64String(utf8Bytes); 
    } 
    else 
    { 
     for(Int32 i = 0; i < utf8Bytes.Length; i++) 
     { 
      if(utf8Bytes[i] != windows1252Bytes[i]) 
      { 
       base64 = Convert.ToBase64String(utf8Bytes); 
       break; 
      } 
     } 
    } 
    return (base64); 
} 

첫 번째 문자열 doena 완전히 동일하며 base64로 결과

Console.WriteLine(String.Format("{0}/{1}", windows1252Text, base64Text)); 

결과를 생성하지 않습니다 in

DJ Doena/

그러나 두 번째 문자열 umlauts a lready 1252보다 UTF-8에서 두 번 바이트를 가지고 있으며, 따라서 필요하다고 표시되지 않습니다에도 불구하고 Base64로 문자열을 생성합니다

äöüßéèâ/w6TDtsO8w5/DqcOow6I= 

을 그리고 세번째는이 "(더 이상하지 않는다하기로되어 있잖아 木? "하지만" "따라서 64 기수) 필요 :

< ä ß á â & ? >/PCDDpCDDnyDDoSDDoiAmIOacqCA+ 

더 나은 결과에 대한 성능 B에 대한 내 Base64로 게터가 강화 될 수있는 방법을 모든 단서를))?

미리 감사드립니다. :-)

+1

보조 노트로 : 윈도우 1252으로 인코딩하기 전에 FormC에 정상화 고려한다. – CodesInChaos

답변

3

나는 완전히 그 질문을 이해하지 못했다. 그러나 나는 노력했다. :) 내가 올바르게 이해한다면,이 코드는 당신이 원하는 것을 수행합니다 :

static void Main(string[] args) 
{ 
    string[] testStrings = { "DJ Doena", "äöüßéèâ", "< ä ß á â & 木 >" }; 

    foreach (string text in testStrings) 
    { 
     Console.WriteLine(ReencodeText(text)); 
    } 
} 

private static string ReencodeText(string text) 
{ 
    Encoding encoding = Encoding.GetEncoding(1252); 
    string text1252 = encoding.GetString(encoding.GetBytes(text)); 

    return text.Equals(text1252, StringComparison.Ordinal) ? 
     text : Convert.ToBase64String(Encoding.UTF8.GetBytes(text)); 
} 

I. 텍스트를 Windows-1252로 인코딩 한 다음 string 객체로 디코딩 한 다음 원본과 비교합니다. 비교가 성공하면 원래 문자열을 반환하고 그렇지 않으면 UTF8로 인코딩 한 다음 base64로 인코딩합니다.

그것은 다음과 같은 출력이 생성 제는베이스 64로 인코딩하는 동안

DJ Doena
äöüßéèâ
PCDDpCDDnyDDoSDDoiAmIOacqCA +

환언하여, 처음 두 개의 스트링은 그대로 유지된다.

+0

이 문제는 문자열이 Base64로 인코딩되었는지 또는 원본인지 여부를 확인할 수 없다는 문제가 있습니다. – CodesInChaos

+0

위의 예를 수정하여 원할 경우 해당 정보를 호출자에게 다시 전달하는 것은 간단합니다. 반환 값을 전달 된 값과 단순히 비교하는 것이 대부분의 경우 충분하다고 생각합니다 (OP가 _already_ base64 인 입력 문자열을 처리하는 경우에만 작동하지 않을 것입니다). –

+0

고마워요, 그게 정확히 내가 성취하려고 시도한 것이 었습니다! –

1

첫 번째 코드에서는 한 인코딩을 사용하여 문자열을 인코딩 한 다음 다른 인코딩을 사용하여이를 디코딩합니다. 그렇다고해서 전혀 신뢰할만한 결과를 얻지는 못합니다. 8 진수로 숫자를 쓴 다음 10 진수로 읽는 것과 같습니다. 7까지 숫자에 대해서는 정상적으로 작동하지만 이후에는 쓸모없는 결과를 얻습니다.

GetBase64Alternate 메서드의 문제는 두 개의 다른 인코딩으로 문자열을 인코딩한다는 것이며 두 번째 인코딩이 다른 바이트 집합으로 된 경우 첫 번째 인코딩이 일부 문자를 지원하지 않는다고 가정합니다.

바이트 시퀀스를 비교해도 인코딩에 실패했는지 여부는 알 수 없습니다. 실패하면 시퀀스가 ​​달라 지지만 인코딩간에 다르게 인코딩 된 문자가있는 경우 시퀀스가 ​​달라집니다.

인코딩이 실제로 모든 문자에 대해 작동했는지 확인하는 것입니다. 지원되지 않는 문자에 대한 대체 문자를 사용하여 Encoding 인스턴스를 생성하면됩니다. 이 경우 사용할 수있는 EncoderExceptionFallback 클래스가 있으며, 호출되면 EncoderFallbackException을 던집니다.

이 코드 인코딩이 문자열의 모든 문자를 지원하지 않는 경우 문자열에서 Windows-1252 인코딩을 사용하려고하고 falseok 변수를 설정합니다 :

Encoding e = Encoding.GetEncoding(1252, new EncoderExceptionFallback(), new DecoderExceptionFallback()); 
bool ok = true; 
try { 
    e.GetByteCount(allIn); 
} catch (EncoderFallbackException) { 
    ok = false; 
} 

을 실제로하지 않는 한 인코딩 된 결과를 아무 것도 사용하지 않으려면 GetByteCount 메서드를 사용할 수 있습니다. 인코딩 된 결과를 생성하지 않고 모든 문자가 어떻게 인코딩되는지 확인합니다.

는 것이 당신의 방법에 사용되는 :

private static String GetBase64Alternate(string text) { 
    Encoding e = Encoding.GetEncoding(1252, new EncoderExceptionFallback(), new DecoderExceptionFallback()); 
    bool ok = true; 
    try { 
    e.GetByteCount(allIn); 
    } catch (EncoderFallbackException) { 
    ok = false; 
    } 
    return ok ? null : Convert.ToBase64(Encoding.UTF8.GetBytes(text)); 
}