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.