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のすべての文字列は、Unicode文字を使用して内部的に文字列を格納します。文字列が「windows-1252」、「iso-8859-1」、「utf-8」などであるという概念はありません。Windowsで表現されていない文字列の文字を破棄しようとしていますか? -1252コードページ?
Ian Boyd、

1
@IanBoyd実際には、文字列はUTF-16コード単位のカウントされたシーケンスです。(残念ながら、Unicodeという用語Encoding.UnicodeはWin32 APIで誤って適用されています。Unicodeは文字セットであり、エンコーディングではありません
。UTF

1
正しくないアクションを実行します。バイト配列をutf8エンコーディングで作成しますが、isoデコードで読み取ります。エンコードされたシンボルで文字列を作成したい場合は、単純に文字列を
StuS 2017

それはもじばけです。
リックジェームズ

Daniilが言っていることMessageは、UTF-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
1つのライナーは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(変数「Unicode」)からエンコードする必要があります。これがデフォルトだからです。したがって、上記のコードのUTF8をUnicodeに変更する必要があります。
goamn 2017年

これを使用することをお勧めします:Encoding iso = Encoding.GetEncoding( "ISO-8859-9"); トルコ語のエンコーディングはラテン語から拡張されたほとんどすべてのアルファベットをカバーするためです。
Fuat 2018

26

あなたの問題は、utf8文字列を表すバイトが別の文字列(iso-8859-1)として解釈されたときに同じ文字列になると想定していることだと思います。そして、それは単に事実ではありません。Joel spolskyによるこの優れた記事を読むことをお勧めします。


1
確かにユーモアのセンスのある逸品!今日、仕事でエンコーディングの問題に直面していましたが、これが助けになりました。
Pantelis 2012

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>を渡したので、同じ出力がmsg varieableに入りました。ラテンデータを取得する方法は?
user1237131 2013年

これでうまくいきます。System.Text名前空間を含めることを忘れないでください。
Spawnrider 2013年

2
Encoding.Convertは、文字列に非
ISO

8

最初に文字列のソースを修正する必要があります。

.NETの文字列は、実際には単なる16ビットのUnicodeコードポイント、文字の配列なので、文字列は特定のエンコーディングではありません。

その文字列をバイトのセットに変換するときに、エンコーディングが機能します。

いずれにしても、文字列を1つの文字セットでバイト配列にエンコードし、次に別の文字セットでデコードする方法は、ご覧のとおり機能しません。

その元の文字列がどこから来たのか、なぜ間違ってエンコードされたと思うのかについて教えてください。


それはApp.configから直接来ており、デフォルトではUTF8だと思っていました。ありがとうございました!
Daniil Harik 09

そのファイルのエンコードは、ファイルの解釈方法に影響を与える可能性があるため、それを調べます。
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を使用している場合、バイトアレイを誤ったエンコーディングの文字列に変換すると情報が失われるため、これを正しいエンコーディングにすることは非常に困難です。
サンダーA

0

ネイサンのソリューションを使用しただけで問題なく動作します。ISO-8859-1をUnicodeに変換する必要がありました。

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.