Como faço para obter uma representação de byte consistente de seqüências de caracteres em c # sem especificar manualmente uma codificação?

Como converter uma string para um byte[] no .NET (C #) sem especificar manualmente uma codificação específica?

Eu vou criptografar a string. Eu posso criptografá-lo sem converter, mas ainda gostaria de saber por que a codificação vem aqui.

Além disso, por que a codificação deve ser levada em consideração? Não consigo simplesmente saber em que bytes a string foi armazenada? Por que há uma dependência nas codificações de caracteres?

Ao contrário das respostas aqui, você NÃO precisa se preocupar com a codificação se os bytes não precisarem ser interpretados!

Como você mencionou, seu objective é, simplesmente, “pegar em que bytes a string foi armazenada” .
(E, claro, para poder reconstruir a string a partir dos bytes.)

Para esses objectives, eu sinceramente não entendo por que as pessoas continuam dizendo que você precisa das codificações. Você certamente não precisa se preocupar com codificações para isso.

Apenas faça isso em vez disso:

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

Enquanto seu programa (ou outros programas) não tentar interpretar os bytes de alguma forma, o que obviamente você não mencionou que pretende fazer, então não há nada de errado com essa abordagem! Preocupar-se com codificações só torna sua vida mais complicada sem nenhuma razão real.

Benefício adicional para esta abordagem:

Não importa se a string contém caracteres inválidos, porque você ainda pode obter os dados e reconstruir a string original de qualquer maneira!

Ele será codificado e decodificado da mesma forma, porque você está apenas olhando para os bytes .

Se você usasse uma codificação específica, no entanto, teria lhe dado problemas com a codificação / decodificação de caracteres inválidos.

Depende da codificação da sua string ( ASCII , UTF-8 , …).

Por exemplo:

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

Uma pequena amostra da importância da codificação:

 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 simplesmente não está equipado para lidar com caracteres especiais.

Internamente, o .NET framework usa UTF-16 para representar strings, portanto, se você quiser simplesmente obter os bytes exatos que o .NET usa, use System.Text.Encoding.Unicode.GetBytes (...) .

Consulte Codificação de caracteres no .NET Framework (MSDN) para obter mais informações.

A resposta aceita é muito, muito complicada. Use as classs .NET incluídas para isso:

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

Não reinvente a roda se você não precisa …

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

Você precisa levar em conta a codificação, porque 1 caractere pode ser representado por 1 ou mais bytes (até cerca de 6), e diferentes codificações tratam esses bytes de maneira diferente.

Joel tem uma postagem sobre isso:

O Mínimo Absoluto que Todo Desenvolvedor de Software Absolutamente, Positivamente Deve Saber Sobre Unicode e Conjuntos de Caracteres (Sem desculpas!)

Esta é uma pergunta popular. É importante entender o que o autor da pergunta está fazendo e que é diferente da provável necessidade mais comum. Para desencorajar o uso indevido do código onde ele não é necessário, respondi o primeiro primeiro.

Necessidade Comum

Cada string possui um conjunto de caracteres e codificação. Quando você converte um object System.String em uma matriz de System.Byte você ainda tem um conjunto de caracteres e codificação. Para a maioria dos usos, você saberá qual conjunto de caracteres e codificação você precisa e o .NET simplifica a “cópia com conversão”. Basta escolher a class de Encoding apropriada.

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

A conversão pode precisar lidar com casos em que o conjunto de caracteres de destino ou a codificação não suporta um caractere que esteja na origem. Você tem algumas opções: exceção, substituição ou pular. A política padrão é replace um ‘?’.

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

Claramente, as conversões não são necessariamente sem perdas!

Nota: Para System.String o conjunto de caracteres de origem é Unicode.

A única coisa confusa é que o .NET usa o nome de um conjunto de caracteres para o nome de uma codificação específica desse conjunto de caracteres. Encoding.Unicode deve ser chamado de Encoding.UTF16 .

É isso para a maioria dos usos. Se é isso que você precisa, pare de ler aqui. Veja o divertido artigo de Joel Spolsky se você não entender o que é uma codificação.

Necessidade Específica

Agora, o autor da pergunta pergunta: “Cada string é armazenada como uma matriz de bytes, certo? Por que não posso simplesmente ter esses bytes?”

Ele não quer nenhuma conversão.

Da especificação C # :

Caractere e processamento de seqüência de caracteres em C # usa codificação Unicode. O tipo char representa uma unidade de código UTF-16 e o ​​tipo string representa uma sequência de unidades de código UTF-16.

Então, sabemos que, se pedirmos a conversão nula (isto é, de UTF-16 para UTF-16), obteremos o resultado desejado:

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

Mas, para evitar a menção de codificações, devemos fazer isso de outra maneira. Se um tipo de dados intermediário for aceitável, há um atalho conceitual para isso:

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

Isso não nos dá o tipo de dados desejado, mas a resposta de Mehrdad mostra como converter essa matriz Char em uma matriz Byte usando BlockCopy . No entanto, isso copia a seqüência de caracteres duas vezes! E, também, explicitamente, usa código específico de codificação: o tipo de dados System.Char .

A única maneira de obter os bytes reais em que a String está armazenada é usar um ponteiro. A declaração fixed permite pegar o endereço dos valores. Da especificação C #:

[Para] uma expressão do tipo string, … o inicializador calcula o endereço do primeiro caractere na string.

Para fazer isso, o compilador escreve o código ignorando as outras partes do object string com RuntimeHelpers.OffsetToStringData . Então, para obter os bytes brutos, basta criar um ponteiro para a string e copiar o número de bytes necessários.

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

Como apontaram @CodesInChaos, o resultado depende do endianness da máquina. Mas o autor da pergunta não está preocupado com isso.

Apenas para demonstrar que a resposta sonora de Mehrdrad funciona, sua abordagem pode até mesmo persistir nos personagens substitutos não pareados (dos quais muitos se nivelaram contra minha resposta, mas dos quais todos são igualmente culpados, por exemplo, System.Text.Encoding.UTF8.GetBytes , System.Text.Encoding.Unicode.GetBytes ; esses methods de codificação não podem persistir os altos caracteres substitutos d800 por exemplo, e aqueles apenas substituem os caracteres substitutos altos pelo valor 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); } } 

Saída:

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

Tente isso com System.Text.Encoding.UTF8.GetBytes ou System.Text.Encoding.Unicode.GetBytes , eles apenas replaceão caracteres substitutos altos pelo valor fffd

Toda vez que há um movimento nessa questão, ainda estou pensando em um serializador (seja da Microsoft ou de um componente de terceiros) que pode persistir cadeias, mesmo que contenha caracteres substitutos não-pareados; Eu google isso de vez em quando: serialização caráter substituto não emparelhado . Isso não me faz perder o sono, mas é meio chato quando, de vez em quando, alguém comentando a minha resposta é falho, mas as respostas são igualmente falhas quando se trata de personagens substitutos não pareados.

Darn, Microsoft deveria ter usado apenas System.Buffer.BlockCopy no seu BinaryFormatter

谢谢!

Tente isso, muito menos código:

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

A primeira parte da sua pergunta (como obter os bytes) já foi respondida por outras pessoas: procure no namespace System.Text.Encoding .

Vou abordar sua pergunta de acompanhamento: por que você precisa escolher uma codificação? Por que você não consegue isso da própria class de string?

A resposta está em duas partes.

Primeiro de tudo, os bytes usados ​​internamente pela class de strings não importam , e sempre que você assume que eles estão provavelmente introduzindo um bug.

Se o seu programa estiver totalmente dentro do mundo do .Net, você não precisa se preocupar em obter matrizes de bytes para cadeias de caracteres, mesmo que esteja enviando dados por uma rede. Em vez disso, use Serialização .Net para se preocupar com a transmissão dos dados. Você não se preocupa mais com os bytes reais: o formatador de serialização faz isso por você.

Por outro lado, e se você estiver enviando esses bytes para algum lugar que não possa garantir que os dados sejam extraídos de um stream serializado em .Net? Neste caso você definitivamente precisa se preocupar com a codificação, porque obviamente este sistema externo se importa. Então, novamente, os bytes internos usados ​​pela string não importam: você precisa escolher uma codificação para poder ser explícito sobre essa codificação no final do recebimento, mesmo que seja a mesma codificação usada internamente pelo .Net.

Eu entendo que, neste caso, você pode preferir usar os bytes reais armazenados pela variável de seqüência de caracteres na memory, sempre que possível, com a ideia de que pode economizar algum trabalho criando seu stream de bytes. No entanto, eu coloquei para você, não é importante, em comparação com a certeza de que sua saída é entendida do outro lado, e para garantir que você deve ser explícito com sua codificação. Além disso, se você realmente deseja corresponder aos seus bytes internos, basta escolher a codificação Unicode e obter essa economia de desempenho.

O que me leva à segunda parte … escolhendo a codificação Unicode está dizendo .net para usar os bytes subjacentes. Você precisa escolher essa codificação, porque quando algum novo Unicode-Plus sai, o tempo de execução do .Net precisa estar livre para usar este modelo de codificação melhor e mais novo sem quebrar seu programa. Mas, no momento (e no futuro previsível), apenas a escolha da codificação Unicode fornece o que você deseja.

Também é importante entender que sua string precisa ser reescrita para ser ligada, e isso envolve pelo menos alguma tradução do padrão de bits, mesmo quando você usa uma codificação correspondente . O computador precisa explicar coisas como Big vs Little Endian, ordem de bytes de rede, pacote, informações de session, etc.

Bem, eu li todas as respostas e elas estavam sobre o uso de codificação ou sobre a serialização que substitui substitutos não pareados.

É ruim quando a string, por exemplo, vem do SQL Server, onde foi construída a partir de um array de bytes que armazena, por exemplo, um hash de senha. Se descartarmos alguma coisa dele, ele armazenará um hash inválido e, se quisermos armazená-lo em XML, queremos deixá-lo intacto (porque o gravador XML descarta uma exceção em qualquer substituto não-pareado encontrado).

Então, eu uso a codificação Base64 de matrizes de bytes em tais casos, mas ei, na Internet existe apenas uma solução para isso em C #, e ele tem bug nele e é apenas uma maneira, então eu consertei o bug e gravei de volta procedimento. Aqui estão vocês, futuros googlers:

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

Também explique por que a codificação deve ser levada em consideração. Não consigo simplesmente saber em que bytes a string foi armazenada? Por que essa dependência na codificação? !!!

Porque não existe tal coisa como “os bytes da string”.

Uma string (ou mais genericamente, um texto) é composta de caracteres: letras, dígitos e outros símbolos. Isso é tudo. Computadores, no entanto, não sabem nada sobre personagens; eles só podem manipular bytes. Portanto, se você deseja armazenar ou transmitir texto usando um computador, é necessário transformar os caracteres em bytes. Como você faz isso? Aqui é onde as codificações vêm para a cena.

Uma codificação não é nada além de uma convenção para converter caracteres lógicos em bytes físicos. A codificação mais simples e mais conhecida é ASCII, e é tudo que você precisa se escrever em inglês. Para outros idiomas, você precisará de codificações mais completas, sendo que qualquer um dos sabores Unicode é a escolha mais segura hoje em dia.

Então, em suma, tentar “obter os bytes de uma string sem usar codificações” é tão impossível quanto “escrever um texto sem usar nenhuma linguagem”.

A propósito, eu recomendo fortemente que você (e qualquer um, por falar nisso) leia este pequeno pedaço de sabedoria: O Mínimo Absoluto Todo Desenvolvedor de Software Absolutamente, Positivamente Deve Saber Sobre Unicode e Conjuntos de Caracteres (Sem desculpas!)

C # para converter uma string em uma matriz de 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); } 

Você pode usar o seguinte código para conversão entre matriz de seqüência de caracteres e byte.

 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) 

Usar:

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

O resultado é:

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

Dois caminhos:

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

Simplesmente use isto:

 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.

Exemplo:

 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.