Мне нужно преобразовать (возможно) массив байтов ascii с нулевым завершением в строку на C#, и самый быстрый способ, который я нашел для этого, — использовать мой метод UnsafeAsciiBytesToString, показанный ниже. Этот метод использует конструктор String.String(sbyte*), который содержит предупреждение в своих примечаниях:
«Предполагается, что параметр value указывает на массив, представляющий строку, закодированную с использованием кодовой страницы ANSI по умолчанию (то есть метода кодирования, указанного Encoding.Default).
Примечание: * Поскольку кодовая страница ANSI по умолчанию зависит от системы, строка, созданная этим конструктором из идентичных массивов байтов со знаком, может различаться в разных системах. * ...
* Если указанный массив не завершается нулем, поведение этого конструктора зависит от системы. Например, такая ситуация может вызвать нарушение прав доступа. * "
Теперь я уверен, что способ кодирования строки никогда не изменится... но кодовая страница по умолчанию в системе, в которой работает мое приложение, может измениться. Итак, есть ли причина, по которой я не должен кричать от использования String.String(sbyte*) для этой цели?
using System;
using System.Text;
namespace FastAsciiBytesToString
{
static class StringEx
{
public static string AsciiBytesToString(this byte[] buffer, int offset, int maxLength)
{
int maxIndex = offset + maxLength;
for( int i = offset; i < maxIndex; i++ )
{
/// Skip non-nulls.
if( buffer[i] != 0 ) continue;
/// First null we find, return the string.
return Encoding.ASCII.GetString(buffer, offset, i - offset);
}
/// Terminating null not found. Convert the entire section from offset to maxLength.
return Encoding.ASCII.GetString(buffer, offset, maxLength);
}
public static string UnsafeAsciiBytesToString(this byte[] buffer, int offset)
{
string result = null;
unsafe
{
fixed( byte* pAscii = &buffer[offset] )
{
result = new String((sbyte*)pAscii);
}
}
return result;
}
}
class Program
{
static void Main(string[] args)
{
byte[] asciiBytes = new byte[]{ 0, 0, 0, (byte)'a', (byte)'b', (byte)'c', 0, 0, 0 };
string result = asciiBytes.AsciiBytesToString(3, 6);
Console.WriteLine("AsciiBytesToString Result: \"{0}\"", result);
result = asciiBytes.UnsafeAsciiBytesToString(3);
Console.WriteLine("UnsafeAsciiBytesToString Result: \"{0}\"", result);
/// Non-null terminated test.
asciiBytes = new byte[]{ 0, 0, 0, (byte)'a', (byte)'b', (byte)'c' };
result = asciiBytes.UnsafeAsciiBytesToString(3);
Console.WriteLine("UnsafeAsciiBytesToString Result: \"{0}\"", result);
Console.ReadLine();
}
}
}