0

我需要一个通过 TCP 发送的字节缓冲区。我需要一种有效地确定通过对字符串等内容进行编码而创建的字节数的方法。

如果我只是使用此代码,则无需这样做。

byte[] buffer = encoder.GetBytes("Hello Client!");
clientStream.Write(buffer, 0 , buffer.Length);

但问题是,我将一个接一个地发送多条消息,并且每次我想发送消息时,这段代码都会为字节缓冲区分配内存。我的理解是他的效率低/慢,因为它每次都分配内存。

我想要做的只是创建一个大字节缓冲区,并将我所有的消息写入其中,并仅发送包含消息的数组的一部分。但我找不到有效地做到这一点的方法。ASCII.Encoding.Getbytes(string) 只会返回字节数组并将其放入我的大字节缓冲区,从位置 0 开始。我需要将消息字节的长度放入字节缓冲区,而无需调用 getbytes (string).Length,因为这又对其进行了编码,效率低下。

可能有一些我找不到的明显解决方案。

4

1 回答 1

0

我同意 Joachim 的观点,因为您似乎试图在没有任何证据(例如分析数据)表明您首先需要这样做的情况下过早地优化您的程序。伟大的 Donald Knuth 说过“过早的优化是万恶之源”——牢记在心。

除此之外,第二个问题是分配不是一项昂贵的操作。一般来说,分配在 O(1) 时间内完成。实际的编码操作要贵很多倍。

第三,是的,您的问题有解决方案;但我不明白这一点,因为给定编码的字符串所需的字节数是不可预测的,这就是为什么(默认情况下)Encoding子类可以自由分配和返回它们自己的缓冲区,因为这意味着你永远不需要如果您的初始调用提供的缓冲区大小不足,请再次使用更大的缓冲区调用该方法。

另一个问题是,.NET 字符串与 C 中以空字符结尾的字符串不同,它具有固定长度并且缺少终止符(.NET 字符串中可以包含空字符,而 C 字符串则不能)。因此,您可能需要在每次使用缓冲区时清除它,这会进一步减慢您的程序:

您需要使用两种方法:Encoding.GetBytesCount(String)Encoding.GetBytes(String, Int32, Int32, Byte[], Int32 ),如下所示:

Encoding encoder = ...
Byte[] buffer = new Byte[1024]; // allocating a 1KB-sized buffer which it is hoped is large enough for every possible string

foreach(String str in stringsToEncode) {
    buffer.Initialize(); // reset every byte to zero (your program may need this, or it may not; I don't know enough about it).

    Int32 bytesWritten;
    do {
        try {
            bytesWritten = encoder.GetBytes( str, 0, str.Length, buffer, 0 );
        } catch(ArgumentException) {
            bytesWritten = Int32.MaxValue;
            buffer = new Byte[ buffer.Length * 2 ];
        }
    }
    while( bytesWritten == Int32.MaxValue )
}

Of course this code is going to have problems of its own. But you should get the idea.

于 2012-09-26T07:28:51.343 回答