C#:什么会占用更多内存?字符串还是字节?
假设我有一行读取“我的文本”,该行会以哪种形式占用更多内存,作为字节还是字符串?
它取决于字节数组的字符编码。您可以将任何字符串转换为字节数组,但您必须选择编码;没有单一的标准或正确的编码。过去被称为 ASCII 的东西在英语世界之外毫无用处。
在大多数编码中,“我的文本”的长度为 7 个字节。但是加入一些欧洲重音字符或日本字符,这些(如果它们可以表示的话)可能每个都超过一两个字节。在某些编码中,对于某些文本字符串,字节数组表示可能大于System.String
.
成为 Unicode 并不意味着字符串每个字符占用一个以上的字节,它只是意味着它“可能”每个字符占用一个以上的字节。
什么占用更多内存?
所以你问的是内存表示的大小。.net 对字符串使用UTF-16,这意味着您的示例将由 14 个字节表示,如在此十六进制转储 (UTF-16LE) 中所示:
4d 00 79 00 20 00 54 00 65 00 78 00 74 00
字节数组的大小取决于您用来表示文本的编码。如果你使用UTF-16,像这样
Encoding.Unicode.GetBytes(string)
你显然得到了相同的 14 个字节。如果您改用UTF-8:
Encoding.UTF8.GetBytes(string)
你得到一个 7 个字节的数组:
4d 79 20 54 65 78 74
这是与ASCII相同的大小(和相同的表示),因为您的示例仅使用 ASCII 字符集中可用的字符。根据定义,所有这些字符在 UTF-8 中都是相同的。
现在,如果您使用非 ASCII 字符,比如日语“日”,则 UTF-8 编码将需要 3 个字节:
e6 97 a5
UTF-16 只需要 2 个字节:
e5 65
尝试将日文字符转换为 ASCII 会产生异常或仅使用“?” 字符,取决于您如何配置Encoding
,因为 ASCII 只能表示 ASCII 字符。
另一个稍微不同的例子,欧洲字符“ä”。UTF-8 中的 2 个字节:
c3 a4
UTF-16 中还有 2 个字节:
e4 00
ASCII 不能代表这个字符。
总而言之,消耗的内存取决于字符串中的实际数据以及用于表示它的编码。
以上所有仅讨论原始数据的内存消耗,请注意,为了计算总内存消耗,您还必须包括作为每个数组和字符串一部分的元数据,例如它的长度,并且,在.net 字符串的情况,也是一个空终止符(2 个附加字节,值为“0”)。元数据的字节数是恒定的并且相对较小,因此字符串和数组之间的任何差异只有在您有大量非常小的文本时才有意义。
两者都非常接近。只有一个真正的答案:
在您的框架/架构上对其进行概要分析。
这里有一篇很好的博客文章,给出了一个字符串占用多少空间的公式,以及与 StringBuilder 和实例分配的各种交互
除非您有多个字符串副本,否则字节数组将占用更少的内存,在这种情况下,由于字符串表,字符串将占用更少的内存。
但真正的问题是,这真的重要吗?将字符串用作字符串而不是将其存储为字节数组有很多好处。
我不知道细节,因为你的问题非常狭窄,但我闻到过早的优化。
字节数组。这会将您的文本存储为 ASCII(每个字符 1 个字节)字符,而 .NET 字符串使用更大的 Unicode。但是请记住,.NET 字符串可能更有用,并且在大型应用程序中,这种差异可能不会产生巨大的差异。
(另请注意,如果您只在 .NET 字符串中使用 ASCII 字符,那么每个字符仍然只有 1 个字节)