如何从C#字符串获取以空字符结尾的字符串?

22
  • 我正在与需要 null 终止的字符串进行通信的服务器进行通信
  • 我该如何在 C# 中 巧妙地 实现这一点呢?
4个回答

56

我认为聪明的方法是简单地做。

string str = "An example string" + char.MinValue; // Add null terminator.
然后将其转换为字节以发送到服务器。
byte[] buffer = ASCIIEncoding.ASCII.GetBytes(str);

当然,你使用的编码取决于服务器期望的编码。


8
char.MinValue是C#语言中最佳选择的方式。 - A. M.
2
这是目前我找到的最简单(也是最可靠)的方法。这应该是被接受的答案。 - jhmckimm

16

如果字符串以 null 结尾,我假设你正在实现某种二进制协议。你是否在使用 BinaryWriter?

默认情况下,BinaryWriter 会将字符串作为长度前缀写入。您可以更改此行为:

class MyBinaryWriter : BinaryWriter
{
    private Encoding _encoding = Encoding.Default;

    public override void Write(string value)
    {
        byte[] buffer = _encoding.GetBytes(value);
        Write(buffer);
        Write((byte)0);
    }
}

那么你只需要像这样写任何字符串:

using (MyBinaryWriter writer = new MyBinaryWriter(myStream))
{
    writer.Write("Some string");
}
你可能需要根据你的需求调整_encoding位。
当然,你可以根据需要扩展该类以处理其他数据类型,使你的协议实现保持简洁明了。你可能还需要自己的(非常相似的)BinaryReader

2
我建议使用base.Write(this._encoding.GetBytes(new char[]{ '\u0000'}))来编码null终止符。默认的UTF-16是2个字节,并期望以两个0字节结尾。 - toong
将值与“\0”附加(如果它尚未以此结尾):if (!value.EndsWith("\0")) value += "\0";,从而使解决方案编码无关(您不必担心零的数量)。 - marchewek

7

这些字符串已经以null结尾。虽然字符串本身不包含null字符,但在内存中,null字符始终跟随在字符串后面。

然而,在.NET中,字符串是unicode编码的,因此它们在内存中以UTF-16/UCS-2格式存储,服务器可能期望不同的编码,通常是8位编码。那么你需要将字符串编码为字节数组,并在末尾放置一个零字节:

byte[] data = Encoding.Default.GetBytes(theString);
byte[] zdata = new byte[data.Length + 1];
data.CopyTo(zdata, 0);

在创建时,zdata数组已经填充了所有的零,因此您不必实际将额外的字节设置为零。

7
“Null terminated” 通常指 “以第一个 null 作为结尾”。如果您允许 .NET 字符串包含一个或多个空字符但仍不终止,则不能将 .NET 字符串视为以 null 结尾。 - John Saunders
1
@John:我在第一句话中特别指的是字符串后面已经有一个终止零。如果字符串本身包含空字符,它自然不能正常作为以空字符结尾的字符串,但这是每个答案都共同存在的问题。 - Guffa
4
@Guffa:Jon的页面似乎直接与实际文档相矛盾。我不认为C#字符串真的是以空字符结尾的,只是封送处理过程知道如何以空字符结尾(我也不确定它如何保留嵌入的空字符,或者是否可能)。我不认为C#字符串真的是以空字符结尾的,只是封送处理过程知道如何以空字符结尾(我也不确定它如何保留嵌入的空字符,或者是否可能)。@Guffa说Jon的页面似乎直接与实际文档相矛盾。 - Aaronaught
@Aaronaught:文档仅说明该字符串不使用终止空字符,但并未说明字符数组中字符串后面是否放置了空字符。 - Guffa
@Juliet https://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/language-specification/unsafe-code 说: 通过固定字符串实例生成的 char* 值始终指向以 null 结尾的字符串。在获取指向字符串实例 s 的指针 p 的固定语句中,从 pp + s.Length - 1 的指针值表示字符串中字符的地址,而指针值 p + s.Length 总是指向空字符(值为 '\0' 的字符)。 - T S
显示剩余3条评论

5

你需要在字符串的末尾添加一个空字符。.NET字符串可以包含空字符。


1
我认为他建议使用'char c = new char()',这将创建Unicode点'U+0000'。 - Steve Cooper

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