【问题标题】:How to determine how many bytes a BinaryWriter would take to write into memory?如何确定 BinaryWriter 写入内存需要多少字节?
【发布时间】:2020-11-25 01:00:50
【问题描述】:

我红色:How many bytes will a string take up?How to know the size of the string in bytes? 以及其他一些,但我无法计算出使用 BinaryWriter 而不是 MemoryMappedViewStream 而不是 MemoryMappedFile 的字符串将进入内存的确切字节数。

有时取的长度是字符串 lenght + 1,有时是字符串 lenght + 2 ???

我都试过了:

  • System.Text.ASCIIEncoding.Default.GetByteCount(str)
  • System.Text.ASCIIEncoding.Unicode.GetByteCount(str)

但它们都不起作用。我尝试了字符串长度加上一个固定的数量,但它也不起作用。

如果我检查之前和之后的 BinaryWriter.BaseStream.Position 之间的差异,那么我无法找到一种方法来确定为字符串写入的确切字节数(之后的位置 - 之前的位置)。听起来好像有对齐或其他我无法弄清楚的东西?

如何每次写入合适的字节数?

更新

我现在使用Encoding.UTF8.GetByteCount(str) + 1;,它在大多数情况下给我的尺寸几乎是正确的,但并非总是如此。

【问题讨论】:

  • 拥有长度后打算如何处理?
  • 好的,如果有的话,你认为这些数字中的哪一个是正确的?
  • 2 个进程通信(一个应用程序和一个记录器应用程序)。主要是单向的。我想在添加附加消息之前验证共享内存是否未满。如果是这样,如果读取器(日志)已经读取了我要写入的内存,我将翻转(从头开始)。但我需要验证我是否有足够的空间来编写消息。我可以通过 char 使用 2 个字节来近似,但为什么不干净地做这件事并获得实际数量?

标签: c# string memory size binarywriter


【解决方案1】:

我根据https://referencesource.microsoft.com/#mscorlib/system/io/binarywriter.cs,08f2e8c389fd32df的Microsoft BinaryWriter源代码找到了我的答案

注意:字符串的长度写在字符串之前,并以 7 位编码,其中大小可能因字符串大小而异(>= 128、>=2^14、> 2^21)。

代码:

    public static int GetBinaryWriterSizeRequired(this string str, Encoding encoding)
    {
        encoding = encoding ?? Encoding.Default;

        int byteCount = encoding.GetByteCount(str);
        int byteCountRequiredToWriteTheSize = 1;

        // EO: This code is based on the Microsoft Source Code of the BinaryWriter at:
        // https://referencesource.microsoft.com/#mscorlib/system/io/binarywriter.cs,2daa1d14ff1877bd
        uint v = (uint)byteCount;   // support negative numbers
        while (v >= 0x80)
        {
            v >>= 7;
            byteCountRequiredToWriteTheSize++;
        }

        return byteCountRequiredToWriteTheSize + byteCount;
    }

电话:

...
_writer = new BinaryWriter(_stream);
_writerEncoding = _writer.GetPrivateFieldValue<Encoding>("_encoding");
...
int sizeRequired = name.GetBinaryWriterSizeRequired(_writerEncoding);

其他(我知道我们不应该调用私有字段,但我做到了):

public static T GetPrivateFieldValue<T>(this object obj, string propName)
{
    if (obj == null)
        throw new ArgumentNullException("obj");

    Type t = obj.GetType();
    FieldInfo fi = null;
    while (fi == null && t != null)
    {
        fi = t.GetField(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
        t = t.BaseType;
    }

    if (fi == null)
        throw new ArgumentOutOfRangeException("propName", string.Format("Field {0} was not found in Type {1}", propName, obj.GetType().FullName));

    return (T)fi.GetValue(obj);
}

仅供参考,这些都是不好的:

return Encoding.UTF8.GetByteCount(str) + 1;
return System.Text.ASCIIEncoding.Default.GetByteCount(str) + 1; //  sizeof(int); // sizeof int to keep the size
return System.Text.ASCIIEncoding.Unicode.GetByteCount(str) + sizeof(int); // sizeof int to keep the size

【讨论】:

    猜你喜欢
    • 2017-08-12
    • 1970-01-01
    • 1970-01-01
    • 2012-06-03
    • 1970-01-01
    • 2020-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多