Come ottengo una rappresentazione di byte coerente di stringhe in C # senza specificare manualmente una codifica?

Come posso convertire una string in un byte[] in .NET (C #) senza specificare manualmente una codifica specifica?

Ho intenzione di crittografare la stringa. Posso crittografarlo senza convertirli, ma mi piacerebbe ancora sapere perché la codifica viene qui a giocare.

Inoltre, perché la codifica dovrebbe essere presa in considerazione? Non posso semplicemente ottenere in quale byte è stata memorizzata la stringa? Perché c’è una dipendenza dalle codifiche dei caratteri?

Contrariamente alle risposte qui, NON è necessario preoccuparsi della codifica se i byte non devono essere interpretati!

Come hai detto, il tuo objective è, semplicemente, “ottenere in quale byte è stata memorizzata la stringa” .
(E, naturalmente, per essere in grado di ribuild la stringa dai byte.)

Per quegli obiettivi, onestamente non capisco perché la gente continui a dirti che hai bisogno delle codifiche. Sicuramente non devi preoccuparti delle codifiche per questo.

Basta fare questo invece:

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

Finché il tuo programma (o altri programmi) non tenta di interpretare i byte in qualche modo, cosa che ovviamente non hai menzionato tu intendi fare, allora non c’è niente di sbagliato in questo approccio! Preoccuparsi delle codifiche ti rende la vita più complicata senza una vera ragione.

Ulteriori vantaggi per questo approccio:

Non importa se la stringa contiene caratteri non validi, perché puoi comunque ottenere i dati e ribuild comunque la stringa originale!

Sarà codificato e decodificato allo stesso modo, perché stai solo guardando i byte .

Se hai usato una codifica specifica, però, ti avrebbe dato problemi con la codifica / decodifica di caratteri non validi.

Dipende dalla codifica della stringa ( ASCII , UTF-8 , …).

Per esempio:

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

Un piccolo esempio per cui la codifica è importante:

 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 semplicemente non è equipaggiato per trattare personaggi speciali.

Internamente, il framework .NET utilizza UTF-16 per rappresentare le stringhe, quindi se si desidera semplicemente ottenere i byte esatti utilizzati da .NET, utilizzare System.Text.Encoding.Unicode.GetBytes (...) .

Vedere Codifica caratteri in .NET Framework (MSDN) per ulteriori informazioni.

La risposta accettata è molto, molto complicata. Utilizzare le classi .NET incluse per questo:

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

Non reinventare la ruota se non devi …

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

È necessario prendere in considerazione la codifica, poiché 1 carattere può essere rappresentato da 1 o più byte (fino a circa 6) e le codifiche differenti gestiranno questi byte in modo diverso.

Joel ha un post su questo:

Il minimo assoluto Ogni sviluppatore di software deve assolutamente conoscere l’Unicode e i set di caratteri (nessuna scusa!)

Questa è una domanda popolare. È importante capire che cosa chiede la domanda all’autore e che è diversa da quella che è probabilmente la necessità più comune. Per scoraggiare l’uso improprio del codice laddove non è necessario, ho risposto per primo.

Bisogno comune

Ogni stringa ha un set di caratteri e codifica. Quando converti un object System.String in un array di System.Byte hai ancora un set di caratteri e una codifica. Per la maggior parte degli usi, sapresti quale set di caratteri e codifica hai bisogno e .NET semplifica la “copia con conversione”. Basta scegliere la class di Encoding appropriata.

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

La conversione potrebbe dover gestire casi in cui il set di caratteri di destinazione o la codifica non supportano un carattere presente nella fonte. Avete alcune scelte: eccezione, sostituzione o salto. La politica di default è di 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 perdite!

Nota: per System.String il set di caratteri di origine è Unicode.

L’unica cosa confusa è che .NET usa 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 di cui hai bisogno, smetti di leggere qui. Guarda il divertente articolo di Joel Spolsky se non capisci cos’è una codifica.

Bisogno specifico

Ora, la domanda dell’autore chiede: “Ogni stringa è memorizzata come una matrice di byte, giusto? Perché non posso semplicemente avere quei byte?”

Lui non vuole alcuna conversione.

Dalla specifica 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 null (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 intermedi è accettabile, esiste una scorciatoia concettuale per questo:

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

Questo non ci porta 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! Inoltre, utilizza esplicitamente un codice specifico per la codifica: il tipo di dati System.Char .

L’unico modo per ottenere i byte effettivi in ​​cui è memorizzata la stringa è utilizzare un puntatore. L’istruzione fixed consente di prendere l’indirizzo dei valori. Dalla specifica C #:

[For] un’espressione di tipo stringa, … l’inizializzatore calcola l’indirizzo del primo carattere nella stringa.

Per fare ciò, il compilatore scrive il codice salta sulle altre parti dell’object 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 dalla endianità della macchina. Ma l’autore della domanda non si occupa di questo.

Solo per dimostrare che la risposta sonora di Mehrdrad funziona, il suo approccio può anche persistere nei caratteri surrogati non appaiati (di cui molti hanno messo a confronto la mia risposta, ma di cui tutti sono ugualmente colpevoli, ad esempio System.Text.Encoding.UTF8.GetBytes , System.Text.Encoding.Unicode.GetBytes , quei metodi di codifica non possono mantenere i caratteri surrogati alti d800 per esempio, e quelli semplicemente sostituiscono solo caratteri surrogati con valore 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); } } 

Produzione:

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

Provalo con System.Text.Encoding.UTF8.GetBytes o System.Text.Encoding.Unicode.GetBytes , sostituiranno semplicemente alti caratteri surrogati con valore fffd

Ogni volta che c’è un movimento in questa domanda, sto ancora pensando a un serializzatore (che si tratti di Microsoft o di un componente di terze parti) che possa persistere nelle stringhe anche se contiene caratteri surrogati non appaiati; Io google di tanto in tanto: serializzazione carattere alternativo surrogato .NET . Questo non mi fa perdere il sonno, ma è un po ‘fastidioso quando ogni tanto qualcuno commenta la mia risposta che è difettosa, eppure le loro risposte sono ugualmente imperfette quando si tratta di personaggi surrogati spaiati.

Dannazione, Microsoft avrebbe dovuto usare System.Buffer.BlockCopy nel suo BinaryFormatter

谢谢!

Prova questo, molto meno codice:

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

La prima parte della tua domanda (come ottenere i byte) ha già ricevuto risposta da altri: guarda nello spazio dei nomi System.Text.Encoding .

Tratterò la tua domanda di follow-up: perché hai bisogno di scegliere una codifica? Perché non puoi ottenerlo dalla stessa class di stringhe?

La risposta è in due parti.

Prima di tutto, i byte usati internamente dalla class string non hanno importanza , e ogni volta che si presume lo facciano probabilmente introducendo un bug.

Se il tuo programma è interamente all’interno del mondo .Net, allora non devi preoccuparti di ottenere array di byte per le stringhe, anche se stai inviando dati attraverso una rete. Invece, utilizzare la serializzazione .Net per preoccuparsi della trasmissione dei dati. Non ti preoccupare più dei byte effettivi: il formattatore di serializzazione lo fa per te.

D’altra parte, cosa succede se si inviano questi byte da qualche parte che non si può garantire l’estrazione dei dati da un stream serializzato .Net? In questo caso hai sicuramente bisogno di preoccuparti della codifica, perché ovviamente questo sistema esterno si preoccupa. Quindi, di nuovo, i byte interni utilizzati dalla stringa non contano: è necessario scegliere una codifica in modo da poter essere espliciti su questa codifica sul lato ricevente, anche se è la stessa codifica utilizzata internamente da .Net.

Capisco che in questo caso potresti preferire utilizzare i byte effettivi memorizzati dalla variabile stringa nella memoria, ove ansible, con l’idea che potrebbe salvare del lavoro creando il stream di byte. Tuttavia, l’ho messo per te non è importante rispetto al fare in modo che il tuo output sia compreso dall’altra parte, e per garantire che tu debba essere esplicito con la tua codifica. Inoltre, se vuoi davvero abbinare i tuoi byte interni, puoi già scegliere la codifica Unicode e ottenere così un risparmio di prestazioni.

Il che mi porta alla seconda parte … la scelta della codifica Unicode sta dicendo a .Net di usare i byte sottostanti. È necessario scegliere questa codifica, perché quando esce Unicode-Plus un po ‘nuovo, il runtime .Net deve essere libero di utilizzare questo modello di codifica più recente e migliore senza interrompere il programma. Ma, per il momento (e il futuro prevedibile), scegliere la codifica Unicode ti dà quello che vuoi.

È anche importante capire che la stringa deve essere riscritta sul filo, e ciò implica almeno una certa traduzione del pattern di bit anche quando si utilizza una codifica corrispondente . Il computer deve tenere conto di cose come Big vs Little Endian, ordine dei byte di rete, pacchetti, informazioni sulla sessione, ecc.

Bene, ho letto tutte le risposte e stavano usando la codifica o uno sulla serializzazione che fa cadere surrogati inermi.

È un problema quando la stringa, ad esempio, proviene da SQL Server in cui è stata creata da un array di byte che memorizza, ad esempio, un hash della password. Se ne eliminiamo qualcosa, memorizzerà un hash non valido e, se vogliamo archiviarlo in XML, vogliamo lasciarlo intatto (perché il writer XML rilascia un’eccezione su qualsiasi surrogato non appaiato trovato).

Quindi io uso la codifica Base64 di matrici di byte in questi casi, ma hey, su Internet c’è una sola soluzione a questo in C #, e ha bug in esso ed è solo un modo, quindi ho risolto il bug e scritto di nuovo procedura. Eccoti, futuri 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); } 

Spiega anche perché la codifica deve essere presa in considerazione. Non posso semplicemente ottenere in quale byte è stata memorizzata la stringa? Perché questa dipendenza dalla codifica? !!!

Perché non esistono cose come “i byte della stringa”.

Una stringa (o più genericamente, un testo) è composta da caratteri: lettere, cifre e altri simboli. È tutto. I computer, tuttavia, non sanno nulla dei personaggi; possono gestire solo byte. Pertanto, se si desidera archiviare o trasmettere il testo utilizzando un computer, è necessario trasformare i caratteri in byte. Come si fa a farlo? Ecco dove arrivano le codifiche sulla scena.

Una codifica non è altro che una convenzione per tradurre i caratteri logici in byte fisici. La codifica più semplice e più conosciuta è ASCII, ed è tutto ciò che serve se scrivi in ​​inglese. Per altre lingue avrete bisogno di codifiche più complete, essendo uno dei sapori Unicode la scelta più sicura al giorno d’oggi.

Quindi, in breve, cercare di “ottenere i byte di una stringa senza utilizzare le codifiche” è imansible quanto “scrivere un testo senza usare alcun linguaggio”.

A proposito, ti consiglio vivamente (e chiunque altro) di leggere questo piccolo pezzo di saggezza: Il minimo assoluto Ogni sviluppatore di software deve assolutamente conoscere positivamente Unicode e set di caratteri (nessuna scusa!)

C # per convertire una string in un array di byte :

 public static byte[] StrToByteArray(string str) { System.Text.UTF8Encoding encoding=new System.Text.UTF8Encoding(); return encoding.GetBytes(str); } 
 byte[] strToByteArray(string str) { System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); return enc.GetBytes(str); } 

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

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.

The key issue is that a glyph in a string takes 32 bits (16 bits for a character code) but a byte only has 8 bits to spare. A one-to-one mapping doesn’t exist unless you restrict yourself to strings that only contain ASCII characters. System.Text.Encoding has lots of ways to map a string to byte[], you need to pick one that avoids loss of information and that is easy to use by your client when she needs to map the byte[] back to a string.

Utf8 is a popular encoding, it is compact and not lossy.

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) 

Uso:

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

Il risultato è:

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

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

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’?

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

Two ways:

 public static byte[] StrToByteArray(this string s) { List value = new List(); 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.

 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 

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().ToArray(); 

Simply use this:

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

With the advent of Span 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().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 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.

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() 

The string can be converted to byte array in few different ways, due to the following fact: .NET supports Unicode, and Unicode standardizes several difference encodings called UTFs. They have different lengths of byte representation but are equivalent in that sense that when a string is encoded, it can be coded back to the string, but if the string is encoded with one UTF and decoded in the assumption of different UTF if can be screwed up.

Also, .NET supports non-Unicode encodings, but they are not valid in general case (will be valid only if a limited sub-set of Unicode code point is used in an actual string, such as ASCII). Internally, .NET supports UTF-16, but for stream representation, UTF-8 is usually used. It is also a standard-de-facto for Internet.

Not surprisingly, serialization of string into an array of byte and deserialization is supported by the class System.Text.Encoding , which is an abstract class; its derived classs support concrete encodings: ASCIIEncoding and four UTFs ( System.Text.UnicodeEncoding supports UTF-16)

Ref this link.

For serialization to an array of bytes using System.Text.Encoding.GetBytes . For the inverse operation use System.Text.Encoding.GetChars . This function returns an array of characters, so to get a string, use a string constructor System.String(char[]) .
Ref this page.

Esempio:

 string myString = //... some string System.Text.Encoding encoding = System.Text.Encoding.UTF8; //or some other, but prefer some UTF is Unicode is used byte[] bytes = encoding.GetBytes(myString); //next lines are written in response to a follow-up questions: myString = new string(encoding.GetChars(bytes)); byte[] bytes = encoding.GetBytes(myString); myString = new string(encoding.GetChars(bytes)); byte[] bytes = encoding.GetBytes(myString); //how many times shall I repeat it to show there is a round-trip? :-) 

From byte[] to string :

  return BitConverter.ToString(bytes); 

It depends on what you want the bytes FOR

This is because, as Tyler so aptly said , “Strings aren’t pure data. They also have information .” In this case, the information is an encoding that was assumed when the string was created.

Assuming that you have binary data (rather than text) stored in a string

This is based off of OP’s comment on his own question, and is the correct question if I understand OP’s hints at the use-case.

Storing binary data in strings is probably the wrong approach because of the assumed encoding mentioned above! Whatever program or library stored that binary data in a string (instead of a byte[] array which would have been more appropriate) has already lost the battle before it has begun. If they are sending the bytes to you in a REST request/response or anything that must transmit strings, Base64 would be the right approach.

If you have a text string with an unknown encoding

Everybody else answered this incorrect question incorrectly.

If the string looks good as-is, just pick an encoding (preferably one starting with UTF), use the corresponding System.Text.Encoding.???.GetBytes() function, and tell whoever you give the bytes to which encoding you picked.