.net string - Wie bekomme ich eine konsistente Byte-Darstellung von Zeichenfolgen in C#, ohne manuell eine Codierung festzulegen?




symbol prefix (25)

Wie konvertiere ich eine string in ein byte[] in .NET (C #), ohne manuell eine spezifische Kodierung anzugeben?

Ich werde die Zeichenfolge verschlüsseln. Ich kann es ohne Konvertierung verschlüsseln, aber ich würde immer noch gerne wissen, warum die Codierung hier zum Einsatz kommt.

Auch warum sollte Codierung in Betracht gezogen werden? Kann ich nicht einfach herausfinden, in welchen Bytes die Zeichenfolge gespeichert wurde? Warum besteht eine Abhängigkeit von Zeichenkodierungen?


Answers

Fastest way

public static byte[] GetBytes(string text)
{
    return System.Text.ASCIIEncoding.UTF8.GetBytes(text);
}

EDIT as Makotosan commented this is now the best way:

Encoding.UTF8.GetBytes(text)

You can use following code to convert a string to a byte array in .NET

string s_unicode = "abcéabc";
byte[] utf8Bytes = System.Text.Encoding.UTF8.GetBytes(s_unicode);

With the advent of Span<T> released with C# 7.2, the canonical technique to capture the underlying memory representation of a string into a managed byte array is:

byte[] bytes = "rubbish_\u9999_string".AsSpan().AsBytes().ToArray();

Converting it back should be a non-starter because that means you are in fact interpreting the data somehow, but for the sake of completeness:

string s;
unsafe
{
    fixed (char* f = &bytes.AsSpan().NonPortableCast<byte, char>().DangerousGetPinnableReference())
    {
        s = new string(f);
    }
}

The names NonPortableCast and DangerousGetPinnableReference should further the argument that you probably shouldn't be doing this.

Note that working with Span<T> requires installing the System.Memory NuGet package .

Regardless, the actual original question and follow-up comments imply that the underlying memory is not being "interpreted" (which I assume means is not modified or read beyond the need to write it as-is), indicating that some implementation of the Stream class should be used instead of reasoning about the data as strings at all.


BinaryFormatter bf = new BinaryFormatter();
byte[] bytes;
MemoryStream ms = new MemoryStream();

string orig = "喂 Hello 谢谢 Thank You";
bf.Serialize(ms, orig);
ms.Seek(0, 0);
bytes = ms.ToArray();

MessageBox.Show("Original bytes Length: " + bytes.Length.ToString());

MessageBox.Show("Original string Length: " + orig.Length.ToString());

for (int i = 0; i < bytes.Length; ++i) bytes[i] ^= 168; // pseudo encrypt
for (int i = 0; i < bytes.Length; ++i) bytes[i] ^= 168; // pseudo decrypt

BinaryFormatter bfx = new BinaryFormatter();
MemoryStream msx = new MemoryStream();            
msx.Write(bytes, 0, bytes.Length);
msx.Seek(0, 0);
string sx = (string)bfx.Deserialize(msx);

MessageBox.Show("Still intact :" + sx);

MessageBox.Show("Deserialize string Length(still intact): " 
    + sx.Length.ToString());

BinaryFormatter bfy = new BinaryFormatter();
MemoryStream msy = new MemoryStream();
bfy.Serialize(msy, sx);
msy.Seek(0, 0);
byte[] bytesy = msy.ToArray();

MessageBox.Show("Deserialize bytes Length(still intact): " 
   + bytesy.Length.ToString());

simple code with LINQ

string s = "abc"
byte[] b = s.Select(e => (byte)e).ToArray();

EDIT : as commented below, it is not a good way.

but you can still use it to understand LINQ with a more appropriate coding :

string s = "abc"
byte[] b = s.Cast<byte>().ToArray();

Es hängt von der Codierung Ihrer Zeichenfolge ab ( ASCII , UTF-8 , ...).

Beispielsweise:

byte[] b1 = System.Text.Encoding.UTF8.GetBytes (myString);
byte[] b2 = System.Text.Encoding.ASCII.GetBytes (myString);

Ein kleines Beispiel, warum Codierung wichtig ist:

string pi = "\u03a0";
byte[] ascii = System.Text.Encoding.ASCII.GetBytes (pi);
byte[] utf8 = System.Text.Encoding.UTF8.GetBytes (pi);

Console.WriteLine (ascii.Length); //Will print 1
Console.WriteLine (utf8.Length); //Will print 2
Console.WriteLine (System.Text.Encoding.ASCII.GetString (ascii)); //Will print '?'

ASCII ist einfach nicht mit Sonderzeichen ausgestattet.

Intern verwendet das .NET-Framework UTF-16 zum Darstellen von Zeichenfolgen. Wenn Sie also einfach die genauen von .NET verwendeten Byte System.Text.Encoding.Unicode.GetBytes (...) möchten, verwenden Sie System.Text.Encoding.Unicode.GetBytes (...) .

Weitere Informationen finden Sie unter Zeichencodierung in .NET Framework (MSDN).


Here is my unsafe implementation of String to Byte[] conversion:

public static unsafe Byte[] GetBytes(String s)
{
    Int32 length = s.Length * sizeof(Char);
    Byte[] bytes = new Byte[length];

    fixed (Char* pInput = s)
    fixed (Byte* pBytes = bytes)
    {
        Byte* source = (Byte*)pInput;
        Byte* destination = pBytes;

        if (length >= 16)
        {
            do
            {
                *((Int64*)destination) = *((Int64*)source);
                *((Int64*)(destination + 8)) = *((Int64*)(source + 8));

                source += 16;
                destination += 16;
            }
            while ((length -= 16) >= 16);
        }

        if (length > 0)
        {
            if ((length & 8) != 0)
            {
                *((Int64*)destination) = *((Int64*)source);

                source += 8;
                destination += 8;
            }

            if ((length & 4) != 0)
            {
                *((Int32*)destination) = *((Int32*)source);

                source += 4;
                destination += 4;
            }

            if ((length & 2) != 0)
            {
                *((Int16*)destination) = *((Int16*)source);

                source += 2;
                destination += 2;
            }

            if ((length & 1) != 0)
            {
                ++source;
                ++destination;

                destination[0] = source[0];
            }
        }
    }

    return bytes;
}

It's way faster than the accepted anwser's one, even if not as elegant as it is. Here are my Stopwatch benchmarks over 10000000 iterations:

[Second String: Length 20]
Buffer.BlockCopy: 746ms
Unsafe: 557ms

[Second String: Length 50]
Buffer.BlockCopy: 861ms
Unsafe: 753ms

[Third String: Length 100]
Buffer.BlockCopy: 1250ms
Unsafe: 1063ms

In order to use it, you have to tick "Allow Unsafe Code" in your project build properties. As per .NET Framework 3.5, this method can also be used as String extension:

public static unsafe class StringExtensions
{
    public static Byte[] ToByteArray(this String s)
    {
        // Method Code
    }
}

Bitte erläutern Sie auch, warum die Codierung berücksichtigt werden sollte. Kann ich nicht einfach herausfinden, in welchen Bytes die Zeichenfolge gespeichert wurde? Warum diese Abhängigkeit von der Kodierung? !!!

Weil es so etwas wie "die Bytes der Zeichenfolge" nicht gibt.

Eine Zeichenfolge (oder allgemeiner ein Text) besteht aus Zeichen: Buchstaben, Ziffern und anderen Symbolen. Das ist alles. Computer wissen jedoch nichts über Charaktere; Sie können nur mit Bytes umgehen. Wenn Sie also Text mithilfe eines Computers speichern oder übertragen möchten, müssen Sie die Zeichen in Bytes umwandeln. Wie machst du das? Hier kommen Codierungen zum Einsatz.

Eine Codierung ist nichts anderes als eine Konvention, um logische Zeichen in physikalische Bytes zu übersetzen. Die einfachste und am besten bekannte Kodierung ist ASCII, und es ist alles, was Sie brauchen, wenn Sie in Englisch schreiben. Für andere Sprachen benötigen Sie umfangreichere Kodierungen, wobei Unicode-Varianten heutzutage die sicherste Wahl sind.

Kurz gesagt, der Versuch, "die Bytes eines Strings ohne Verwendung von Codierungen zu erhalten", ist genauso unmöglich wie "einen Text schreiben, ohne irgendeine Sprache zu verwenden".

Übrigens empfehle ich Ihnen (und allen anderen) sehr, dieses kleine Stück Weisheit zu lesen: joelonsoftware.com/articles/Unicode.html


You can use the following code for conversion between string and byte array.

string s = "Hello World";

// String to Byte[]

byte[] byte1 = System.Text.Encoding.Default.GetBytes(s);

// OR

byte[] byte2 = System.Text.ASCIIEncoding.Default.GetBytes(s);

// Byte[] to string

string str = System.Text.Encoding.UTF8.GetString(byte1);

Nun, ich habe alle Antworten gelesen, und es ging um die Verwendung von Encoding oder um Serialisierung, die unpaare Surrogate löscht.

Es ist schlecht, wenn die Zeichenfolge beispielsweise von SQL Server stammt, wo sie aus einem Bytearray erstellt wurde, das beispielsweise einen Kennworthash speichert. Wenn wir etwas daraus entfernen, speichert es einen ungültigen Hash. Wenn wir es in XML speichern wollen, wollen wir es intakt lassen (weil der XML-Writer eine Ausnahme für jedes nicht gefundene Ersatz-Ersatzzeichen löscht).

Also benutze ich Base64 Codierung von Byte-Arrays in solchen Fällen, aber hey, im Internet gibt es nur eine Lösung in C #, und es hat einen Fehler und es ist nur eine Möglichkeit, also habe ich den Fehler behoben und zurückgeschrieben Verfahren. Hier sind Sie, zukünftige Googler:

public static byte[] StringToBytes(string str)
{
    byte[] data = new byte[str.Length * 2];
    for (int i = 0; i < str.Length; ++i)
    {
        char ch = str[i];
        data[i * 2] = (byte)(ch & 0xFF);
        data[i * 2 + 1] = (byte)((ch & 0xFF00) >> 8);
    }

    return data;
}

public static string StringFromBytes(byte[] arr)
{
    char[] ch = new char[arr.Length / 2];
    for (int i = 0; i < ch.Length; ++i)
    {
        ch[i] = (char)((int)arr[i * 2] + (((int)arr[i * 2 + 1]) << 8));
    }
    return new String(ch);
}

I'm not sure, but I think the string stores its info as an array of Chars, which is inefficient with bytes. Specifically, the definition of a Char is "Represents a Unicode character".

take this example sample:

String str = "asdf éß";
String str2 = "asdf gh";
EncodingInfo[] info =  Encoding.GetEncodings();
foreach (EncodingInfo enc in info)
{
    System.Console.WriteLine(enc.Name + " - " 
      + enc.GetEncoding().GetByteCount(str)
      + enc.GetEncoding().GetByteCount(str2));
}

Take note that the Unicode answer is 14 bytes in both instances, whereas the UTF-8 answer is only 9 bytes for the first, and only 7 for the second.

So if you just want the bytes used by the string, simply use Encoding.Unicode , but it will be inefficient with storage space.


Benutzen:

    string text = "string";
    byte[] array = System.Text.Encoding.UTF8.GetBytes(text);

The result is:

[0] = 115
[1] = 116
[2] = 114
[3] = 105
[4] = 110
[5] = 103

From byte[] to string :

        return BitConverter.ToString(bytes);

Im Gegensatz zu den Antworten hier müssen Sie sich nicht um die Kodierung kümmern, wenn die Bytes nicht interpretiert werden müssen!

Wie Sie bereits erwähnt haben, ist Ihr Ziel, einfach "zu bekommen, in welche Bytes die Zeichenfolge gespeichert wurde" .
(Und natürlich, um die Zeichenfolge aus den Bytes neu zu konstruieren.)

Für diese Ziele verstehe ich ehrlich gesagt nicht , warum Leute dir immer wieder sagen, dass du die Kodierungen benötigst. Sie müssen sich sicherlich nicht um Kodierungen kümmern.

Tun Sie das stattdessen:

static byte[] GetBytes(string str)
{
    byte[] bytes = new byte[str.Length * sizeof(char)];
    System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
    return bytes;
}

static string GetString(byte[] bytes)
{
    char[] chars = new char[bytes.Length / sizeof(char)];
    System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
    return new string(chars);
}

Solange Ihr Programm (oder andere Programme) nicht versuchen, die Bytes irgendwie zu interpretieren , was Sie offensichtlich nicht erwähnt haben, beabsichtigen Sie zu tun, dann ist an dieser Vorgehensweise nichts falsch! Sich über Codierungen Sorgen zu machen, macht dein Leben ohne wirklichen Grund komplizierter.

Zusätzlicher Vorteil für diesen Ansatz:

Es spielt keine Rolle, ob die Zeichenfolge ungültige Zeichen enthält, da Sie die Daten trotzdem erhalten und die ursprüngliche Zeichenfolge trotzdem rekonstruieren können!

Es wird genauso codiert und decodiert, weil Sie nur die Bytes betrachten .

Wenn Sie jedoch eine bestimmte Kodierung verwendet hätten, hätten Sie Probleme mit der Kodierung / Dekodierung ungültiger Zeichen gehabt.


Nur um zu demonstrieren, dass Mehrdrads Klangantwort funktioniert, kann seine Herangehensweise sogar die [BinaryFormatter beibehalten (von denen viele gegen meine Antwort System.Text.Encoding.UTF8.GetBytes , von denen aber alle gleichermaßen schuldig sind, zB System.Text.Encoding.UTF8.GetBytes , System.Text.Encoding.Unicode.GetBytes ; diese Codierungsmethoden können die hohen d800 nicht d800 und ersetzen nur hohe fffd durch den Wert fffd ):

using System;

class Program
{     
    static void Main(string[] args)
    {
        string t = "爱虫";            
        string s = "Test\ud800Test"; 

        byte[] dumpToBytes = GetBytes(s);
        string getItBack = GetString(dumpToBytes);

        foreach (char item in getItBack)
        {
            Console.WriteLine("{0} {1}", item, ((ushort)item).ToString("x"));
        }    
    }

    static byte[] GetBytes(string str)
    {
        byte[] bytes = new byte[str.Length * sizeof(char)];
        System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
        return bytes;
    }

    static string GetString(byte[] bytes)
    {
        char[] chars = new char[bytes.Length / sizeof(char)];
        System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
        return new string(chars);
    }        
}

Ausgabe:

T 54
e 65
s 73
t 74
? d800
T 54
e 65
s 73
t 74

Versuchen Sie das mit System.Text.Encoding.UTF8.GetBytes oder System.Text.Encoding.Unicode.GetBytes , sie ersetzen nur Ersatzzeichen mit Wert fffd

Jedes Mal, wenn eine Bewegung in dieser Frage auftritt, denke ich immer noch an einen Serialisierer (sei es von Microsoft oder von einer Drittanbieterkomponente), der Zeichenfolgen beibehalten kann, selbst wenn er nicht ersetzte Ersatzzeichen enthält. Ich google dies hin und wieder: Serialisierung ungepaartes Ersatzzeichen .NET . Das lässt mich nicht schlafen, aber es ist irgendwie nervig, wenn ab und zu jemand meine Antwort kommentiert, dass sie fehlerhaft ist, aber ihre Antworten sind ebenso fehlerhaft, wenn es um ungepackte Ersatzcharaktere geht.

Darn, Microsoft hätte einfach System.Buffer.BlockCopy in seinem BinaryFormatterツ verwenden sollen

谢谢!


bytes[] buffer = UnicodeEncoding.UTF8.GetBytes(string something); //for converting to UTF then get its bytes

bytes[] buffer = ASCIIEncoding.ASCII.GetBytes(string something); //for converting to ascii then get its bytes

Der erste Teil Ihrer Frage (wie Sie die Bytes erhalten) wurde bereits von anderen beantwortet: System.Text.Encoding Namespace System.Text.Encoding .

Ich werde auf Ihre Follow-up-Frage eingehen: Warum müssen Sie eine Codierung auswählen? Warum kannst du das nicht von der String-Klasse selbst bekommen?

Die Antwort besteht aus zwei Teilen.

Zuallererst sind die Bytes, die intern von der String-Klasse verwendet werden, nicht wichtig , und wann immer Sie davon ausgehen, dass Sie dies tun, führen Sie wahrscheinlich einen Bug ein.

Wenn sich Ihr Programm vollständig innerhalb der .Net-Welt befindet, müssen Sie sich keine Gedanken darüber machen, Byte-Arrays für Strings überhaupt zu erhalten, selbst wenn Sie Daten über ein Netzwerk senden. Verwenden Sie stattdessen die .Net-Serialisierung, um sich um die Übertragung der Daten zu kümmern. Sie müssen sich nicht mehr um die tatsächlichen Bytes kümmern: Der Serialisierungsformatierer erledigt das für Sie.

Auf der anderen Seite, was passiert, wenn Sie diese Bytes irgendwo senden, die Sie nicht garantieren können, Daten aus einem serialisierten .Net-Stream einzuziehen? In diesem Fall müssen Sie sich auf jeden Fall um die Kodierung kümmern, denn offensichtlich kümmert sich dieses externe System darum. Auch hier sind die internen Bytes, die von der Zeichenfolge verwendet werden, egal: Sie müssen eine Codierung auswählen, damit Sie diese Codierung auf der Empfängerseite explizit angeben können, auch wenn es sich um dieselbe Codierung handelt, die intern von .Net verwendet wird.

Ich verstehe, dass Sie in diesem Fall lieber die tatsächlichen Bytes verwenden möchten, die von der String-Variablen im Speicher gespeichert werden, wo dies möglich ist, mit der Idee, dass es beim Erstellen Ihres Byte-Streams etwas Arbeit sparen könnte. Wie auch immer, ich sage es Ihnen, es ist einfach nicht wichtig im Vergleich zu sicherzustellen, dass Ihre Ausgabe am anderen Ende verstanden wird, und um sicherzustellen, dass Sie explizit mit Ihrer Kodierung kommunizieren müssen. Wenn Sie Ihre internen Bytes wirklich abgleichen möchten, können Sie außerdem einfach die Unicode Codierung auswählen und diese Leistungseinsparungen erzielen.

Das bringt mich zum zweiten Teil ... die Unicode Codierung auszuwählen, sagt .Net, die zugrunde liegenden Bytes zu verwenden. Sie müssen diese Kodierung wählen, denn wenn ein neugefädeltes Unicode-Plus herauskommt, muss die .Net-Laufzeit frei sein, um dieses neuere, bessere Kodierungsmodell zu verwenden, ohne Ihr Programm zu unterbrechen. Aber für den Moment (und die absehbare Zukunft), nur die Wahl der Unicode-Codierung gibt Ihnen, was Sie wollen.

Es ist auch wichtig zu verstehen, dass die Zeichenfolge in die Leitung neu geschrieben werden muss, und dies beinhaltet zumindest eine gewisse Übersetzung des Bitmusters, selbst wenn Sie eine passende Codierung verwenden . Der Computer muss Dinge wie Big vs Little Endian, Netzwerk-Byte-Reihenfolge, Paketierung, Sitzungsinformationen usw. berücksichtigen.


The closest approach to the OP's question is Tom Blodget's, which actually goes into the object and extracts the bytes. I say closest because it depends on implementation of the String Object.

"Can't I simply get what bytes the string has been stored in?"

Sure, but that's where the fundamental error in the question arises. The String is an object which could have an interesting data structure. We already know it does, because it allows unpaired surrogates to be stored. It might store the length. It might keep a pointer to each of the 'paired' surrogates allowing quick counting. Etc. All of these extra bytes are not part of the character data.

What you want is each character's bytes in an array. And that is where 'encoding' comes in. By default you will get UTF-16LE. If you don't care about the bytes themselves except for the round trip then you can choose any encoding including the 'default', and convert it back later (assuming the same parameters such as what the default encoding was, code points, bug fixes, things allowed such as unpaired surrogates, etc.

But why leave the 'encoding' up to magic? Why not specify the encoding so that you know what bytes you are gonna get?

"Why is there a dependency on character encodings?"

Encoding (in this context) simply means the bytes that represent your string. Not the bytes of the string object. You wanted the bytes the string has been stored in -- this is where the question was asked naively. You wanted the bytes of string in a contiguous array that represent the string, and not all of the other binary data that a string object may contain.

Which means how a string is stored is irrelevant. You want a string "Encoded" into bytes in a byte array.

I like Tom Bloget's answer because he took you towards the 'bytes of the string object' direction. It's implementation dependent though, and because he's peeking at internals it might be difficult to reconstitute a copy of the string.

Mehrdad's response is wrong because it is misleading at the conceptual level. You still have a list of bytes, encoded. His particular solution allows for unpaired surrogates to be preserved -- this is implementation dependent. His particular solution would not produce the string's bytes accurately if GetBytes returned the string in UTF-8 by default.

I've changed my mind about this (Mehrdad's solution) -- this isn't getting the bytes of the string; rather it is getting the bytes of the character array that was created from the string. Regardless of encoding, the char datatype in c# is a fixed size. This allows a consistent length byte array to be produced, and it allows the character array to be reproduced based on the size of the byte array. So if the encoding were UTF-8, but each char was 6 bytes to accommodate the largest utf8 value, it would still work. So indeed -- encoding of the character does not matter.

But a conversion was used -- each character was placed into a fixed size box (c#'s character type). However what that representation is does not matter, which is technically the answer to the OP. So -- if you are going to convert anyway... Why not 'encode'?


Simply use this:

byte[] myByte= System.Text.ASCIIEncoding.Default.GetBytes(myString);

Two ways:

public static byte[] StrToByteArray(this string s)
{
    List<byte> value = new List<byte>();
    foreach (char c in s.ToCharArray())
        value.Add(c.ToByte());
    return value.ToArray();
}

And,

public static byte[] StrToByteArray(this string s)
{
    s = s.Replace(" ", string.Empty);
    byte[] buffer = new byte[s.Length / 2];
    for (int i = 0; i < s.Length; i += 2)
        buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
    return buffer;
}

I tend to use the bottom one more often than the top, haven't benchmarked them for speed.


Die angenommene Antwort ist sehr, sehr kompliziert. Verwenden Sie dazu die enthaltenen .NET-Klassen:

const string data = "A string with international characters: Norwegian: ÆØÅæøå, Chinese: 喂 谢谢";
var bytes = System.Text.Encoding.UTF8.GetBytes(data);
var decoded = System.Text.Encoding.UTF8.GetString(bytes);

Erfinde das Rad nicht neu, wenn du nicht musst ...


Dies ist eine beliebte Frage. Es ist wichtig zu verstehen, was der Fragesteller fragt und dass es sich von dem wahrscheinlichsten Bedürfnis unterscheidet. Um den Missbrauch des Codes, wo es nicht benötigt wird, zu entmutigen, habe ich das erstere beantwortet.

Gemeinsame Notwendigkeit

Jede Zeichenfolge hat einen Zeichensatz und eine Codierung. Wenn Sie ein System.String Objekt in ein Array von System.Byte Sie noch einen Zeichensatz und eine Codierung. Für die meisten Anwendungen wissen Sie, welchen Zeichensatz und welche Kodierung Sie benötigen, und .NET vereinfacht das Kopieren mit der Konvertierung. Wählen Sie einfach die entsprechende Encoding .

// using System.Text;
Encoding.UTF8.GetBytes(".NET String to byte array")

Die Konvertierung muss möglicherweise Fälle behandeln, in denen der Zielzeichensatz oder die Zeichencodierung kein Zeichen unterstützt, das sich in der Quelle befindet. Sie haben einige Auswahlmöglichkeiten: Ausnahme, Ersetzung oder Überspringen. Die Standardrichtlinie besteht darin, ein "?" Zu ersetzen.

// using System.Text;
var text = Encoding.ASCII.GetString(Encoding.ASCII.GetBytes("You win €100")); 
                                                      // -> "You win ?100"

Natürlich sind Conversions nicht unbedingt verlustfrei!

Hinweis: Für System.String der System.String Unicode.

Die einzige verwirrende Sache ist, dass .NET den Namen eines Zeichensatzes für den Namen einer bestimmten Kodierung dieses Zeichensatzes verwendet. Encoding.Unicode sollte Encoding.UTF16 heißen.

Das ist es für die meisten Verwendungen. Wenn Sie das brauchen, hören Sie hier auf. Sehen Sie sich joelonsoftware.com/articles/Unicode.html wenn Sie nicht verstehen, was eine Kodierung ist.

Spezifische Notwendigkeit

Jetzt fragt der Autor der Frage: "Jede Zeichenfolge wird als Array von Bytes gespeichert, richtig? Warum kann ich diese Bytes nicht einfach haben?"

Er möchte keine Konvertierung.

Aus der C # -Spezifikation :

Zeichen- und Zeichenfolgeverarbeitung in C # verwendet Unicode-Codierung. Der Zeichenartstyp steht für eine UTF-16-Codeeinheit und der Zeichenfolgentyp für eine Sequenz von UTF-16-Codeeinheiten.

Wir wissen also, dass wir das gewünschte Ergebnis erhalten, wenn wir nach der Nullumwandlung (dh von UTF-16 nach UTF-16) fragen:

Encoding.Unicode.GetBytes(".NET String to byte array")

Aber um die Erwähnung von Codierungen zu vermeiden, müssen wir es anders machen. Wenn ein Zwischendatentyp akzeptabel ist, gibt es dafür eine konzeptionelle Verknüpfung:

".NET String to byte array".ToCharArray()

Das bringt uns nicht den gewünschten Datentyp, aber Mehrdads Antwort zeigt, wie man dieses Char-Array mit BlockCopy in ein Byte-Array BlockCopy . Dies kopiert jedoch die Zeichenfolge zweimal! Und es verwendet auch explizit codierungsspezifischen Code: den Datentyp System.Char .

Die einzige Möglichkeit, zu den tatsächlichen Bytes zu gelangen, in denen die Zeichenfolge gespeichert ist, ist die Verwendung eines Zeigers. Die fixed Anweisung ermöglicht die Übernahme der Adresse von Werten. Aus der C # -Spezifikation:

[Für] einen Ausdruck vom Typ string, ... berechnet der Initialisierer die Adresse des ersten Zeichens in der Zeichenkette.

Um dies zu tun, schreibt der Compiler mit RuntimeHelpers.OffsetToStringData Code, der die anderen Teile des String-Objekts RuntimeHelpers.OffsetToStringData . Um also die rohen Bytes zu erhalten, erstellen Sie einfach einen Zeiger auf die Zeichenfolge und kopieren Sie die Anzahl der benötigten Bytes.

// using System.Runtime.InteropServices
unsafe byte[] GetRawBytes(String s)
{
    if (s == null) return null;
    var codeunitCount = s.Length;
    /* We know that String is a sequence of UTF-16 codeunits 
       and such codeunits are 2 bytes */
    var byteCount = codeunitCount * 2; 
    var bytes = new byte[byteCount];
    fixed(void* pRaw = s)
    {
        Marshal.Copy((IntPtr)pRaw, bytes, 0, byteCount);
    }
    return bytes;
}

Wie @CodesInChaos gezeigt hat, hängt das Ergebnis von der Endianess der Maschine ab. Aber der Fragesteller kümmert sich nicht darum.


Versuchen Sie dies, viel weniger Code:

System.Text.Encoding.UTF8.GetBytes("TEST String");

If you really want a copy of the underlying bytes of a string, you can use a function like the one that follows. However, you shouldn't please read on to find out why.

[DllImport(
        "msvcrt.dll",
        EntryPoint = "memcpy",
        CallingConvention = CallingConvention.Cdecl,
        SetLastError = false)]
private static extern unsafe void* UnsafeMemoryCopy(
    void* destination,
    void* source,
    uint count);

public static byte[] GetUnderlyingBytes(string source)
{
    var length = source.Length * sizeof(char);
    var result = new byte[length];
    unsafe
    {
        fixed (char* firstSourceChar = source)
        fixed (byte* firstDestination = result)
        {
            var firstSource = (byte*)firstSourceChar;
            UnsafeMemoryCopy(
                firstDestination,
                firstSource,
                (uint)length);
        }
    }

    return result;
}

This function will get you a copy of the bytes underlying your string, pretty quickly. You'll get those bytes in whatever way they are encoding on your system. This encoding is almost certainly UTF-16LE but that is an implementation detail you shouldn't have to care about.

It would be safer, simpler and more reliable to just call,

System.Text.Encoding.Unicode.GetBytes()

In all likelihood this will give the same result, is easier to type, and the bytes will always round-trip with a call to

System.Text.Encoding.Unicode.GetString()

Eine Unicode-Zeichenfolge als eine Bytefolge darzustellen, wird als Codierung bezeichnet . Benutze u'...'.encode(encoding) .

Beispiel:

    >>> u'æøå'.encode('utf8')
    '\xc3\x83\xc2\xa6\xc3\x83\xc2\xb8\xc3\x83\xc2\xa5'
    >>> u'æøå'.encode('latin1')
    '\xc3\xa6\xc3\xb8\xc3\xa5'
    >>> u'æøå'.encode('ascii')
    UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: 
    ordinal not in range(128)

Normalerweise codieren Sie einen Unicode-String, wenn Sie ihn für IO verwenden, z. B. über das Netzwerk übertragen oder in einer Datei speichern.

Die Umwandlung einer Bytefolge in eine Unicode-Zeichenfolge wird als Decodierung bezeichnet . Benutze unicode('...', encoding) oder '...' Dekodierung (Kodierung).

Beispiel:

   >>> u'æøå'
   u'\xc3\xa6\xc3\xb8\xc3\xa5' # the interpreter prints the unicode object like so
   >>> unicode('\xc3\xa6\xc3\xb8\xc3\xa5', 'latin1')
   u'\xc3\xa6\xc3\xb8\xc3\xa5'
   >>> '\xc3\xa6\xc3\xb8\xc3\xa5'.decode('latin1')
   u'\xc3\xa6\xc3\xb8\xc3\xa5'

In der Regel dekodieren Sie eine Zeichenfolge, wenn Sie Zeichenfolgedaten aus dem Netzwerk oder aus einer Datenträgerdatei erhalten.

Ich glaube, es gibt einige Änderungen in der Unicode-Behandlung in Python 3, also ist das obige wahrscheinlich nicht korrekt für Python 3.

Einige gute Links:





c# .net string