关于c#:c# – 在字符串中使用二进制数据时数据是否“丢失”?

c# - Is data “lost” when using binary data in a string?

我尝试使用返回字符串的StreamReader类'ReadToEnd()方法读取JPG文件。

但出于某种原因,当我把这个字符串写到一个文件中时,它就不会打开。

将数据读取到字符串时是否丢失了某些内容?


字符串用于文本数据。它们不适用于二进制数据——如果您这样使用它们,将丢失数据(您可以使用一些编码,如果幸运的话,不会丢失数据,但仍有一些微妙的问题使它成为一个非常糟糕的主意。)

如果您实际处理的是一个文件,那么读取整个文件的最简单方法就是调用file.readallbytes。如果必须处理任意流,请看一下"从流创建字节数组"。


始终记住,文本数据是二进制数据,但二进制数据不是文本数据。


正如所有真正的程序员所知,唯一有用的数据结构是数组。字符串、列表、结构、集合——这些都是数组的特殊情况,可以很容易地用这种方式处理,而不会使您的编程语言陷入各种复杂的情况。对于花哨的数据类型,最糟糕的是必须声明它们,而真正的编程语言,如我们所知,都有基于(六个字符)变量名的第一个字母的隐式类型。

此外,确定的真正的程序员可以用任何语言编写Fortran程序。

任何人把这一点弄清楚,要么没有幽默感,要么不懂民俗学。以上内容摘自泰克公司的Ed Post于1983年写给《数据编辑》的一封非常著名的信。这封信的标题是"真正的程序员不使用帕斯卡"。


字符串用于保存Unicode字符,而不是二进制字符。对于二进制文件,使用byte[]Stream。或者使用Image等进行更专业的图像处理。

尽管有这个名字,但StreamReader实际上是一个专门的TextReader,即从Stream中读取的TextReader。图像不是文本,因此这不是正确的选项。


不幸的是,System.IO命名空间中的类名存在严重问题。streamreader设计用于读取写入到文本文件。您应该按照@goodwill的建议对二进制文件使用filestream。


字符串默认使用Unicode编码,Unicode使用nul字符作为控制字符,双nul用于终止,单nul用于表示前面的ASCII字符。

因此二进制数据不能加载到字符串中。


我注意到没有人回答过实际的问题。

将数据读取到字符串时是否丢失了某些内容?

jpeg文件包含图片而不是文字。这个双精度有一个字节序列的二进制表示。其中一些字节的值0x00也表示为nul。在字符串中,包含此值的字节被解释为标记字符串的结尾。超过字符串结尾的数据将被视为未使用的缓冲区并被忽略。

将字符串写入文件时,不包括第一个nul之后的任何内容。因此,该文件不是完整的二进制图像,并且被试图将其解释为jpeg的软件验证逻辑拒绝。

因此,当您使用非文本数据加载字符串时,数据通常会丢失。这里的问题是,您已经有效地进行了无效的类型转换,但是编译器和运行时都没有阻止您,结果是数据损坏。

它真正有什么用?

有几件事。正如其他人所说,字符串被设计为包含文本。在.NET中,字符串支持纯旧ASCII以外的编码。对文本操作也有广泛的支持。在帮助中查找格式说明符,以获得字符串操作的壮观示例。

为什么C字符串使用nul作为字符串结尾?

这是个遗产。nul对其他任何东西都没有多大好处,这样做可以简化托管代码内外的字符串编组。BSTR做同样的事情也是出于同样的原因。


字符串用于表示文本。他们善于表现文字。事实上,非常好,因为它们支持Unicode并保护您免受各种典型的字符串处理错误的影响。

他们不擅长表示二进制数据,因为这不是他们设计的目的。正如您所提到的,字节数组更适合于此。

这不是一个比另一个更好的问题,它只是为了达到目的和理解什么时候选择一个或另一个。文本=字符串,二进制=字节数组或流。


你不能这样做….改用文件流。

你不能用字符串来读取二进制文件,据我所知,有些字符是行不通的。