Bagaimana cara mengubah UTF-8 byte [] ke string?

932

Saya memiliki byte[]array yang diambil dari file yang kebetulan saya kenal mengandung UTF-8 .

Dalam beberapa kode debug, saya perlu mengubahnya menjadi string. Apakah ada satu liner yang akan melakukan ini?

Di bawah selimut itu harus hanya alokasi dan memo , jadi bahkan jika itu tidak dilaksanakan, itu harus mungkin.

BCS
sumber
5
"seharusnya hanya alokasi dan memo": tidak benar karena string .NET dikodekan UTF-16. Karakter Unicode mungkin satu unit kode UTF-8 atau satu unit kode UTF-16. yang lain mungkin dua unit kode UTF-8 atau satu unit kode UTF-16, yang lain mungkin tiga unit kode UTF-8 atau satu unit kode UTF-16, yang lain mungkin empat unit kode UTF-8 atau dua unit kode UTF-16 . Sebuah memo mungkin bisa melebar tetapi itu tidak akan mampu menangani konversi UTF-8 ke UTF-16.
Tom Blodget

Jawaban:

1470
string result = System.Text.Encoding.UTF8.GetString(byteArray);
Zanoni
sumber
13
bagaimana cara menangani string null berakhir?
maazza
14
@ MAZZA untuk alasan yang tidak diketahui tidak sama sekali. Saya menyebutnya seperti System.Text.Encoding.UTF8.GetString(buf).TrimEnd('\0');.
Hi-Angel
15
@ Hai-Angel Alasan tidak diketahui? Satu-satunya alasan null-terminated string menjadi populer adalah bahasa C - dan bahkan itu hanya karena keanehan historis (instruksi CPU yang berurusan dengan string null-dihentikan). .NET hanya menggunakan string yang diakhiri dengan nol ketika interupsi dengan kode yang menggunakan string yang diakhiri dengan nol (yang akhirnya menghilang). Ini benar-benar valid untuk string yang berisi karakter NUL. Dan tentu saja, sementara string null-terminated mati sederhana di ASCII (hanya membangun sampai Anda mendapatkan nol byte pertama), pengkodean lainnya, termasuk UTF-8, tidak begitu sederhana.
Luaan
4
Salah satu fitur UTF-8 yang indah adalah bahwa urutan yang lebih pendek tidak pernah merupakan urutan yang lebih lama. Jadi string UTF-8 null yang diakhiri adalah sederhana.
plugwash
10
Yah, semoga berhasil membongkar jika memiliki non-ascii. Cukup gunakan Convert.ToBase64String.
Erik Bergstedt
323

Setidaknya ada empat cara berbeda melakukan konversi ini.

  1. Encoding's GetString
    , tetapi Anda tidak akan bisa mendapatkan kembali byte asli jika byte tersebut memiliki karakter non-ASCII.

  2. BitConverter.ToString
    Outputnya adalah string yang dibatasi "-", tetapi tidak ada metode .NET built-in untuk mengubah string kembali ke byte array.

  3. Convert.ToBase64String
    Anda dapat dengan mudah mengkonversi string output kembali ke byte array dengan menggunakan Convert.FromBase64String.
    Catatan: String output dapat berisi '+', '/' dan '='. Jika Anda ingin menggunakan string dalam URL, Anda harus menyandikannya secara eksplisit.

  4. HttpServerUtility.UrlTokenEncode
    Anda dapat dengan mudah mengkonversi string output kembali ke byte array dengan menggunakan HttpServerUtility.UrlTokenDecode. String output sudah ramah URL! Kelemahannya adalah perlu System.Webperakitan jika proyek Anda bukan proyek web.

Contoh lengkap:

byte[] bytes = { 130, 200, 234, 23 }; // A byte array contains non-ASCII (or non-readable) characters

string s1 = Encoding.UTF8.GetString(bytes); // ���
byte[] decBytes1 = Encoding.UTF8.GetBytes(s1);  // decBytes1.Length == 10 !!
// decBytes1 not same as bytes
// Using UTF-8 or other Encoding object will get similar results

string s2 = BitConverter.ToString(bytes);   // 82-C8-EA-17
String[] tempAry = s2.Split('-');
byte[] decBytes2 = new byte[tempAry.Length];
for (int i = 0; i < tempAry.Length; i++)
    decBytes2[i] = Convert.ToByte(tempAry[i], 16);
// decBytes2 same as bytes

string s3 = Convert.ToBase64String(bytes);  // gsjqFw==
byte[] decByte3 = Convert.FromBase64String(s3);
// decByte3 same as bytes

string s4 = HttpServerUtility.UrlTokenEncode(bytes);    // gsjqFw2
byte[] decBytes4 = HttpServerUtility.UrlTokenDecode(s4);
// decBytes4 same as bytes
detale
sumber
7
LINQ:var decBytes2 = str.Split('-').Select(ch => Convert.ToByte(ch, 16)).ToArray();
drtf
25

Solusi umum untuk mengkonversi dari array byte ke string ketika Anda tidak tahu pengkodeannya:

static string BytesToStringConverted(byte[] bytes)
{
    using (var stream = new MemoryStream(bytes))
    {
        using (var streamReader = new StreamReader(stream))
        {
            return streamReader.ReadToEnd();
        }
    }
}
Nir
sumber
3
Tetapi ini mengasumsikan bahwa ada BOM pengkodean dalam aliran byte atau bahwa itu dalam UTF-8. Tetapi Anda tetap bisa melakukan hal yang sama dengan Encoding. Itu tidak secara ajaib memecahkan masalah ketika Anda tidak tahu pengkodean.
Sebastian Zander
12

Definisi:

public static string ConvertByteToString(this byte[] source)
{
    return source != null ? System.Text.Encoding.UTF8.GetString(source) : null;
}

Menggunakan:

string result = input.ConvertByteToString();
Erçin Dedeoğlu
sumber
9

Konversi a byte[]ke yang stringtampak sederhana tetapi segala jenis pengkodean cenderung mengacaukan string keluaran. Fungsi kecil ini hanya berfungsi tanpa hasil yang tidak terduga:

private string ToString(byte[] bytes)
{
    string response = string.Empty;

    foreach (byte b in bytes)
        response += (Char)b;

    return response;
}
AndrewJE
sumber
Saya menerima System.FormatException menggunakan metode Anda ketika saya membukanya dengan Convert.FromBase64String.
Erik Bergstedt
@ AndrewJE ini akan diperlukan bahkan untuk menghitung jika Anda memiliki array byte besar seperti yang digunakan dari gambar.
user3841581
7

Menggunakan (byte)b.ToString("x2"), Outputb4b5dfe475e58b67

public static class Ext {

    public static string ToHexString(this byte[] hex)
    {
        if (hex == null) return null;
        if (hex.Length == 0) return string.Empty;

        var s = new StringBuilder();
        foreach (byte b in hex) {
            s.Append(b.ToString("x2"));
        }
        return s.ToString();
    }

    public static byte[] ToHexBytes(this string hex)
    {
        if (hex == null) return null;
        if (hex.Length == 0) return new byte[0];

        int l = hex.Length / 2;
        var b = new byte[l];
        for (int i = 0; i < l; ++i) {
            b[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
        }
        return b;
    }

    public static bool EqualsTo(this byte[] bytes, byte[] bytesToCompare)
    {
        if (bytes == null && bytesToCompare == null) return true; // ?
        if (bytes == null || bytesToCompare == null) return false;
        if (object.ReferenceEquals(bytes, bytesToCompare)) return true;

        if (bytes.Length != bytesToCompare.Length) return false;

        for (int i = 0; i < bytes.Length; ++i) {
            if (bytes[i] != bytesToCompare[i]) return false;
        }
        return true;
    }

}
metadings
sumber
4

Ada juga kelas UnicodeEncoding, cukup sederhana dalam penggunaan:

ByteConverter = new UnicodeEncoding();
string stringDataForEncoding = "My Secret Data!";
byte[] dataEncoded = ByteConverter.GetBytes(stringDataForEncoding);

Console.WriteLine("Data after decoding: {0}", ByteConverter.GetString(dataEncoded));
PK
sumber
Tapi bukan metode UTF-8?
david.pfx
1
UnicodeEncodingadalah nama kelas terburuk yang pernah ada; unicode sama sekali bukan encoding. Kelas itu sebenarnya adalah UTF-16. Versi little-endian, kurasa.
Nyerguds
3

Kalau tidak:

 var byteStr = Convert.ToBase64String(bytes);
Fehr
sumber
2

Linq one-liner untuk mengonversi byte array yang byteArrFilenamedibaca dari file ke string ascii C-style nol murni akan seperti ini: Berguna untuk membaca hal-hal seperti tabel indeks file dalam format arsip lama.

String filename = new String(byteArrFilename.TakeWhile(x => x != 0)
                              .Select(x => x < 128 ? (Char)x : '?').ToArray());

Saya menggunakan '?'sebagai default char untuk apa pun yang bukan ascii murni di sini, tapi itu bisa diubah, tentu saja. Jika Anda ingin memastikan Anda bisa mendeteksinya, gunakan '\0'saja, karena TakeWhilepada awalnya memastikan bahwa string yang dibangun dengan cara ini tidak mungkin mengandung '\0'nilai dari sumber input.

Nyergud
sumber
2

BitConverterkelas dapat digunakan untuk mengonversi a byte[]menjadi string.

var convertedString = BitConverter.ToString(byteAttay);

Dokumentasi BitConverterkelas dapat diperoleh di MSDN

Sagar
sumber
1
Ini mengkonversi array byte ke string heksadesimal yang mewakili setiap byte, yang umumnya tidak seperti yang Anda inginkan ketika mengkonversi byte ke string. Jika ya, maka itu adalah pertanyaan lain, lihat misalnya Bagaimana Anda mengonversi Byte Array ke Hexadecimal String, dan sebaliknya? .
CodeCaster
Bukan yang diminta OP
Musim Dingin
2

Setahu saya tidak ada jawaban yang diberikan menjamin perilaku yang benar dengan nol penghentian. Sampai seseorang menunjukkan saya berbeda saya menulis kelas statis saya sendiri untuk menangani ini dengan metode berikut:

// Mimics the functionality of strlen() in c/c++
// Needed because niether StringBuilder or Encoding.*.GetString() handle \0 well
static int StringLength(byte[] buffer, int startIndex = 0)
{
    int strlen = 0;
    while
    (
        (startIndex + strlen + 1) < buffer.Length // Make sure incrementing won't break any bounds
        && buffer[startIndex + strlen] != 0       // The typical null terimation check
    )
    {
        ++strlen;
    }
    return strlen;
}

// This is messy, but I haven't found a built-in way in c# that guarentees null termination
public static string ParseBytes(byte[] buffer, out int strlen, int startIndex = 0)
{
    strlen = StringLength(buffer, startIndex);
    byte[] c_str = new byte[strlen];
    Array.Copy(buffer, startIndex, c_str, 0, strlen);
    return Encoding.UTF8.GetString(c_str);
}

Alasannya startIndexadalah dalam contoh yang saya kerjakan secara khusus saya perlu menguraikan byte[]sebagai array string diakhiri null. Ini dapat diabaikan dengan aman dalam kasus sederhana

Assimilater
sumber
Milik saya sebenarnya. byteArr.TakeWhile(x => x != 0)adalah cara cepat dan mudah untuk menyelesaikan masalah terminasi nol.
Nyerguds
1

hier adalah hasil di mana Anda tidak perlu repot dengan pengkodean. Saya menggunakannya di kelas jaringan saya dan mengirim objek biner sebagai string dengannya.

        public static byte[] String2ByteArray(string str)
        {
            char[] chars = str.ToArray();
            byte[] bytes = new byte[chars.Length * 2];

            for (int i = 0; i < chars.Length; i++)
                Array.Copy(BitConverter.GetBytes(chars[i]), 0, bytes, i * 2, 2);

            return bytes;
        }

        public static string ByteArray2String(byte[] bytes)
        {
            char[] chars = new char[bytes.Length / 2];

            for (int i = 0; i < chars.Length; i++)
                chars[i] = BitConverter.ToChar(bytes, i * 2);

            return new string(chars);
        }
Marco Pardo
sumber
tidak punya satu. Tetapi fungsi ini digunakan untuk transmisi biner di jaringan perusahaan kami dan sejauh ini 20TB telah kembali dan disandikan dengan benar. Jadi bagi saya fungsi ini berfungsi :)
Marco Pardo
1

Selain jawaban yang dipilih, jika Anda menggunakan .NET35 atau .NET35 CE, Anda harus menentukan indeks byte pertama yang akan di-decode, dan jumlah byte yang di-decode:

string result = System.Text.Encoding.UTF8.GetString(byteArray,0,byteArray.Length);
Yang satu
sumber
0

Coba aplikasi konsol ini:

static void Main(string[] args)
{
    //Encoding _UTF8 = Encoding.UTF8;
    string[] _mainString = { "Héllo World" };
    Console.WriteLine("Main String: " + _mainString);

    //Convert a string to utf-8 bytes.
    byte[] _utf8Bytes = Encoding.UTF8.GetBytes(_mainString[0]);

    //Convert utf-8 bytes to a string.
    string _stringuUnicode = Encoding.UTF8.GetString(_utf8Bytes);
    Console.WriteLine("String Unicode: " + _stringuUnicode);
}
RM Shahidul Islam Shahed
sumber
0

Saya melihat beberapa jawaban di posting ini dan dimungkinkan untuk dianggap pengetahuan dasar yang lengkap, karena memiliki beberapa pendekatan dalam Pemrograman C # untuk menyelesaikan masalah yang sama. Hanya satu hal yang perlu dipertimbangkan adalah tentang perbedaan antara Pure UTF-8 dan UTF-8 dengan BOM .

Pada minggu lalu, di pekerjaan saya, saya perlu mengembangkan satu fungsionalitas yang menghasilkan file CSV dengan BOM dan CSV lainnya dengan UTF-8 murni (tanpa BOM), setiap jenis file CSV Encoding akan dikonsumsi oleh berbagai API non-standar, yang API membaca UTF-8 dengan BOM dan API lainnya membaca tanpa BOM. Saya perlu meneliti referensi tentang konsep ini, membaca " Apa perbedaan antara UTF-8 dan UTF-8 tanpa BOM? " Diskusi Stack Overflow dan tautan Wikipedia ini " Tanda urutan Byte " untuk membangun pendekatan saya.

Akhirnya, Pemrograman C # saya untuk kedua jenis pengkodean UTF-8 (dengan BOM dan murni) harus serupa seperti contoh di bawah ini:

//for UTF-8 with B.O.M., equals shared by Zanoni (at top)
string result = System.Text.Encoding.UTF8.GetString(byteArray);

//for Pure UTF-8 (without B.O.M.)
string result = (new UTF8Encoding(false)).GetString(byteArray);
Antonio Leonardo
sumber