【问题标题】:getting a string from a []byte in C#从 C# 中的 []byte 获取字符串
【发布时间】:2009-05-14 20:37:54
【问题描述】:

我有一个奇怪的问题。 我有一个带有标签的表单,用于在程序中的某些点输出文本,而不是控制台输出。 给定以下代码:

result = SetupDiGetDeviceRegistryProperty(deviceInfoSet, ref tBuff, 
                                          (uint)SPDRP.DEVICEDESC,
                                          out RegType, ptrBuf, 
                                          buffersize, out RequiredSize); 

if (!result)
{
    errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message;
    statusLabel.Text += "\nSetupDiGetDeviceRegistryProperty failed because "
                        + errorMessage.ToString();
}
else
{
    statusLabel.Text += "\nPtr buffer length is: " + ptrBuf.Length.ToString();

    sw.WriteLine(tCode.GetString(ptrBuf) );

    sw.WriteLine("\n");
    // This is the only encoding that will give any legible output.
    // Others only show the first character "U"
    string tmp = tCode.GetString(ptrBuf) + "\n"; 

    statusLabel.Text += "\nDevice is: " + tmp + ".\n";                    
}

我只得到标签上的一个硬件 ID 输出。这段代码在我循环的末尾。一开始,这让我觉得我的循环有点悬,但是当我决定将输出直接输出到一个文件时,我几乎得到了我想要的和循环外的输出。 谁能告诉我这里发生了什么? 我想要的只是从 []byte (ptrBuf) 中获取表示硬件 ID 的字符串。 请有人解释一下这里发生了什么? 我的工作环境是 MSVstudio 2008 express。在 Windows 7 中。

谢谢

【问题讨论】:

  • 如果你在硬件 ID 之后,你不应该传递 SPDRP_HARDWAREID 而不是 SPDRP_DEVICEDESC 吗?

标签: c# .net usb


【解决方案1】:

很遗憾,您还没有显示tCode 是什么。

查看docs for the API call,它看起来应该填充了 REG_SZ。我怀疑那是Unicode,即

string property = Encoding.Unicode.GetString(ptrBuf, 0, RequiredSize);

应该转换它。

但是,如果您期望多个值,我想知道它是否是 '\0' 分隔的字符串:尝试在 Win32 控件中输出它确实会在第一个 '\0' 处停止。

试试这个:

string property = Encoding.Unicode.GetString(ptrBuf, 0, RequiredSize);
                                  .Replace('\0', ' ');

这应该(如果我没猜错的话)用空格分隔值。

【讨论】:

  • 如果打算传递 SPDRP_HARDWAREID 而不是 SPDRP_DEVICEDESC,那么这肯定是正确的,因为该属性是“REG_MULTI_SZ”。
  • 是的,这很有意义。
  • 我现在只为有同样问题的人提及这一点。问题是 Win32 控件确实停止在第一个 '\0' 因此我在文本文件中获得完整输出的原因。
【解决方案2】:

你需要指定一个编码:

// C# to convert a byte array to a string.
byte [] dBytes = ...
string str;
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
str = enc.GetString(dBytes);

【讨论】:

  • 如果 ASCII 确实是正确的编码(我怀疑不是),使用 Encoding.ASCII 比创建新实例更简单。
  • +1 对此评论,完全正确。顺便说一句,这对于框架开发人员来说是完全令人困惑和奇怪的选择。您不会期望名为 *Encoding 的对象能够解码。你会认为它是数组的一个属性。哦,好吧,它有效。
  • 对我来说很有意义。如果您喜欢冗长的名称,我想您可以将其称为 ByteEncodingManager 或其他名称。
  • @Serapth:不,我根本没想到会这样。 Encoding 负责编码和解码,在字符数据和二进制数据之间进行转换。我当然不希望数组知道如何做到这一点。我们也不知道这行得通...
  • @Jon。我想这是假设我们不同意的地方。我将编码和解码视为完全独立的任务,并将编码器视为仅负责编码过程。我想我同意数组,进一步思考,如果我是框架设计师,我会把功能放在 System.Convert
【解决方案3】:

对不起,我应该说。 UnicodeEncoding tCode = new UnicodeEncoding(); 并且感谢 skeet,我不知道关于 Win32 控件的小信息。我会努力纠正这一点。 我并没有暗中尝试将字节转换为字符(或字符串)。以后我会努力做到更详细的。

感谢大家的回复。

【讨论】:

    【解决方案4】:

    您不能将字节隐式转换为字符串。您必须为转换选择一种编码方法(可能是 Unicode 或 ASCII)。一个字节存储一个可以表示一个字符(或一些其他数据)的数值,但本质上并不意味着什么。它在哲学上相当于将整数转换为字符串。您可以决定对该值进行直接转换,也可以从该值中得出一些含义(即使用 ASCII 表:13 = TAB)。

    您列出的函数返回的值很可能返回了一个表示某个字符串值的字节数组,但是您需要找到相关的编码方法将其转换为可用的字符串。

    希望有所帮助!

    埃里克

    【讨论】:

      猜你喜欢
      • 2020-01-01
      • 1970-01-01
      • 2011-05-25
      • 2012-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多