Как получить строку с нулевым завершением из строки С#?

  • Я общаюсь с сервером, которому нужна строка с нулевым завершением
  • Как я могу сделать это умно на C#?

person Betamoo    schedule 08.05.2010    source источник


Ответы (4)


Я предполагаю, что вы реализуете какой-то двоичный протокол, если строки заканчиваются нулем. Вы используете BinaryWriter?

По умолчанию BinaryWriter записывает строки с префиксом длины. Вы можете изменить это поведение:

class MyBinaryWriter : BinaryWriter
{
    private Encoding _encoding = Encoding.Default;

    public override void Write(string value)
    {
        byte[] buffer = _encoding.GetBytes(value);
        Write(buffer);
        Write((byte)0);
    }
}

Затем вы можете просто написать любую строку следующим образом:

using (MyBinaryWriter writer = new MyBinaryWriter(myStream))
{
    writer.Write("Some string");
}

Возможно, вам придется настроить бит _encoding в зависимости от ваших потребностей.

Вы, конечно, можете расширить класс с конкретными потребностями для других типов данных, которые вам могут понадобиться для передачи, сохраняя вашу фактическую реализацию протокола красивой и чистой. Возможно, вам также понадобится ваш собственный (очень похожий) BinaryReader.

person Thorarin    schedule 08.05.2010
comment
Вместо этого я бы предложил использовать base.Write(this._encoding.GetBytes(new char[]{ ''})) для кодирования нулевого терминатора. UTF-16 по умолчанию составляет 2 байта и ожидает два нулевых байта в конце. - person toong; 18.06.2012
comment
Добавьте значение с помощью \0 (если оно еще не заканчивается на него): if (!value.EndsWith("\0")) value += "\0"; таким образом делая решение независимым от кодировки (вам не нужно беспокоиться о количестве нулей). - person marchewek; 18.12.2012

Я думаю, что умный способ сделать это просто.

string str = "An example string" + char.MinValue; // Add null terminator.

Затем конвертируйте его в байты для отправки на сервер.

byte[] buffer = ASCIIEncoding.ASCII.GetBytes(str);

Конечно, какую кодировку вы используете, зависит от того, какую кодировку ожидает сервер.

person Alex McBride    schedule 08.05.2010
comment
char.MinValue - это настоящий путь С# - person A. M.; 19.06.2010
comment
Это, безусловно, самый простой (и самый надежный) способ, который я нашел. Это должен быть принятый ответ. - person jhmckimm; 08.10.2016

Строки уже заканчиваются нулем. Хотя сама строка не содержит нулевого символа, нулевой символ всегда следует за строкой в ​​памяти.

Однако строки в .NET имеют кодировку Unicode, поэтому они хранятся в памяти как UTF-16/UCS-2, и сервер может ожидать другую кодировку, обычно 8-битную. Затем вам нужно будет закодировать строку в массив байтов и поместить нулевой байт в конце:

byte[] data = Encoding.Default.GetBytes(theString);
byte[] zdata = new byte[data.Length + 1];
data.CopyTo(zdata, 0);

(Массив zdata при создании заполняется нулями, поэтому вам не нужно фактически устанавливать дополнительный байт равным нулю.)

person Guffa    schedule 08.05.2010
comment
Исправлена ​​незначительная опечатка. Лично я не слишком доволен двойным выделением буфера. Вы можете обойти это. Опять же, струны вряд ли будут огромными или очень громкими. - person Thorarin; 08.05.2010
comment
Завершение нулевым значением обычно означает окончание на первом нулевом значении. Строки .NET не могут считаться заканчивающимися нулем, если вы также допускаете, что строка .NET может содержать один или несколько нулевых символов и при этом не завершаться - person John Saunders; 08.05.2010
comment
Строки уже заканчиваются нулем. Хотя сама строка не содержит нулевого символа, нулевой символ всегда следует за строкой в ​​памяти. Я никогда не слышал об этом раньше и не видел никакой информации об этом в документах MSDN. Не могли бы вы опубликовать источник? - person Juliet; 08.05.2010
comment
@John: Что я имел в виду конкретно в первом предложении, так это то, что после строки уже есть завершающий ноль. Если сама строка содержит нулевой символ, она, естественно, не будет работать должным образом как строка с нулевым завершением, но это проблема, которую разделяет каждый отдельный ответ, представленный здесь. - person Guffa; 08.05.2010
comment
@Guffa: страница Джона, похоже, напрямую противоречит фактической документации. Я не думаю, что строки C# на самом деле заканчиваются нулем, процесс маршалинга просто знает, как завершать их нулем (и я не уверен, как он сохранит встроенные нули или возможно ли это вообще). - person Aaronaught; 08.05.2010
comment
@Aaronaught: в документации только говорится, что в строке не используется завершающий нулевой символ, и ничего не говорится о том, помещается ли нулевой символ после строки в массиве символов или нет. - person Guffa; 08.05.2010

Вы добавляете нулевой символ в конец строки. Строки .NET могут содержать нулевые символы.

person Tomalak    schedule 08.05.2010
comment
Я думаю, что он предлагает «char c = new char()», что создаст точку Юникода «U + 0000». - person Steve Cooper; 15.09.2010