C#中文字符显示为乱码

用C#编写了一个DICOM医学图像接收程序,当发送患者列表中登记的姓名是拼音时,接收到的姓名正常显示(也是拼音),但如果发送患者列表中登记的是中文名时,显示为乱码。如姓名:伍海文,显示为:浼嶆捣鏂?(这个乱码是我从数据库中复制出来的)。在网上搜了许多编码格式转换的代码,均没有用。
另外,从发送端设置里查到,那边DICOM图像编码格式是ISO_IR 192,(网上搜了一下,DICOM默认编码格式是ISO_IR 100)但我无论怎么转换都没效果,可能操作不对吧。
我的代码如下(只列出了姓名获取的代码):

 class PatientInfo
 //患者姓名
        public string patName
        {
            get;
            set;
        }
 PatientInfo.patName = Ddataset.Get(DicomTag.PatientName, "NONAME").Replace("\0", "");

运行下来,这个PatientInfo.patName始终是乱码。
请问,如何对PatientInfo.patName进行转换而正常显示中文名,需要代码。

“Devil组”引证GPT后的撰写:

  • 问题就是涉及到字符编码的转换问题,因为中文字符在不同的编码格式下,对应的二进制数值是不同的,如果在接收端和发送端的编码格式不一致,就有可能导致中文字符乱码的情况。
  • 从DICOM协议的规范上看,DICOM中使用的字符编码格式是多种多样的,包括ISO_IR 100、ISO_IR 192等等,这些编码格式都是通过DICOM标签来指定的。
  • 在C#中,可以使用System.Text.Encoding类来进行字符编码的转换。

根据你提供的信息,试以下的代码:

//获取DICOM标签中的患者姓名
string nameInDicom = Ddataset.Get<string>(DicomTag.PatientName, "NONAME").Replace("\0", "");

//将DICOM中的姓名字符串按照指定的编码格式解码为字节数组
byte[] nameBytes = System.Text.Encoding.GetEncoding("ISO_IR 192").GetBytes(nameInDicom);

//将字节数组按照指定的编码格式转换为字符串
string nameInChinese = System.Text.Encoding.UTF8.GetString(nameBytes);

//将最终的中文姓名赋值给PatientInfo对象
PatientInfo.patName = nameInChinese;

先将DICOM标签中获取的患者姓名字符串nameInDicom按照ISO_IR 192编码格式转换为字节数组nameBytes,然后再将nameBytes按照UTF-8编码格式转换为中文字符串nameInChinese。最后将nameInChinese赋值给PatientInfo对象的patName属性即可。

  • 需要注意的是,如果发送端和接收端的字符编码格式不一致,那么在将DICOM中的字符串解码为字节数组时,需要使用发送端指定的编码格式。如果发送端指定的编码格式是ISO_IR 192,那么在接收端解码时也应该使用相同的编码格式。如果不确定发送端使用的编码格式,可以先尝试使用不同的编码格式进行解码,并观察结果是否正确。

参考chatGPT的回答和自己的思路,根据你提供的信息,乱码的出现可能是由于编码问题引起的。DICOM标准规定使用ISO 2022字符集,而ISO_IR 192代表使用GBK编码字符集。因此,在获取患者姓名时,你需要将其从GBK编码转换为Unicode编码,以确保正确显示中文姓名。可以尝试以下代码:

using System.Text;

...

string patName = Ddataset.Get<string>(DicomTag.PatientName, "NONAME").Replace("\0", "");
byte[] gbkBytes = Encoding.GetEncoding("GBK").GetBytes(patName);
string unicodeName = Encoding.Unicode.GetString(gbkBytes);

其中,首先使用GBK编码将患者姓名转换为字节数组,然后再使用Unicode编码将其转换为字符串,从而确保正确显示中文姓名。
回答不易,还请采纳!!!

参考GPT和自己的思路:出现中文字符乱码的原因可能是编码格式不一致或者没有正确地解析DICOM文件中的编码格式。首先,您需要确认DICOM文件中的编码格式是什么。在这种情况下,您提到的编码格式是ISO_IR 192。

根据DICOM标准,ISO_IR 192表示Unicode字符集。因此,您需要使用Unicode编码来正确地解析中文字符。下面是一个示例代码,演示如何正确地解析DICOM文件中的Unicode编码字符串。

using System.Text;
using Dicom;

// ...

DicomEncoding.RegisterEncoding(Encoding.GetEncoding("ISO-IR 192"));

// ...

string patientName = Ddataset.Get<string>(DicomTag.PatientName, "NONAME");
patientName = Encoding.GetEncoding("ISO-IR 192").GetString(Encoding.UTF8.GetBytes(patientName));


这段代码首先将ISO_IR 192编码格式注册到DICOM编码表中,然后使用DICOM库中的Get方法获取患者姓名,并将其转换为字节数组。最后,使用Encoding类将字节数组转换为Unicode编码字符串。

请注意,如果DICOM文件中使用的编码格式不是ISO_IR 192,您需要相应地更改编码格式的名称。

试试使用 System.Text.Encoding 类的 GetEncoding 方法来指定GBK编码方式进行解码


using System.Text;
...
PatientInfo.patName = Ddataset.Get<string>(DicomTag.PatientName, "NONAME").Replace("\0", "");
PatientInfo.patName = Encoding.GetEncoding("GBK").GetString(Encoding.Default.GetBytes(PatientInfo.patName));

修改Dicom的字符集(0008,0005标签,名字叫SpecificCharacterSet),把该值改成支持中文的即可,如GB1830、ISO_IR 192。
参考:https://blog.csdn.net/weixin_43533308/article/details/123978001

使用CB18030

可参考该实例思路:DICOM乱码问题,链接:https://blog.csdn.net/m0_37460012/article/details/89671606?spm=1001.2101.3001.6650.8&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EESLANDING%7Edefault-8-89671606-blog-123978001.pc_relevant_landingrelevant&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EESLANDING%7Edefault-8-89671606-blog-123978001.pc_relevant_landingrelevant&utm_relevant_index=15

试一下 GB18030 解析
解决DicomTag中文乱码的编码解析对照表

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
在处理中文字符时,需要注意以下几点:

  1. 确认接收到的字符编码格式,是否为发送端设置的ISO_IR 192格式。

  2. 将接收到的字符进行正确的解码。

  3. 在显示字符时,确保使用的字体支持相应的中文字符集。

下面是一个简单的代码示例,用于处理DICOM编码格式为ISO_IR 192的中文字符:

//获取患者姓名
string patname = Ddataset.GetString(DicomTag.PatientName, "NONAME");

//将ISO_IR 192编码格式转换为Unicode格式
string decoded = Encoding.GetEncoding("iso-ir-192").GetString(Encoding.Default.GetBytes(patname));

//设置字体支持的字符集
Font font = new Font("Arial", 12, FontStyle.Regular, GraphicsUnit.Pixel, 0, false);
FontFamily fontFamily = new FontFamily("Arial");
StringFormat stringFormat = new StringFormat(StringFormat.GenericTypographic);
stringFormat.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;

//在界面上显示中文字符
Graphics graphics = this.CreateGraphics();
SizeF sizeF = graphics.MeasureString(decoded, font, new SizeF(100, 100), stringFormat);
graphics.DrawString(decoded, font, new SolidBrush(Color.Black), new PointF(50, 50), stringFormat);

在上述代码中,我们首先获取到患者姓名,接着将其解码为Unicode格式,最后使用指定的字体和字符集在界面上显示中文字符。

需要注意的是,有些DICOM编码格式可能不支持中文字符集,这时候需要将编码格式转换为支持中文字符集的编码格式,例如UTF-8格式。同时,还需要确保在接收、处理和显示中文字符时使用相同的字符编码格式和字符集,避免发生乱码问题。
如果我的回答解决了您的问题,请采纳!