强制C#使用ASCII

强制C#使用ASCII,c#,.net,unicode,ascii,C#,.net,Unicode,Ascii,我正在用C#编写一个应用程序,需要从特定的数据文件格式进行读写。目前唯一的问题是该格式使用的是严格的单字节字符,而C#在使用writer和char数组时一直试图使用Unicode(在其他严重问题中,这会使文件大小加倍)。我一直在修改代码,改为使用字节数组,但在将它们输入到树视图和datagrid控件时,会引起一些抱怨,这涉及到转换等 我花了一点时间在谷歌上搜索,似乎没有一个简单的typedef可以用来强制char类型为我的程序使用byte,至少不会造成额外的麻烦 有没有一种简单的方法可以强制C#

我正在用C#编写一个应用程序,需要从特定的数据文件格式进行读写。目前唯一的问题是该格式使用的是严格的单字节字符,而C#在使用writer和char数组时一直试图使用Unicode(在其他严重问题中,这会使文件大小加倍)。我一直在修改代码,改为使用字节数组,但在将它们输入到树视图和datagrid控件时,会引起一些抱怨,这涉及到转换等

我花了一点时间在谷歌上搜索,似乎没有一个简单的typedef可以用来强制
char
类型为我的程序使用byte,至少不会造成额外的麻烦

有没有一种简单的方法可以强制C#程序只使用ASCII而不使用Unicode

后来,我几乎成功了。在BinaryReader/Writer上使用
asciencoding
解决了大部分问题(出现了一些问题,在字符串前面加了一个额外的字符,但我已经解决了)。我还有最后一个问题,非常小,但可能很大:在文件中,当我加载/保存文件时,一个特定字符(打印为欧元符号)被转换为
。这在文本中不是一个很大的问题,但如果它发生在记录长度中,它可能会改变大小千字节(显然不好)。我认为这是由编码引起的,但是如果它来自文件,为什么不返回呢

确切的问题/结果如下:

  • 原始文件:0x80(欧元)

  • 编码: **ASCII:0x3F(?) **UTF8:0xC280(A-hat欧元)


这两种结果都不起作用,因为文件中的任何位置都可能发生变化(如果记录长度int中的80变为3F,则可能是65*(256^3)的差值)。不好的。我尝试使用一种编码,认为这可以很好地解决这个问题,但现在它添加了第二个字符,这更糟糕。

在.NET中,内部字符串始终是Unicode,但这确实不应该引起您的兴趣。如果您有一个需要遵守的特定格式,那么您所走的路线(将其读取为字节)是正确的。您只需使用
System.Encoding.ASCII
类从
string->byte[]
byte[]->string
C#(.NET)进行转换,字符串将始终使用Unicode。这是故意的

但是,在读取或写入文件时,可以使用StreamReader/StreamWriter设置强制ASCII编码,如下所示:

StreamReader reader = new StreamReader (fileStream, new ASCIIEncoding());
然后使用StreamReader阅读

写作也是一样的,只需使用StreamWriter。

如果您想在中使用它,可以使用创建一个支持它的库。F#支持ASCII字符串,基本类型为字节数组,请参阅(MSDN):


如果您的文件格式将单字节字符中的文本与二进制值(如长度、控制字符)混合在一起,那么最好使用的编码是代码页28591又名Latin1又名ISO-8859-1

您可以使用以下任何一种可读性最高的编码:

Encoding.GetEncoding(28591) 
Encoding.GetEncoding("Latin1")
Encoding.GetEncoding("ISO-8859-1")
此编码具有一个有用的特性,即最多255个字节的值被转换为具有相同值的unicode字符(例如,字节0x80变为字符0x0080)


在您的场景中,这可能比ASCII编码(将0x80到0xFF范围内的值转换为“?”)或任何其他常用编码(也将转换此范围内的某些字符)更有用。

好的。我试试看。有一个问题(我以前没有处理过编码,现在还不需要),将单字节字符(读取为字节)转换为双字节字符字符串,显示并允许用户编辑值,然后转换回并再次将其作为单字节字符写入,是否会有任何问题?我知道任何特殊/Unicode字符都会丢失其高位字节,但会/会对来自ASCII文件的字符造成任何损坏吗?我想不出怎么会出错,但有了M$,谁知道呢;P@peachykeen:如果您只是使用StreamReader和StreamWriter进行读写,.NET程序将永远不会知道该文件是ASCII格式的。NET使处理这个问题变得非常、非常简单和健壮。>>…然后再转换回来并将其作为单字节字符写入?取决于字符串在程序中时发生的情况。如果所执行的操作插入了在最终代码页中不可表示的字符,则可能会看到垃圾。所谓的高ASCII字符(>127十进制)会根据活动代码页的不同而变化,但在流处理程序中不一定无效。使用设置为ASCII编码的流会切断2字节字符的额外(第一个)字节,还是将其分成两个?一个简单的转换为字节数组的实验最终给出了两倍的字节,每隔一个通常无法打印。至于手头的问题,程序不需要,格式也不支持VS尝试使用的UTF-16,但在这种情况下,显示上/显示后转换可能会更好,因为某些字段在数据之前包含8字节的标志部分。这应该适用于ASCII读写器,但在代码中使用转换器可能会有所帮助…直接转换到字节数组是错误的b/c UTF-16每个字符使用2个字节。正如你们所看到的,每隔一个字节就有一个无结构。如Reed所述,使用StreamWriter应该为每个字符输出写入一个“正常”字节。ASCII文件中的8字节标志部分对于流处理程序来说只是一个字符。除非您绝对必须以每个字节为基础处理事情,否则请处理字符。您的“字节o’标志”将是一组普通读/写中的“半字符o’标志”。进入这一领域可能很棘手,但应该是可行的。仅供参考,Unicode不是一种编码,它只是一种标准。从技术上讲,ASCII是Unicode的7位编码,只能对前128个码点进行编码。所以
Encoding.GetEncoding(28591) 
Encoding.GetEncoding("Latin1")
Encoding.GetEncoding("ISO-8859-1")