Questa è una domanda popolare È importante capire cosa si pone l'autore della domanda e che è diverso da quello che è probabilmente il bisogno più comune. Per scoraggiare l'uso improprio del codice laddove non è necessario, ho risposto prima in un secondo momento.
Esigenza comune
Ogni stringa ha un set di caratteri e una codifica. Quando converti un System.String
oggetto in un array, System.Byte
hai ancora un set di caratteri e una codifica. Per la maggior parte degli utilizzi, sapresti quale set di caratteri e codifica hai bisogno e .NET semplifica la "copia con conversione". Basta scegliere la Encoding
classe appropriata .
// using System.Text;
Encoding.UTF8.GetBytes(".NET String to byte array")
La conversione potrebbe dover gestire i casi in cui il set di caratteri di destinazione o la codifica non supportano un carattere che si trova nella fonte. Hai alcune scelte: eccezione, sostituzione o salto. La politica di default è sostituire un '?'.
// using System.Text;
var text = Encoding.ASCII.GetString(Encoding.ASCII.GetBytes("You win €100"));
// -> "You win ?100"
Chiaramente, le conversioni non sono necessariamente senza perdita!
Nota: per System.String
il set di caratteri di origine è Unicode.
L'unica cosa confusa è che .NET utilizza il nome di un set di caratteri per il nome di una particolare codifica di quel set di caratteri. Encoding.Unicode
dovrebbe essere chiamato Encoding.UTF16
.
Questo è tutto per la maggior parte degli usi. Se è quello che ti serve, smetti di leggere qui. Vedi il divertente articolo di Joel Spolsky se non capisci cos'è una codifica.
Bisogno specifico
Ora, l'autore della domanda chiede: "Ogni stringa è memorizzata come una matrice di byte, giusto? Perché non posso semplicemente avere quei byte?"
Non vuole alcuna conversione.
Dalle specifiche C # :
L'elaborazione di caratteri e stringhe in C # utilizza la codifica Unicode. Il tipo di carattere rappresenta un'unità di codice UTF-16 e il tipo di stringa rappresenta una sequenza di unità di codice UTF-16.
Quindi, sappiamo che se chiediamo la conversione nulla (cioè da UTF-16 a UTF-16), otterremo il risultato desiderato:
Encoding.Unicode.GetBytes(".NET String to byte array")
Ma per evitare la menzione delle codifiche, dobbiamo farlo in un altro modo. Se un tipo di dati intermedio è accettabile, esiste un collegamento concettuale per questo:
".NET String to byte array".ToCharArray()
Questo non ci fornisce il tipo di dati desiderato, ma la risposta di Mehrdad mostra come convertire questo array Char in un array Byte usando BlockCopy . Tuttavia, questo copia la stringa due volte! E usa troppo esplicitamente il codice specifico della codifica: il tipo di dati System.Char
.
L'unico modo per raggiungere i byte effettivi in cui è memorizzata la stringa è utilizzare un puntatore. L' fixed
istruzione consente di prendere l'indirizzo dei valori. Dalle specifiche C #:
[Per] un'espressione di tipo stringa, ... l'inizializzatore calcola l'indirizzo del primo carattere nella stringa.
Per fare ciò, il compilatore scrive il salto del codice sulle altre parti dell'oggetto stringa con RuntimeHelpers.OffsetToStringData
. Quindi, per ottenere i byte non elaborati, basta creare un puntatore alla stringa e copiare il numero di byte necessari.
// 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;
}
Come sottolineato da @CodesInChaos, il risultato dipende dall'endianità della macchina. Ma l'autore della domanda non si preoccupa di questo.