.NET 4.0中是否支持ISO_IR 58?

4
在DICOM中,有一个双字节字符集名为ISO_IR 58。据我所知,在.Net中其等效编码为gb2312。我正在尝试将ISO_IR 58字符进行7位ASCII编码,以便在医疗系统之间进行通信。在Java世界中,字符串gb2312可用于进行此编码。首先看一下ISO_IR 87的示例(ISO_IR 87等于.Net中的iso-2022-jp)。
Encoding enc = Encoding.GetEncoding("iso-2022-jp");
byte[] bytes = enc.GetBytes("叙収參参^去厰厦厘=却占^卮博南");
string asciistring = ASCIIEncoding.ASCII.GetString(bytes);

这段代码将输入字符串转换为ASCII字符串:$B=v<}RT;2(B^$B5nRRRONR(B=$B5Q@j(B^$BRHGnFn(B

所有适当的转义序列都已包含,可以正确使用。

(实际的第一个转义字符在此处不显示,但粘贴后其余序列会显示)

如果我使用来自ISR_IR 58的字符,则使用此代码:

Encoding enc = Encoding.GetEncoding("gb2312");
byte[] bytes = enc.GetBytes("ㄆㄉㄊㄋ^ㄌㄍㄐㄓ^ㄖㄠㄢㄤ");
string asciistring = ASCIIEncoding.ASCII.GetString(bytes);

我只得到了字符串:????????^????????^????????

那么,在使用.Net时,DICOM ISO_IR 58编码的答案是什么?我是否使用了错误的编码字符串?在.Net中不支持DICOM中的ISO_IR 58吗?.Net中是否存在漏洞?这是否可能实现?


你是如何检查生成的 asciistring 的?在调试中,保存到文本文件、屏幕上等等?当你使用Java并获得正确的结果时,你是在同一台电脑上使用吗? - Racil Hilan
@Ulugbek 我不是Java开发人员,我使用.Net。但是在我的工作中,我们的产品是用Java构建的。我使用.Net进行测试。我将要求提供正确编码为ISO_IR 58的Java等效代码,并在此处添加它。我真的很感兴趣这个答案,因为我在.Net中似乎无论做什么都不起作用,而Clear Canvas似乎没有支持DICOM标准中仅限于特定字符集的原因。 https://raw.githubusercontent.com/ClearCanvas/ClearCanvas/master/Dicom/SpecificCharacterSetParser.cs - Jake
@ Racil Hilan,情况比那更加复杂,我正在使用Clear Canvas DICOM工具包执行DICOM C-Finds,并在Windows表单上显示接收到的信息结果数据网格。例如,请参见:https://github.com/ClearCanvas/ClearCanvas/issues/147 - Jake
我最终想要实现的是在.Net中是否可能实现这一点,如果可能的话,我想亲自编写并提交给Clear Canvas以支持该字符集,并回馈这个绝对惊人的开源代码库。 - Jake
1
但是Java返回的字符串不是7位ASCII码,而是8位字符串。要获得这样的输出,您需要执行string asciistring = Encoding.GetEncoding("iso-8859-1").GetString(bytes); - Ulugbek Umirov
显示剩余3条评论
2个回答

5

ASCIIEncoding是一种7位编码,任何8位编码都无法用它表示。因此会出现问号。

这适用于所有字符集:

Encoding enc = Encoding.GetEncoding("gb2312");
byte[] bytes = enc.GetBytes("ㄆㄉㄊㄋ^ㄌㄍㄐㄓ^ㄖㄠㄢㄤ");

Encoding asc = Encoding.GetEncoding("iso-8859-1");
string astr = asc.GetString(bytes);

输出

A8 C6 A8 C9 A8 CA A8 CB 5E A8 CC A8 CD A8 D0 A8 D3 5E A8 D6 A8 E0 A8 E2 A8 E4 
¨Æ¨É¨Ê¨Ë^¨Ì¨Í¨Ð¨Ó^¨Ö¨à¨â¨ä

确实非常好的观点。让我错过它的原因是他的第��个示例起作用了,但现在我在思考它时,尽管 iso-2022-jp 是8位的,但它被设计成能够在7位中编码而不失真(根据Wikipedia)。 我使用以下编码测试了您的代码:gb2312ISO-IR-58GB18030GB_2312-80。 它们都返回了与您答案中完全相同的结果。 - Racil Hilan

3

对编码进行一些研究,根据IANA的说法,ISO-IR-58映射到GB_2312-80而不是GB2312,在.Net Framework中映射到x-cp20936并使用代码页20936。如果是这种情况,您需要使用:

Encoding.GetEncoding("x-cp20936");

或者

Encoding.GetEncoding(20936);

当然,两者都是相同的,所以你可以选择使用名称或代码页。

您提到Java与GB2312很好地配合,您认为这是ISO-IR-58的正确映射。现在,这真的很有趣。有趣的是,根据DICOM(此链接为MS Word文档),ISO_IR 58被映射到IANA ISO-2022-CN。这与IANA所说的相冲突,那么我们该相信谁呢?好吧,我们以上面的IAIA为准,希望这对您有用,但现在让我们遵循DICOM并看看它会去哪里。可悲的是,在.Net中没有ISO-2022-CN编码,因此我们需要进行更多的研究。

根据WikipediaISO-2022-CN编码可以以以下任一方式开始:

ESC $ ) A 可以切换到 GB 2312-1980(每个字符占2个字节)[指定为G1]
ESC $ ) G 可以切换到 CNS 11643-1992 Plane 1(每个字符占2个字节)[指定为G1]
ESC $ * H 可以切换到 CNS 11643-1992 Plane 2(每个字符占2个字节)

你提到Java返回的正确字符串以ESC $ ) A开头,因此我们将遵循第一种选项,这会引导我们到GB2312的维基百科页面,这是你认为正确的编码。现在有几个重要的事情需要在此页面上观察:

  • 它以GB2312(1980)开头。等等,这是GB_2312-80编码的实际含义吗?如果是,那么我们又回到了IANA在第一次告诉我们的内容,上述提到的代码就是正确的。

  • 然后它继续说已被GBK和GB18030所取代。 .Net Framework没有GBK编码,但它有GB18030,代码页为54936。我不认为这是你应该使用的,但如果其他编码无法正常工作,它值得一试。

  • 然后,如果您滚动到GB2312的两个实现标题,您可以看到以下文本:

截至2015年,Microsoft .Net Framework正在使用Implementation A。iconv-1.14、php-5.6、ActivePerl-5.20、Java 1.7和Python 3.4正在使用Implementation B.[2] Ruby 2.2与Implementation A和Implementation B兼容,它会内部将冲突字符转换为Implementation A。你读懂了吗?我再重复一遍:.Net Framework正在使用Implementation A,而Java正在使用Implementation B。

我尝试了x-cp20936和GB18030,但它们都不能正确工作。 - Jake
我发现了一件有趣的事情。尽管我在答案中引用的 Microsoft 页面没有提到,但它实际上支持 ISO-IR-58 编码。哇!我检查了它的 WebName,它实际上返回了 GB2312。因此,ISO-IR-58 实际上被映射到 GB2312。请参见我的评论以获取更多测试结果。 - Racil Hilan
Java和.NET只在它们如何将GB 2312的点映射到Unicode上有所不同(它们都使用某种EUC-CN来表示“gb2312”),而ISO-2022和EUC-CN之间的区别在于它们如何将GB 2312的行列位置编码为字节。 - Mingye Wang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接