3
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来提供很多关于如何格式化事物的选项,但我没有看到任何方法告诉它不要格式化/更改/更改数据的值。

4

2 回答 2

9

您可以将字节转换为字符:

sb.Append((char)b);

您还可以使用 anASCIIEncoding一次转换所有字节:

string s = Encoding.ASCII.GetString(packedDecValue);
sb.Append(s);
于 2012-12-21T19:06:51.407 回答
1

如前所述,在 Unicode 世界中,字节(八位字节)不是字符。CLR 在内部使用 Unicode 字符,并在内部以 UTF-16 编码表示它们。AStringBuilder构建一个 UTF-16 编码的 Unicode 字符串。

然而,一旦你有了那个 UTF-16 字符串,你就可以使用 UTF-8 或 ASCIIEncoding 重新编码它。但是,在这两种情况下,代码点 0x0080 和更高的代码点都不会保持原样。

UTF-8 使用 2 个八位字节表示代码点 0x0080–0x07FF;3 个八位字节用于代码点 0x0800–0xFFFF 等等。http://en.wikipedia.org/wiki/UTF-8#Description

ASCII 编码更糟糕:根据文档,0x0000–0x007F 之外的代码点被简单地丢弃:

如果您使用 Encoding.ASCII 属性或 ASCIIEncoding 构造函数返回的默认编码器,则在执行编码操作之前,该范围之外的字符将替换为问号 (?)。

如果您需要毫发无损地发送八位字节流,则最好使用System.IO.MemoryStream包装在 a 中的StreamReaderand StreamWriter

然后,您可以通过它的方法或它的方法访问MemoryStream的后备存储。为您提供对实际后备存储的参考。但是,它可能包含已分配但未使用的字节——您需要检查流的和. 分配一个新数组并将实际流内容复制到其中,因此您收到的数组引用是正确的长度。GetBuffer()ToArray()GetBuffer()LengthCapacityToArray()

于 2012-12-21T20:25:40.247 回答