【问题标题】:C# BinaryWriter length prefix - UTF7 encodingC# BinaryWriter 长度前缀 - UTF7 编码
【发布时间】:2013-04-08 21:02:49
【问题描述】:

我有一个项目使用内存映射文件让两个应用程序相互共享数据。 生产者应用程序是用 C# 编写的,消费者应用程序使用普通的旧 C。两者都使用 VS2010。

MSDN 说“BinaryWriter.Write 方法(字符串)”在数据前面加上一个 UTF-7 编码的无符号整数,然后写入有效负载。这正是我卡住的地方。如果我写 一个长度为 256 个字符的字符串,C 应用程序的调试器向我显示了这个字节序列:0x80 0x2 。将长度前缀转换为我可以在消费者应用程序中安全使用的内容的最佳方法是什么?

生产者应用:

using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Threading;
using System.Text;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        using (MemoryMappedFile mmf_read = MemoryMappedFile.CreateNew("mappedview", 4096))
        {
            using (MemoryMappedViewStream stream = mmf_read.CreateViewStream())
            {
                string str;
                BinaryWriter writer = new BinaryWriter(stream);

                str = string.Join("", Enumerable.Repeat("x", 256));

                writer.Write(str);
            }
        }
    }
}

消费者应用:

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#pragma comment(lib, "user32.lib")

#define BUF_SIZE 4096
TCHAR szName[]=TEXT("Global\\mappedview");


int _tmain()
{
    HANDLE hMapFile;
    LPCSTR pBuf;

    hMapFile = OpenFileMapping(
               FILE_MAP_ALL_ACCESS,         // read/write access
               FALSE,                       // do not inherit the name
               szName);                     // name of mapping object

    if (hMapFile == NULL)
    {
        _tprintf(TEXT("Could not open file mapping object (%d).\n"),
         GetLastError());
        return 1;
    }

    pBuf = (LPCSTR) MapViewOfFile(hMapFile,     // handle to map object
           FILE_MAP_ALL_ACCESS,             // read/write permission
           0,
           0,
           BUF_SIZE);

    if (pBuf == NULL)
    {
        _tprintf(TEXT("Could not map view of file (%d).\n"),
                GetLastError());

        CloseHandle(hMapFile);
        return 1;
    }

    printf("Proc1: %s\n\n", pBuf);              // print mapped data

    UnmapViewOfFile(pBuf);

    CloseHandle(hMapFile);

    return 0;
}

br, 克里斯

【问题讨论】:

  • 0x80 0x02 是无符号整数...
  • 是的,差点忘了 ;) 如果写入

标签: c#


【解决方案1】:

不管微软文档怎么说,

  1. 所写的前缀号实际上是LEB128 encoded count
  2. 这是字节数,不是字符数。

我链接的 Wiki 页面为您提供了解码代码,但我会考虑使用我自己的方案。您可以使用 Encoding.GetBytes() 手动将字符串转换为 UTF8 并将其写入 MMF,并在其前面加上一个普通的无符号短字符。这样您就可以完全控制一切。

【讨论】:

  • 我会按照你的建议做,并组成我自己的 byte/char/whatever 计数函数并将其用作我的前缀。问候,克里斯
【解决方案2】:

虽然MSDN Documentation on BinaryWriter.Write 声明它“首先将字符串的长度写入为 UTF-7 编码的无符号整数”,但这是错误的。首先,UTF-7 是一种字符串编码,你不能用UTF-7 编码整数。文档的含义(以及代码的作用)是它使用可变长度的 7 位编码(有时称为LEB128)来写入长度。在您的具体情况下,数据字节 80 02 的含义如下:

1000 0000 0000 0010

Nbbb bbbb Eaaa aaaa

  • N 设置为 1 表示这不是最后一个字节
  • E 设置为零表示这是最后一个字节
  • aaaaaaabbbbbbb是真实数据;因此结果是:

00000100000000

aaaaaaabbbbbbb

即二进制100000000,十进制为256。

【讨论】:

  • Matthew 的速度有点快。感谢您的详尽解释!
猜你喜欢
  • 1970-01-01
  • 2012-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-12
  • 1970-01-01
  • 2017-01-23
  • 1970-01-01
相关资源
最近更新 更多