StringBuilder добавляет байт без форматирования

DateTime todayDateTime = DateTime.Now;
StringBuilder todayDateTimeSB = new StringBuilder("0");
todayDateTimeSB.Append(todayDateTime.ToString("MMddyyyy"));
long todayDateTimeLongValue = Convert.ToInt64(todayDateTimeSB.ToString());
// convert to byte array packed decimal
byte[] packedDecValue = ToComp3UsingStrings(todayDateTimeLongValue); 
// append each byte to the string builder
foreach (byte b in packedDecValue)
{
    sb.Append(b); // bytes 56-60
}
sb.Append(' ', 37);

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

Однако выше приведен код, с которым у меня возникают проблемы, в частности, я исследовал и обнаружил, что строитель строк .Append(byte) на самом деле делает ToString() для этого байта. Который изменяет значение байта при добавлении его в строку. Вопрос в том, как мне StringBuilder взять "байт" как есть и сохранить его в памяти без форматирования / изменения значения. Я знаю, что есть также .AppendFormat() который имеет несколько перегрузок, которые используют IFormatProvider дать много-много опций о том, как форматировать вещи, но я не вижу способа сказать это НЕ форматировать / изменять / изменять значение данных.

2 ответа

Вы можете преобразовать байт в символ:

sb.Append((char)b);

Вы также можете использовать ASCIIEncoding преобразовать все байты одновременно:

string s = Encoding.ASCII.GetString(packedDecValue);
sb.Append(s);

As noted, in a Unicode world, bytes (octets) are not characters. The CLR works with Unicode characters internally and internally represents them in the UTF-16 encoding. StringBuilder builds a UTF-16 encoded Unicode string.

Once you have that UTF-16 string, however, you can re-encode it, using, say UTF-8 or the ASCIIEncoding. However, in both of those, code points 0x0080 and higher will not be left as-is.

UTF-8 uses 2 octets for code points 0x0080–0x07FF; 3 octets for code points 0x0800–0xFFFF and so on. http://en.wikipedia.org/wiki/UTF-8

The ASCII encoding is worse: per the documentation, code points outside 0x0000–0x007F are simply chucked:

If you use the default encoder returned by the Encoding.ASCII property or the ASCIIEncoding constructor, characters outside that range are replaced with a question mark (?) before the encoding operation is performed.

Если вам нужно отправить поток октетов в целости и сохранности, лучше использовать System.IO.MemoryStream завернутый в StreamReader а также StreamWriter,

Вы можете получить доступ к MemoryStream Поддерживает магазин через свой GetBuffer() метод или его ToArray() метод. GetBuffer() дает вам ссылку на фактический резервный магазин. Однако он, вероятно, содержит выделенные, но неиспользуемые байты - вам нужно проверить поток Length а также Capacity, ToArray() выделяет новый массив и копирует в него фактическое содержимое потока, поэтому полученная вами ссылка на массив имеет правильную длину.

Другие вопросы по тегам