.net obtener - ¿Cómo obtengo una representación de bytes consistente de cadenas en C#sin especificar manualmente una codificación?




los ultimos (25)

¿Cómo convierto una string a un byte[] en .NET (C #) sin especificar manualmente una codificación específica?

Voy a cifrar la cadena. Puedo cifrarlo sin convertirlo, pero aún me gustaría saber por qué la codificación viene a jugar aquí.

Además, ¿por qué debería considerarse la codificación? ¿No puedo simplemente obtener en qué bytes se ha almacenado la cadena? ¿Por qué hay una dependencia en las codificaciones de caracteres?


Answers

Bueno, he leído todas las respuestas y trataron sobre el uso de codificación o una sobre la serialización que elimina sustitutos no pareados.

Es malo cuando la cadena, por ejemplo, proviene de SQL Server, donde se creó a partir de una matriz de bytes, por ejemplo, un hash de contraseña. Si eliminamos algo de él, almacenará un hash no válido y si queremos almacenarlo en XML, queremos dejarlo intacto (porque el escritor XML elimina una excepción en cualquier sustituto no pareado que encuentre).

Así que uso la codificación Base64 de matrices de bytes en tales casos, pero bueno, en Internet solo hay una solución para esto en C #, y tiene errores y es solo de una manera, así que arreglé el error y lo escribí. procedimiento. Aquí tienes, 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);
}

C # para convertir a stringa una bytematriz:

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

Esta es una pregunta popular. Es importante entender lo que el autor de la pregunta está haciendo, y que es diferente de lo que probablemente sea la necesidad más común. Para desalentar el uso indebido del código donde no se necesita, he respondido primero más tarde.

Necesidad Común

Cada cadena tiene un conjunto de caracteres y codificación. Cuando convierte un objeto System.String en una matriz de System.Byte , todavía tiene un conjunto de caracteres y codificación. Para la mayoría de los usos, sabría qué conjunto de caracteres y codificación necesita y .NET facilita la "copia con conversión". Simplemente elija la clase de Encoding apropiada.

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

Es posible que la conversión deba manejar casos en los que el conjunto de caracteres o la codificación de destino no sean compatibles con un carácter que esté en el origen. Tienes algunas opciones: excepción, sustitución o saltar. La política predeterminada es sustituir un '?'.

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

Claramente, las conversiones no son necesariamente sin pérdida!

Nota: para System.String el conjunto de caracteres de origen es Unicode.

Lo único confuso es que .NET usa el nombre de un conjunto de caracteres para el nombre de una codificación particular de ese conjunto de caracteres. Encoding.Unicode debe llamarse Encoding.UTF16 .

Eso es todo para la mayoría de los usos. Si eso es lo que necesitas, deja de leer aquí. Vea el divertido joelonsoftware.com/articles/Unicode.html si no entiende qué es una codificación.

Necesidad especifica

Ahora, el autor pregunta: "Cada cadena se almacena como una matriz de bytes, ¿verdad? ¿Por qué no puedo simplemente tener esos bytes?"

Él no quiere ninguna conversión.

De la especificación de C # :

El procesamiento de caracteres y cadenas en C # utiliza la codificación Unicode. El tipo char representa una unidad de código UTF-16, y el tipo de cadena representa una secuencia de unidades de código UTF-16.

Entonces, sabemos que si solicitamos la conversión nula (es decir, de UTF-16 a UTF-16), obtendremos el resultado deseado:

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

Pero para evitar la mención de las codificaciones, debemos hacerlo de otra manera. Si un tipo de datos intermedio es aceptable, hay un atajo conceptual para esto:

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

Eso no nos da el tipo de datos deseado, pero la respuesta de Mehrdad muestra cómo convertir esta matriz Char en una matriz de bytes mediante BlockCopy . Sin embargo, esto copia la cadena dos veces! Y, también utiliza explícitamente el código específico de la codificación: el tipo de datos System.Char .

La única forma de obtener los bytes reales en los que se almacena la cadena es utilizar un puntero. La declaración fixed permite tomar la dirección de valores. De la especificación de C #:

[Para] una expresión de tipo cadena, ... el inicializador calcula la dirección del primer carácter en la cadena.

Para hacerlo, el compilador escribe código de salto sobre las otras partes del objeto de cadena con RuntimeHelpers.OffsetToStringData . Entonces, para obtener los bytes sin procesar, simplemente cree un puntero a la cadena y copie la cantidad de bytes necesarios.

// 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 señaló @CodesInChaos, el resultado depende de la endianness de la máquina. Pero a la pregunta del autor no le preocupa eso.


El enfoque más cercano a la pregunta del OP es Tom Blodget, que en realidad entra en el objeto y extrae los bytes. Digo más cerca porque depende de la implementación del objeto String.

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

Claro, pero ahí es donde surge el error fundamental en la pregunta. La cadena es un objeto que podría tener una estructura de datos interesante. Ya sabemos que lo hace, porque permite que se almacenen sustitutos no pareados. Podría almacenar la longitud. Puede mantener un puntero a cada uno de los sustitutos "emparejados" que permite un conteo rápido. Etc. Todos estos bytes adicionales no son parte de los datos de caracteres.

Lo que quieres son los bytes de cada carácter en una matriz. Y ahí es donde entra la "codificación". De forma predeterminada, obtendrá UTF-16LE. Si no le importan los bytes, excepto el viaje de ida y vuelta, puede elegir cualquier codificación, incluida la "predeterminada", y volver a convertirla más tarde (asumiendo los mismos parámetros, como cuál fue la codificación predeterminada, los puntos de código, las correcciones de errores). , cosas permitidas tales como sustitutos no pareados, etc.

Pero ¿por qué dejar la 'codificación' a la magia? ¿Por qué no especificar la codificación para que sepa qué bytes obtendrá?

"Why is there a dependency on character encodings?"

La codificación (en este contexto) simplemente significa los bytes que representan su cadena. No los bytes del objeto cadena. Quería los bytes en los que se había almacenado la cadena; aquí es donde se hizo la pregunta ingenuamente. Quería los bytes de la cadena en una matriz contigua que representa la cadena y no todos los demás datos binarios que un objeto de cadena puede contener.

Lo que significa que una cadena se almacena es irrelevante. Desea una cadena "Codificada" en bytes en una matriz de bytes.

Me gusta la respuesta de Tom Bloget porque te llevó hacia la dirección de 'bytes de la cadena de objetos'. Sin embargo, depende de la implementación, y debido a que está mirando hacia adentro, puede ser difícil reconstituir una copia de la cadena.

La respuesta de Mehrdad es incorrecta porque es engañosa en el nivel conceptual. Todavía tienes una lista de bytes, codificados. Su solución particular permite preservar sustitutos no pareados, esto depende de la implementación. Su solución particular no produciría los bytes de la cadena con precisión si se GetBytesdevolviera la cadena en UTF-8 de forma predeterminada.

He cambiado de opinión sobre esto (la solución de Mehrdad): esto no está obteniendo los bytes de la cadena; más bien está obteniendo los bytes de la matriz de caracteres que se creó a partir de la cadena. Independientemente de la codificación, el tipo de datos char en c # es un tamaño fijo. Esto permite que se produzca una matriz de bytes de longitud constante, y permite que la matriz de caracteres se reproduzca en función del tamaño de la matriz de bytes. Entonces, si la codificación fuera UTF-8, pero cada caracter fuera de 6 bytes para acomodar el mayor valor de utf8, aún funcionaría. Así que, de hecho, la codificación del personaje no importa.

Pero se usó una conversión: cada carácter se colocó en un cuadro de tamaño fijo (tipo de carácter de c #). Sin embargo, no importa qué es esa representación, que técnicamente es la respuesta al OP. Entonces, si vas a convertir de todos modos ... ¿Por qué no 'codificar'?


Si realmente desea una copia de los bytes subyacentes de una cadena, puede usar una función como la que sigue. Sin embargo, no deberías seguir leyendo para averiguar por qué.

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

Esta función le proporcionará una copia de los bytes subyacentes a su cadena, muy rápidamente. Obtendrá esos bytes de cualquier forma que estén codificando en su sistema. Esta codificación es casi seguramente UTF-16LE, pero ese es un detalle de implementación que no debería tener que preocuparse.

Sería más seguro, más simple y más confiable simplemente llamar,

System.Text.Encoding.Unicode.GetBytes()

Con toda probabilidad, esto dará el mismo resultado, es más fácil de escribir y los bytes siempre se redondearán con una llamada a

System.Text.Encoding.Unicode.GetString()

¿Cómo convierto una cadena a un byte [] en .NET (C #) sin especificar manualmente una codificación específica?

Una string en .NET representa el texto como una secuencia de unidades de código UTF-16, por lo que los bytes ya están codificados en la memoria en UTF-16.

La respuesta de Mehrdad

Puedes usar la respuesta de Mehrdad , pero en realidad usa una codificación porque los caracteres son UTF-16. Llama a ToCharArray, que al ver la fuente crea char[]y copia la memoria directamente. Luego copia los datos a una matriz de bytes que también se asigna. Así que debajo del capó está copiando los bytes subyacentes dos veces y asignando una matriz de caracteres que no se usa después de la llamada.

La respuesta de Tom Blodget

La respuesta de Tom Blodget es un 20-30% más rápida que la de Mehrdad, ya que omite el paso intermedio de asignar una matriz de caracteres y copiar los bytes en ella, pero requiere que compiles con la /unsafeopción. Si no desea utilizar la codificación, creo que este es el camino a seguir. Si coloca su inicio de sesión de cifrado dentro del fixedbloque, ni siquiera necesita asignar una matriz de bytes separada y copiar los bytes en ella.

Además, ¿por qué debería considerarse la codificación? ¿No puedo simplemente obtener en qué bytes se ha almacenado la cadena? ¿Por qué hay una dependencia en las codificaciones de caracteres?

Porque esa es la forma correcta de hacerlo. stringEs una abstracción.

El uso de una codificación podría causarle problemas si tiene 'cadenas' con caracteres no válidos, pero eso no debería suceder. Si está obteniendo datos en su cadena con caracteres no válidos, lo está haciendo mal. Probablemente debería estar usando una matriz de bytes o una codificación Base64 para comenzar.

Si lo usas System.Text.Encoding.Unicode, tu código será más resistente. No tiene que preocuparse por la endianness del sistema en el que se ejecutará su código. No debe preocuparse si la próxima versión de CLR usará una codificación de caracteres interna diferente.

Creo que la pregunta no es por qué quieres preocuparte por la codificación, sino por qué quieres ignorarla y usar otra cosa. La codificación está destinada a representar la abstracción de una cadena en una secuencia de bytes. System.Text.Encoding.Unicodele dará una pequeña codificación de bytes de bytes endian y funcionará de la misma manera en todos los sistemas, ahora y en el futuro.


La respuesta aceptada es muy, muy complicada. Utilice las clases .NET incluidas para esto:

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

No reinventes la rueda si no tienes que ...


Con la llegada de Span<T>C # 7.2, la técnica canónica para capturar la representación de memoria de una cadena en una matriz de bytes administrada es:

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

Volver a convertirlo no debería ser un arranque, ya que eso significa que de hecho está interpretando los datos de alguna manera, pero para completarlos:

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

Los nombres NonPortableCasty DangerousGetPinnableReferencedeben promover el argumento de que probablemente no deberías estar haciendo esto.

Tenga en cuenta que trabajar con Span<T>requiere instalar el paquete System.Memory NuGet .

En cualquier caso, la pregunta original real y los comentarios de seguimiento implican que la memoria subyacente no se está "interpretando" (lo que supongo que significa que no se modifica o lee más allá de la necesidad de escribirla tal como está), lo que indica que alguna implementación de la Streamclase debe utilizarse en lugar de razonar sobre los datos como cadenas en absoluto.


La primera parte de su pregunta (cómo obtener los bytes) ya fue respondida por otros: busque en el System.Text.Encoding nombres System.Text.Encoding .

Abordaré su pregunta de seguimiento: ¿por qué necesita elegir una codificación? ¿Por qué no puedes obtener eso de la propia clase de cadena?

La respuesta está en dos partes.

En primer lugar, los bytes utilizados internamente por la clase de cadena no importan , y siempre que asuma que lo hacen, es probable que esté introduciendo un error.

Si su programa está completamente dentro del mundo .Net, entonces no necesita preocuparse por obtener matrices de bytes para cadenas, incluso si está enviando datos a través de una red. En su lugar, use .Net Serialization para preocuparse por la transmisión de datos. Ya no se preocupa por los bytes reales: el formateador de serialización lo hace por usted.

Por otro lado, ¿qué sucede si está enviando estos bytes a algún lugar que no puede garantizar que extraerá datos de un flujo serializado .Net? En este caso, definitivamente debe preocuparse por la codificación, porque obviamente a este sistema externo le importa. De nuevo, los bytes internos utilizados por la cadena no importan: debe elegir una codificación para que pueda ser explícito acerca de esta codificación en el extremo receptor, incluso si es la misma codificación utilizada internamente por .Net.

Entiendo que en este caso, es posible que prefiera usar los bytes reales almacenados por la variable de cadena en la memoria siempre que sea posible, con la idea de que podría ahorrar algo de trabajo al crear su flujo de bytes. Sin embargo, te lo pongo, no es importante en comparación con asegurarte de que tu salida se comprenda en el otro extremo y garantizar que debes ser explícito con tu codificación. Además, si realmente desea hacer coincidir sus bytes internos, ya puede elegir la codificación Unicode y obtener ese ahorro de rendimiento.

Lo que me lleva a la segunda parte ... elegir la codificación Unicode es decirle a .Net que use los bytes subyacentes. Es necesario que elija esta codificación, porque cuando aparece Unicode-Plus con nuevos colmillos, el tiempo de ejecución .Net debe ser libre para usar este modelo de codificación mejor y más nuevo sin interrumpir su programa. Pero, por el momento (y el futuro previsible), con solo elegir la codificación Unicode, obtendrá lo que desea.

También es importante entender que la cadena debe volver a escribirse en el cable, y eso implica al menos una traducción del patrón de bits, incluso cuando se utiliza una codificación coincidente . La computadora debe tener en cuenta cosas como Big vs Little Endian, orden de bytes de la red, paquetización, información de sesión, etc.


El problema clave es que un glifo en una cadena toma 32 bits (16 bits para un código de caracteres) pero un byte solo tiene 8 bits de sobra. No existe una asignación uno a uno a menos que se limite a cadenas que solo contengan caracteres ASCII. System.Text.Encoding tiene muchas formas de asignar una cadena a byte [], debe elegir una que evite la pérdida de información y que sea fácil de usar por su cliente cuando necesite asignar el byte [] a una cadena .

Utf8 es una codificación popular, es compacta y no tiene pérdidas.


La manera más rápida

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

EDITAR como Makotosan comentó esta es ahora la mejor manera:

Encoding.UTF8.GetBytes(text)

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

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

Depende de lo que quieras para los bytes.

Esto se debe a que, como Tyler lo said tan acertadamente , "las cadenas no son datos puros. También tienen information ". En este caso, la información es una codificación que se asumió cuando se creó la cadena.

Suponiendo que tiene datos binarios (en lugar de texto) almacenados en una cadena

Esto se basa en el comentario de OP sobre su propia pregunta, y es la pregunta correcta si entiendo las sugerencias de OP sobre el caso de uso.

¡Almacenar datos binarios en cadenas es probablemente el enfoque incorrecto debido a la supuesta codificación mencionada anteriormente! Cualquier programa o biblioteca que haya almacenado esos datos binarios en un string(en lugar de una byte[]matriz que hubiera sido más apropiado) ya ha perdido la batalla antes de que haya comenzado. Si le envían los bytes en una solicitud / respuesta REST o cualquier cosa que deba transmitir cadenas, Base64 sería el enfoque correcto.

Si tienes una cadena de texto con una codificación desconocida

Todos los demás respondieron esta pregunta incorrecta incorrectamente.

Si la cadena se ve bien como está, simplemente elija una codificación (preferiblemente una que comience con UTF), use la System.Text.Encoding.???.GetBytes()función correspondiente y dígale a quien le da los bytes a la codificación que eligió.


código simple con LINQ

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

EDITAR: como se comenta a continuación, no es una buena manera.

pero todavía puedes usarlo para entender LINQ con una codificación más apropiada:

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

Al contrario de las respuestas aquí, ¡NO tiene que preocuparse por la codificación si los bytes no necesitan ser interpretados!

Como mencionó, su objetivo es, simplemente, "obtener en qué bytes se ha almacenado la cadena" .
(Y, por supuesto, para poder reconstruir la cadena a partir de los bytes.)

Para esos objetivos, honestamente no entiendo por qué la gente te dice que necesitas las codificaciones. Ciertamente, NO es necesario preocuparse por las codificaciones para esto.

Solo haz esto en su lugar:

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

Mientras tu programa (u otros programas) no intente interpretar los bytes de alguna manera, lo que obviamente no mencionaste que pretendes hacer, ¡entonces no hay nada de malo en este enfoque! Preocuparse por las codificaciones solo hace que tu vida sea más complicada sin ninguna razón real.

Beneficio adicional a este enfoque:

¡No importa si la cadena contiene caracteres no válidos, porque de todos modos aún puede obtener los datos y reconstruir la cadena original!

Se codificará y decodificará de la misma manera, porque solo está mirando los bytes .

Sin embargo, si usó una codificación específica, le habría dado problemas para codificar / descodificar caracteres no válidos.


También explique por qué se debe tener en cuenta la codificación. ¿No puedo simplemente obtener en qué bytes se ha almacenado la cadena? ¿Por qué esta dependencia en la codificación? !!!

Porque no hay tal cosa como "los bytes de la cadena".

Una cadena (o más genéricamente, un texto) está compuesta de caracteres: letras, dígitos y otros símbolos. Eso es todo. Las computadoras, sin embargo, no saben nada de los personajes; solo pueden manejar bytes. Por lo tanto, si desea almacenar o transmitir texto usando una computadora, necesita transformar los caracteres en bytes. ¿Cómo haces eso? Aquí es donde las codificaciones vienen a la escena.

Una codificación no es más que una convención para traducir caracteres lógicos a bytes físicos. La codificación más simple y conocida es ASCII, y es todo lo que necesita si escribe en inglés. Para otros idiomas, necesitará codificaciones más completas, siendo cualquiera de los sabores de Unicode la opción más segura en la actualidad.

Entonces, en pocas palabras, tratar de "obtener los bytes de una cadena sin usar codificaciones" es tan imposible como "escribir un texto sin usar ningún idioma".

Por cierto, te recomiendo encarecidamente a ti (y a cualquier persona) que leas esta pequeña pieza de sabiduría: joelonsoftware.com/articles/Unicode.html


Dos caminos:

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

Y,

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

Tiendo a usar el de abajo más a menudo que el de arriba, no los he evaluado para la velocidad.


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

Aquí está mi aplicación poco segura de Stringque Byte[]la conversión:

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

Es mucho más rápido que el de la anwser aceptada, aunque no sea tan elegante como es. Aquí están mis puntos de referencia de cronómetro sobre 10000000 iteraciones:

[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

Para usarlo, debe marcar "Permitir código no seguro" en las propiedades de compilación de su proyecto. Según .NET Framework 3.5, este método también se puede utilizar como extensión de cadena:

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

Solo para demostrar que la share sonido de Mehrdrad funciona, su enfoque puede incluso persistir en [BinaryFormatter (de los cuales muchos se habían nivelado en contra de mi respuesta, pero de los cuales todos son igualmente culpables, por ejemplo, System.Text.Encoding.UTF8.GetBytes , System.Text.Encoding.Unicode.GetBytes ; esos métodos de codificación no pueden conservar los caracteres sustitutos altos d800 por ejemplo, y simplemente reemplazan los caracteres sustitutos altos con el 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);
    }        
}

Salida:

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

Intente eso con System.Text.Encoding.UTF8.GetBytes o System.Text.Encoding.Unicode.GetBytes , simplemente reemplazarán los caracteres sustitutos altos con el valor fffd

Cada vez que hay un movimiento en esta pregunta, todavía estoy pensando en un serializador (ya sea de Microsoft o de un componente de terceros) que puede persistir en cadenas incluso que contiene caracteres sustitutos no pareados; Busco en Google esto de vez en cuando: serialización no pareada . Surrogate caracter .NET . Esto no me hace perder el sueño, pero es un poco molesto cuando de vez en cuando alguien comenta en mi respuesta que tiene fallas, pero sus respuestas son igualmente erróneas cuando se trata de personajes sustitutos no apareados.

Maldición, Microsoft debería haber usado System.Buffer.BlockCopy en su BinaryFormatter

谢谢!


Utilizar:

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

El resultado es:

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

Puede usar el siguiente código para convertir stringa a byte arrayen .NET

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

Puede usar el siguiente código para la conversión entre la cadena y la matriz de bytes.

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

Puede utilizar métodos de extensión ahora:

public static T ToEnum<T>(this string value, bool ignoreCase = true)
{
    return (T) Enum.Parse(typeof (T), value, ignoreCase);
}

Y puede llamarlos por el siguiente código (aquí, FilterType es un tipo de enumeración):

FilterType filterType = type.ToEnum<FilterType>();




c# .net string character-encoding