C # UTF-8에서 ISO-8859-1 (Latin1) H로 문자열 변환


103

이 주제에 대해 검색해 보았고 모든 답변을 살펴 보았지만 여전히 이해하지 못했습니다.

기본적으로 UTF-8 문자열을 ISO-8859-1로 변환해야하며 다음 코드를 사용하여 수행합니다.

Encoding iso = Encoding.GetEncoding("ISO-8859-1");
Encoding utf8 = Encoding.UTF8;
string msg = iso.GetString(utf8.GetBytes(Message));

내 소스 문자열은

Message = "ÄäÖöÕõÜü"

하지만 불행히도 내 결과 문자열은

msg = "�ä�ö�õ�ü

내가 여기서 뭘 잘못하고 있니?


5
.NET의 모든 문자열은 유니 코드 문자를 사용하여 내부적으로 문자열을 저장합니다. 문자열이 "windows-1252", "iso-8859-1", "utf-8"등이라는 개념이 없습니다. 문자열에서 Windows에서 표현이없는 문자를 버리려고합니까? -1252 코드 페이지?
Ian Boyd

1
@IanBoyd 실제로 문자열 은 UTF-16 코드 단위의 계수 된 시퀀스입니다. (안타깝게도 유니 코드라는 용어가 Encoding.UnicodeWin32 API에 잘못 적용되었습니다 . 유니 코드는 인코딩이 아니라 문자 집합입니다. UTF-16은 유니 코드를위한 여러 인코딩 중 하나입니다.)
Tom Blodget

1
잘못된 동작을합니다. utf8 인코딩으로 바이트 배열을 만들지 만 iso 디코딩으로 읽습니다. 인코딩 된 기호로 문자열을 만들려면 간단한 호출 string msg = iso.GetString (iso.GetBytes (Message));
StuS

모지 바케라고합니다.
릭 제임스

Daniil이 말하는 것은 MessageUTF-8에서 디코딩 된 것입니다. 해당 부분이 올바르게 작동했다고 가정하면 Latin-1로 변환하는 것은 byte[] bytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(Message). 그런 다음 StuS가 말했듯이 Latin-1 바이트를 다시 UTF-16으로 변환 할 수 있습니다.Encoding.GetEncoding("ISO-8859-1").GetString(bytes)
Qwertie

답변:


176

인코딩 을 대상 인코딩으로 디코딩하기 전에 Encoding.Convert 를 사용 하여 바이트 배열을 조정합니다.

Encoding iso = Encoding.GetEncoding("ISO-8859-1");
Encoding utf8 = Encoding.UTF8;
byte[] utfBytes = utf8.GetBytes(Message);
byte[] isoBytes = Encoding.Convert(utf8, iso, utfBytes);
string msg = iso.GetString(isoBytes);

7
한 줄은Encoding.GetEncoding("ISO-8859-1").GetString(Encoding.Convert(Encoding.UTF8, Encoding.GetEncoding("ISO-8859-1"), Encoding.UTF8.GetBytes(myString)))

1
C # /. Net에서 직접 문자열을 생성하는 경우이 코드가 100 % 정확하지 않습니다. UTF-16 (변수 "유니 코드")에서 인코딩해야합니다. 이것이 기본값이기 때문입니다. 따라서 위 코드의 UTF8은 유니 코드로 변경해야합니다.
goamn

다음을 사용하는 것이 좋습니다. Encoding iso = Encoding.GetEncoding ( "ISO-8859-9"); 터키어 인코딩은 라틴어에서 확장 된 모든 알파벳을 포함하기 때문입니다.
Fuat

26

문제는 utf8 문자열을 나타내는 바이트가 다른 것으로 해석 될 때 동일한 문자열이된다고 가정한다는 것입니다 (iso-8859-1). 그리고 그것은 단지 사실이 아닙니다. Joel spolsky 의이 훌륭한 기사 를 읽어 보시기 바랍니다.


1
참으로 유머 감각이있는 훌륭한 기사! 나는 오늘 직장에서 인코딩 문제에 직면했고 이것이 나를 도왔습니다.
Pantelis 2012-08-23

16

이 시도:

Encoding iso = Encoding.GetEncoding("ISO-8859-1");
Encoding utf8 = Encoding.UTF8;
byte[] utfBytes = utf8.GetBytes(Message);
byte[] isoBytes = Encoding.Convert(utf8,iso,utfBytes);
string msg = iso.GetString(isoBytes);

왜 동일한 utf-8 메시지를 받고 있습니까? 메시지 대신에 string message = <name> sdjfhsjdf </ name> .then msg varieable.how to get latin data?
user1237131

이것은 나를 위해 작동합니다. System.Text 네임 스페이스를 포함해야합니다.
Spawnrider

2
Encoding.Convert는 문자열에 비 iso 문자가있는 경우 변환하는 동안 폴백 예외를 throw합니다.
Tertium

8

먼저 문자열의 소스를 수정해야합니다.

.NET의 문자열은 실제로 16 비트 유니 코드 코드 포인트, 문자의 배열 일 뿐이므로 문자열은 특정 인코딩이 아닙니다.

해당 문자열을 가져 와서 인코딩이 작동하는 바이트 집합으로 변환 할 때입니다.

어쨌든 한 문자 세트로 문자열을 바이트 배열로 인코딩 한 다음 다른 문자 세트로 디코딩하는 방식은 작동하지 않습니다.

원래 문자열의 출처와 인코딩이 잘못되었다고 생각하는 이유에 대해 자세히 설명해 주시겠습니까?


App.config에서 직접오고 있으며 기본적으로 UTF8이라고 생각했습니다. 감사합니다!
Daniil Harik

해당 파일의 인코딩은 파일이 해석되는 방식에 영향을 미칠 수 있으므로 살펴 보겠습니다.
Lasse V. Karlsen

2
내가 틀렸다면 저를 정정하십시오. 그러나 기술적으로는 "특정 인코딩에 있지는 않지만".NET 문자열은 바이트 단위로 UTF-16 파일에 정확하게 해당하는 바이트 배열입니다 (제외 BOM). 심지어 같은 방식으로 대리를 사용합니다 (인코딩 트릭처럼 보입니다). 물론 일반적으로 파일을 UTF-8로 저장하지만 메모리의 데이터를 16 비트로 처리합니다. (또는 32 비트, 대리 쌍의 복잡성을 피하기 위해, 그것이 정말로 가능한지 확실하지 않습니다.)
Jon Coombs

6

약간 이상한 코드가 보입니다. Utf8 바이트 스트림에서 문자열을 얻으려면 다음을 수행하면됩니다.

string str = Encoding.UTF8.GetString(utf8ByteArray);

iso-8859-1 바이트 스트림을 어딘가에 저장해야하는 경우 다음을 사용하십시오. 이전에 대한 추가 코드 줄 :

byte[] iso88591data = Encoding.GetEncoding("ISO-8859-1").GetBytes(str);

1
이것은 분명히 가장 직접적인 대답입니다. 코드의 문제는 실제로 작성자가 C #의 문자열이 특정 인코딩을 "사용하여"이미 저장 될 수 있다고 가정하는 것 같습니다. 이는 사실이 아닙니다. 내부적으로는 항상 UTF16입니다.
Nyerguds

1
전적으로 동의. UTF-16이 이미 있으면 올바른 인코딩으로 만들기가 매우 어렵습니다. 잘못된 인코딩으로 바이트 배열을 문자열로 변환하면 이미 정보가 손실되기 때문입니다.
Sander A

0

Nathan의 솔루션을 사용했으며 제대로 작동합니다. ISO-8859-1을 유니 코드로 변환해야했습니다.

string isocontent = Encoding.GetEncoding("ISO-8859-1").GetString(fileContent, 0, fileContent.Length);
byte[] isobytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(isocontent);
byte[] ubytes = Encoding.Convert(Encoding.GetEncoding("ISO-8859-1"), Encoding.Unicode, isobytes);
return Encoding.Unicode.GetString(ubytes, 0, ubytes.Length);

0
Encoding targetEncoding = Encoding.GetEncoding(1252);
// Encode a string into an array of bytes.
Byte[] encodedBytes = targetEncoding.GetBytes(utfString);
// Show the encoded byte values.
Console.WriteLine("Encoded bytes: " + BitConverter.ToString(encodedBytes));
// Decode the byte array back to a string.
String decodedString = Encoding.Default.GetString(encodedBytes);

-5

다음은 ISO-8859-9의 샘플입니다.

protected void btnKaydet_Click(object sender, EventArgs e)
{
    Response.Clear();
    Response.Buffer = true;
    Response.ContentType = "application/vnd.openxmlformatsofficedocument.wordprocessingml.documet";
    Response.AddHeader("Content-Disposition", "attachment; filename=XXXX.doc");
    Response.ContentEncoding = Encoding.GetEncoding("ISO-8859-9");
    Response.Charset = "ISO-8859-9";
    EnableViewState = false;


    StringWriter writer = new StringWriter();
    HtmlTextWriter html = new HtmlTextWriter(writer);
    form1.RenderControl(html);


    byte[] bytesInStream = Encoding.GetEncoding("iso-8859-9").GetBytes(writer.ToString());
    MemoryStream memoryStream = new MemoryStream(bytesInStream);


    string msgBody = "";
    string Email = "mail@xxxxxx.org";
    SmtpClient client = new SmtpClient("mail.xxxxx.org");
    MailMessage message = new MailMessage(Email, "mail@someone.com", "ONLINE APP FORM WITH WORD DOC", msgBody);
    Attachment att = new Attachment(memoryStream, "XXXX.doc", "application/vnd.openxmlformatsofficedocument.wordprocessingml.documet");
    message.Attachments.Add(att);
    message.BodyEncoding = System.Text.Encoding.UTF8;
    message.IsBodyHtml = true;
    client.Send(message);}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.