15

我有一个从外部实体接收到的字节数组。它是一个固定大小。字节包含一个 unicode 字符串,用 0 值填充缓冲区的其余部分:

所以字节可能是:

H \0 E \0 L \0 L \0 \0 \0 \0 \0 \0 ... etc 

我正在获取该缓冲区并将其转换为如下字符串:

byte[] buffer = new byte[buffSize];
m_dataStream.Read(buffer, 0, buffSize);
String cmd = System.Text.Encoding.Unicode.GetString(buffer);

我得到的是一个看起来像这样的字符串:

"HELLO\0\0\0\0\0\0\0\0..."

如何告诉 GetString 在第一个 Unicode null 处终止字符串(即,我只返回“HELLO”)?

感谢您的任何意见。

4

4 回答 4

15

如果你确定其余的都是 \0,这会起作用:

cmd = cmd.TrimEnd('\0');

否则,如果您只想在第一个 null 之前获取所有内容:

int index = cmd.IndexOf('\0');
if (index >= 0)
   cmd = cmd.Remove(index);

请注意,这Unicode.GetString将处理双 \0。你应该只寻找一个\0。

于 2009-05-14T16:11:47.160 回答
3

对于 UTF8/ASCII 编码,您可以通过查找缓冲区中第一次出现的空终止符(使用System.Array.IndexOf)来实现此目的,而无需重新处理字符串。然后,您可以使用重载System.Text.Encoding.Unicode.GetString方法创建一个字符串,直到给定缓冲区大小。

下面的示例还适用于不包含空字节的缓冲区:

byte[] buffer = new byte[buffSize];
m_dataStream.Read(buffer, 0, buffSize);
var size = System.Array.IndexOf(buffer, (byte)0);
String cmd = System.Text.Encoding.Unicode.GetString(buffer, 0, size < 0 ? buffSize : size);

对于 UTF16,您可以使用带有 for 循环的类似方法(寻找第一对空字符 ... 例如if (buffer[i] == (byte)0 && buffer[i] == buffer[i+1]).

如果创建临时字符串无关紧要,那么接受的答案是最好的解决方案。

于 2018-03-23T10:07:10.643 回答
2

如前所述,最简单的方法是在转换后修剪字符串。

如果您事先知道字符数,则可以使用 GetString 重载,该重载采用起始索引和字节数,以获得正确的字符串,而无需修剪。

如果您事先不知道字符数,并且想避免事后修剪字符串,则需要先修剪字节数组,因此您只传递您感兴趣的字节。对于 Unicode,这意味着删除任何字节在并包括第一对零之后。

于 2009-05-14T16:15:42.643 回答
-1

您可以从 Stream.Read() 中获取长度。在这种情况下,流中的 \0 将不被计算在内,您将获得 5 的长度。然后您可以使用 Encoding.UTF8.GetString 按长度修剪字符串。

int length = peerStream.Read(buffer, 0, buffer.Length);
receive = Encoding.UTF8.GetString(buffer, 0, length);
于 2021-05-25T12:02:28.483 回答