UTF-8 바이트 []를 문자열로 변환하는 방법?


932

나는이 byte[]내가 알고 일이있는 파일에서로드되는 배열은 포함 UTF-8 .

일부 디버깅 코드에서는 문자열로 변환해야합니다. 이것을 할 하나의 라이너가 있습니까?

표지 아래에는 할당 및 memcopy 일뿐 이므로 구현되지 않더라도 가능해야합니다.


5
.NET 문자열이 UTF-16으로 인코딩 되었기 때문에 "할당과 memcopy 일뿐"입니다. 유니 코드 문자는 하나의 UTF-8 코드 단위 또는 하나의 UTF-16 코드 단위 일 수 있습니다. 다른 하나는 두 개의 UTF-8 코드 단위 또는 하나의 UTF-16 코드 단위 일 수 있고, 다른 하나는 세 개의 UTF-8 코드 단위 또는 하나의 UTF-16 코드 단위 일 수 있으며, 다른 하나는 네 개의 UTF-8 코드 단위 또는 두 개의 UTF-16 코드 단위 일 수 있습니다. . memcopy는 확장 할 수 있지만 UTF-8에서 UTF-16으로의 변환은 처리 할 수 ​​없습니다.
Tom Blodget 1

답변:


1469
string result = System.Text.Encoding.UTF8.GetString(byteArray);

13
null로 끝나는 문자열을 어떻게 처리합니까?
maazza

14
알 수없는 이유로 @maazza는 전혀하지 않습니다. 나는 그것을 그렇게 부르고있다 System.Text.Encoding.UTF8.GetString(buf).TrimEnd('\0');.
Hi-Angel

15
@ Hi-Angel 알 수없는 이유? null로 끝나는 문자열이 대중화 된 유일한 이유는 C 언어였습니다. 심지어 역사적인 홀수 (널로 끝나는 문자열을 처리하는 CPU 명령어) 때문이었습니다. .NET은 null로 끝나는 문자열을 사용하는 코드 ( 마지막으로 사라지는)를 사용하여 null로 끝나는 문자열 만 사용합니다 . 문자열에 NUL 문자를 포함하는 것이 완벽하게 유효합니다. 물론 Null로 끝나는 문자열은 ASCII에서 간단하지 않지만 (첫 번째 0 바이트를 얻을 때까지 빌드) UTF-8을 포함한 다른 인코딩은 그렇게 간단하지 않습니다.
Luaan

4
UTF-8의 아름다운 기능 중 하나는 짧은 시퀀스가 ​​더 긴 시퀀스의 하위 시퀀스가 ​​아니라는 것입니다. 따라서 null로 끝나는 UTF-8 문자열은 간단합니다.
plugwash

10
ASCII가 아닌 경우 포장을 풀고 행운을 빕니다. Convert.ToBase64String을 사용하십시오.
Erik Bergstedt

323

이 전환을 수행하는 방법에는 적어도 네 가지가 있습니다.

  1. 인코딩의 GetString
    이지만 ASCII가 아닌 문자가있는 바이트는 원래 바이트를 되돌릴 수 없습니다.

  2. BitConverter.ToString
    출력은 "-"로 구분 된 문자열이지만 문자열을 바이트 배열로 다시 변환하는 .NET 기본 제공 방법은 없습니다.

  3. Convert.ToBase64String
    을 사용하여 출력 문자열을 바이트 배열로 쉽게 변환 할 수 있습니다 Convert.FromBase64String.
    참고 : 출력 문자열에는 '+', '/'및 '='이 포함될 수 있습니다. URL에서 문자열을 사용하려면 명시 적으로 인코딩해야합니다.

  4. HttpServerUtility.UrlTokenEncode
    을 사용하여 출력 문자열을 바이트 배열로 쉽게 변환 할 수 있습니다 HttpServerUtility.UrlTokenDecode. 출력 문자열은 이미 URL 친화적입니다! 단점은 System.Web프로젝트가 웹 프로젝트가 아닌 경우 어셈블리 가 필요하다는 것 입니다.

전체 예 :

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

7
LINQ 그것 :var decBytes2 = str.Split('-').Select(ch => Convert.ToByte(ch, 16)).ToArray();
drtf

25

인코딩을 모르는 경우 바이트 배열에서 문자열로 변환하는 일반적인 솔루션 :

static string BytesToStringConverted(byte[] bytes)
{
    using (var stream = new MemoryStream(bytes))
    {
        using (var streamReader = new StreamReader(stream))
        {
            return streamReader.ReadToEnd();
        }
    }
}

3
그러나 이것은 바이트 스트림에 인코딩 BOM이 있거나 UTF-8에 있다고 가정합니다. 그러나 어쨌든 Encoding을 사용하여 동일한 작업을 수행 할 수 있습니다. 인코딩을 모르면 문제를 마술처럼 해결하지 못합니다.
Sebastian Zander

12

정의:

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

사용 :

string result = input.ConvertByteToString();

9

를 a byte[]로 변환하는 string것은 간단 해 보이지만 모든 종류의 인코딩은 출력 문자열을 망칠 수 있습니다. 이 작은 기능은 예기치 않은 결과없이 작동합니다.

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

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

    return response;
}

Convert.FromBase64String으로 압축을 풀 때 메서드를 사용하여 System.FormatException을 받았습니다.
Erik Bergstedt

@ AndrewJE 그림에서 사용 된 것과 같은 큰 바이트 배열이있는 경우 계산하는 데에도 시간이 걸립니다.
user3841581

7

(byte)b.ToString("x2"), 출력 사용b4b5dfe475e58b67

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;
    }

}

4

사용법이 매우 간단한 UnicodeEncoding 클래스도 있습니다.

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

Console.WriteLine("Data after decoding: {0}", ByteConverter.GetString(dataEncoded));

그러나 UTF-8 방식은 아닙니까?
david.pfx

1
UnicodeEncoding최악의 클래스 이름입니다. 유니 코드는 전혀 인코딩이 아닙니다. 이 클래스는 실제로 UTF-16입니다. 리틀 엔디안 버전이라고 생각합니다.
Nyerguds

3

또는

 var byteStr = Convert.ToBase64String(bytes);

2

byteArrFilename파일에서 읽은 바이트 배열 을 순수한 ASCII C 스타일의 0으로 끝나는 문자열 로 변환하기위한 Linq one-liner는 다음과 같습니다.

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

나는 '?'순수한 ASCII가 아닌 것을 기본 문자로 사용 하지만 물론 변경할 수 있습니다. 처음에이 방법으로 작성된 문자열이 입력 소스의 값을 포함 할 수 없도록 하기 때문에이를 감지 할 수 있으려면 '\0'대신 사용 하십시오.TakeWhile'\0'


2

BitConverter클래스는 변환 할 수 있습니다 byte[]string.

var convertedString = BitConverter.ToString(byteAttay);

MSDNBitConverter클래스 문서를 정리할 수 있습니다


1
이것은 바이트 배열을 각 바이트를 나타내는 16 진 문자열로 변환하는데, 이것은 일반적으로 바이트를 문자열로 변환 할 때 원하는 것이 아닙니다. 그렇다면 다른 질문입니다. 예를 들어 바이트 배열을 16 진수 문자열로 어떻게 변환합니까? .
CodeCaster

OP가 요청한 내용이 아님
Winter

2

내 지식으로는 주어진 대답 중 아무것도 널 종료와 함께 올바른 동작을 보장하지 않습니다. 누군가 나를 다르게 보여줄 때까지 나는 다음 방법으로 이것을 처리하기 위해 자신의 정적 클래스를 작성했습니다.

// 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);
}

에 대한 이유는 startIndex내가 구체적으로 작업 한 예제 byte[]에서 null 종료 문자열의 배열 로 구문 분석해야했습니다 . 간단한 경우에는 무시해도됩니다


실제로는 그렇습니다. byteArr.TakeWhile(x => x != 0)널 종료 문제를 해결하는 빠르고 쉬운 방법입니다.
Nyerguds

1

hier는 인코딩에 신경 쓸 필요가없는 결과입니다. 나는 그것을 네트워크 클래스에서 사용하고 바이너리 객체를 문자열로 보냅니다.

        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);
        }

하나도 없었습니다. 그러나이 기능은 회사 네트워크에서 이진 전송에 사용되고 있으며 지금까지 20TB가 올바르게 다시 인코딩되고 인코딩되었습니다. 그래서 나를 위해이 기능은 작동합니다 :)
Marco Pardo

1

선택한 답변과 함께 .NET35 또는 .NET35 CE를 사용하는 경우 디코딩 할 첫 번째 바이트의 인덱스와 디코딩 할 바이트 수를 지정해야합니다.

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

0

이 콘솔 앱을 사용해보십시오 :

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);
}

0

이 게시물에서 일부 답변을 보았으며 동일한 문제를 해결하기 위해 C # 프로그래밍에 여러 가지 접근 방식이 있기 때문에 완전한 기본 지식으로 간주 될 수 있습니다. 고려해야 할 유일한 것은 BOMPure UTF-8UTF-8 의 차이점에 관한 것입니다 .

지난 주에, 나는 일할 때 BOM을 사용하여 CSV 파일을 출력하고 BOM이없는 순수한 UTF-8을 사용하는 다른 CSV를 출력하는 하나의 기능을 개발해야합니다. 각 CSV 파일 인코딩 유형은 표준화되지 않은 다른 API에 의해 소비됩니다. BOM이있는 API 읽기 UTF-8 및 BOM이없는 다른 API 읽기 이 개념에 대한 참고 자료를 조사하여 " BOM없이 UTF-8과 UTF-8의 차이점은 무엇입니까? "를 읽어야합니다. 스택 오버플로 토론과이 Wikipedia 링크 " Byte order mark "는 내 접근 방식을 구축합니다.

마지막으로, UTF-8 인코딩 유형 (BOM 및 순수 모두)에 대한 C # 프로그래밍은 다음 예제와 유사해야합니다.

//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);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.