Dies ist eine beliebte Frage. Es ist wichtig zu verstehen, was der Autor der Frage stellt und dass es sich von dem unterscheidet, was wahrscheinlich am häufigsten benötigt wird. Um den Missbrauch des Codes dort zu verhindern, wo er nicht benötigt wird, habe ich den späteren zuerst beantwortet.
Gemeinsames Bedürfnis
Jede Zeichenfolge hat einen Zeichensatz und eine Codierung. Wenn Sie ein System.String
Objekt in ein Array von konvertieren, System.Byte
haben Sie immer noch einen Zeichensatz und eine Codierung. Für die meisten Anwendungen wissen Sie, welchen Zeichensatz und welche Codierung Sie benötigen, und .NET macht es einfach, "mit Konvertierung zu kopieren". Wählen Sie einfach die entsprechende Encoding
Klasse.
// 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 Codierung kein Zeichen in der Quelle unterstützt. Sie haben einige Mö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"
Conversions sind natürlich nicht unbedingt verlustfrei!
Hinweis: System.String
Der Quellzeichensatz ist Unicode.
Das einzig Verwirrende ist, dass .NET den Namen eines Zeichensatzes für den Namen einer bestimmten Codierung dieses Zeichensatzes verwendet. Encoding.Unicode
sollte aufgerufen werden Encoding.UTF16
.
Das war's für die meisten Verwendungen. Wenn Sie das brauchen, hören Sie hier auf zu lesen. Lesen Sie den lustigen Artikel von Joel Spolsky, wenn Sie nicht verstehen, was eine Codierung ist.
Spezifischer Bedarf
Nun fragt der Autor der Frage: "Jede Zeichenfolge wird als Array von Bytes gespeichert, richtig? Warum kann ich diese Bytes nicht einfach haben?"
Er will keine Bekehrung.
Aus der C # -Spezifikation :
Die Zeichen- und Zeichenfolgenverarbeitung in C # verwendet die Unicode-Codierung. Der Zeichentyp repräsentiert eine UTF-16-Codeeinheit, und der Zeichenfolgentyp repräsentiert eine Folge von UTF-16-Codeeinheiten.
Wir wissen also, dass wir das gewünschte Ergebnis erhalten, wenn wir nach der Nullkonvertierung fragen (dh von UTF-16 nach UTF-16):
Encoding.Unicode.GetBytes(".NET String to byte array")
Aber um die Erwähnung von Kodierungen 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 dieses Char-Array mit BlockCopy in ein Byte-Array konvertiert wird . Dies kopiert die Zeichenfolge jedoch zweimal! Außerdem wird explizit codierungsspezifischer Code verwendet: der Datentyp System.Char
.
Der einzige Weg, um zu den tatsächlichen Bytes zu gelangen, in denen der String gespeichert ist, ist die Verwendung eines Zeigers. Die fixed
Anweisung ermöglicht die Angabe der Adresse von Werten. Aus der C # -Spezifikation:
[Für] einen Ausdruck vom Typ Zeichenfolge, ... berechnet der Initialisierer die Adresse des ersten Zeichens in der Zeichenfolge.
Zu diesem Zweck schreibt der Compiler Code, der die anderen Teile des Zeichenfolgenobjekts mit überspringt RuntimeHelpers.OffsetToStringData
. Um die Rohbytes 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 hervorhob, hängt das Ergebnis von der Endianness der Maschine ab. Aber der Fragesteller befasst sich nicht damit.