获取编码创建的字节数的最有效方法是什么?

时间:2012-09-26 07:00:06

标签: c# .net encoding

我需要通过TCP发送字节缓冲区。我需要一种有效地确定通过编码类似字符串创建的字节数的方法。

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

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

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

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

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

1 个答案:

答案 0 :(得分:0)

我同意Joachim的看法,你似乎在尝试过早地优化你的程序,而没有任何证据表明你需要首先进行分析。伟大的唐纳德克努特说“过早优化是所有邪恶的根源” - 把它放在心上。

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

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

另一个问题是,与C以null结尾的字符串不同,.NET字符串具有固定长度并且缺少终止符(.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 )
}

当然这段代码会有自己的问题。但你应该明白这一点。