РЕДАКТИРАНЕ: Намерих решение, ето го за всеки друг, който може да го иска. Може да бъде актуализиран в бъдеще, ако се открие грешка или се добавят други подобрения. Последна актуализация на 18.07.2015 г.
/// <summary>
/// Decodes a string from the specified bytes in the specified encoding.
/// </summary>
/// <param name="Length">Specify -1 to read until null, otherwise, specify the amount of bytes that make up the string.</param>
public static string GetString(byte[] Source, int Offset, int Length, Encoding Encoding)
{
if (Length == 0) return string.Empty;
var sb = new StringBuilder();
if (Length <= -1)
{
using (var sr = new StreamReader(new MemoryStream(Source, Offset, Source.Length - Offset), Encoding, false))
{
int ch;
while (true)
{
ch = sr.Read();
if (ch <= 0) break;
sb.Append((char)ch);
}
if (ch == -1) throw new Exception("End of stream reached; null terminator not found.");
return sb.ToString();
}
}
else return Encoding.GetString(Source, Offset, Length);
}
Надстройвам вътрешния низ/кодиращ код на приложението си и се натъкнах на малък проблем с внедряването.
По принцип исках да направя лесен метод, ReadNullTerminatedString. В началото не беше много трудно да се направи. Използвах Encoding.IsSingleByte, за да определя дължината на един символ, щях да прочета байтовете, да проверя за 0s и да спра четенето/продължа въз основа на резултата.
Това е мястото, където става трудно. UTF8 има кодиране с променлива дължина. Encoding.IsSingleByte връща false, но това не винаги е правилно, тъй като това е променливо кодиране и знакът може да бъде 1 байт, така че моята реализация, базирана на Encoding.IsSingleByte, няма да работи за UTF8.
В този момент не бях сигурен дали този метод може да бъде коригиран, така че имах друга идея. Просто използвайте метода GetString на кодирането върху байтовете, използвайте максималната дължина, която низът може да бъде за параметъра за броене, и след това отрежете нулите от върнатия низ.
Това също има предупреждение. Трябва да обмисля случаите, в които моите управлявани приложения ще взаимодействат с масиви от байтове, върнати от неуправляван код, случаи, в които ще има нулев терминатор, разбира се, но възможността да има допълнителни нежелани знаци след него. Например: "blah\0\0\oldstring"
ReadNullTerminatedString би било идеалното решение в този случай, но в момента не може да бъде, ако искам да поддържа UTF8. Второто решение също няма да работи - ще изреже 0-те, но боклуците ще останат.
Някакви идеи за елегантно решение за C#?