c# - 在字符串中使用二进制数据时数据是不是“丢失”?
Posted
技术标签:
【中文标题】c# - 在字符串中使用二进制数据时数据是不是“丢失”?【英文标题】:c# - Is data "lost" when using binary data in a string?c# - 在字符串中使用二进制数据时数据是否“丢失”? 【发布时间】:2010-09-19 13:05:51 【问题描述】:我尝试使用返回字符串的StreamReader
类'ReadToEnd()
方法读取 JPG 文件。
但由于某种原因,当我将此字符串写入文件时,它并没有打开。
将数据读入字符串时会丢失一些东西吗?
【问题讨论】:
【参考方案1】:字符串默认使用 Unicode 编码,unicode 使用 NUL 字符作为控制字符,双 NUL 用于终止,单 NUL 用于表示它之前的 ASCII 字符。
因为这个原因,二进制数据不能加载到字符串中。
【讨论】:
【参考方案2】:我注意到没有人回答实际问题。
将数据读入字符串时是否丢失了什么?
JPEG 文件包含图片而不是文字。该图片具有作为字节序列的二进制表示。其中一些字节的值 0x00 也表示为 NUL。在字符串中,包含此值的字节被解释为标记字符串的结尾。超过字符串末尾的数据被视为未使用的缓冲区并被忽略。
当您将字符串写入文件时,不会包含第一个 NUL 之后的内容。因此,该文件不是完整的二进制图像,并被试图将其解释为 JPEG 的软件的验证逻辑拒绝。
因此,当您加载包含非文本数据的字符串时,数据通常会丢失。这里的问题是你实际上做了一个无效的类型转换,但是编译器和运行时都没有阻止你,结果是数据损坏。
它到底有什么用处?
几件事。正如其他人所说,字符串旨在包含文本。在 .NET 中,字符串支持普通旧 ASCII 以外的编码。还广泛支持文本操作。在帮助中查找格式说明符,了解字符串操作的精彩示例。
为什么 C# 字符串使用 NUL 作为字符串结尾?
这是一个遗留问题。 NUL 对其他任何事情都没有多大好处,这样做可以简化将字符串编组进出托管代码的过程。 BSTR 出于同样的原因做同样的事情。
【讨论】:
我意识到在 C/C++ 中 NUL 字符 (0x00) 是字符串的结尾。但是,在 .Net 中,字符串是更复杂的对象。除了具体的实现细节,还有什么原因导致字符串不能包含 NUL 字符。【参考方案3】:永远记住,文本数据 是 二进制数据但二进制数据 不是 文本数据。
【讨论】:
【参考方案4】:正如所有真正的程序员所知道的,唯一有用的数据结构是数组。字符串、列表、结构、集合——这些都是数组的特殊情况,可以很容易地以这种方式处理,而不会因各种复杂情况而弄乱你的编程语言。花哨的数据类型最糟糕的是你必须声明它们,而众所周知,真正的编程语言具有基于(六个字符)变量名的第一个字母的隐式类型。
此外,坚定的Real Programmer可以用任何语言编写Fortran程序。
显然,修改此内容的人要么没有幽默感,要么不了解民间传说。以上内容摘自泰克公司的 Ed Post 于 1983 年致 Datamation 编辑的一封非常著名的信。这封信的标题是Real Programmers Don't Use Pascal。
【讨论】:
【参考方案5】:字符串用于表示文本。他们擅长表示文本。非常好,事实上,因为它们支持 Unicode 并保护您免受各种典型的字符串处理错误。
它们不擅长表示二进制数据,因为这不是它们的设计目的。正如您所提到的,字节数组对此要好得多。
这不是一个比另一个更好的问题,它只是适合目标和了解何时选择一个或另一个。文本 = 字符串,二进制 = 字节数组或流。
【讨论】:
【参考方案6】:字符串用于文本数据。它们不适用于二进制数据 - 如果您以这种方式使用它们,您将丢失数据(如果幸运的话,您可以使用一些不会丢失数据的编码,但存在一些微妙的问题仍然让它成为一个非常糟糕的主意。)
如果您实际上是在处理一个文件,阅读整个文件的最简单方法是调用File.ReadAllBytes。如果您必须处理任意流,请查看"Creating a byte array from a stream"。
【讨论】:
【参考方案7】:不幸的是,System.IO 命名空间中的类名存在严重问题。 StreamReader 旨在从文本文件读取\写入。您应该按照@goodwill 的建议对二进制文件使用 FileStream
【讨论】:
【参考方案8】:String 是为保存 unicode 字符而设计的;不是二进制的。对于二进制,使用byte[]
或Stream
。或Image
等,用于更专业的图像处理。
尽管有这个名字,StreamReader
实际上是一个专门的TextReader
- 即它是一个从Stream
读取的TextReader
。图片不是文字,所以这不是正确的选择。
【讨论】:
【参考方案9】:你不能这样做......改用 FileStream。
您不能使用字符串来读取二进制文件,据我所知,有些字符不会出现。
【讨论】:
以上是关于c# - 在字符串中使用二进制数据时数据是不是“丢失”?的主要内容,如果未能解决你的问题,请参考以下文章
使用 C#,将包含二进制数据的字符串转换为字节数组的最有效方法是啥
在 c# / ReadAsync 中读取二进制数据而不是读取计数中指定的所有内容
java中for多次嵌套循环丢数据,丢数据,丢数据,逻辑没问题!