C#BinaryWriter长度前缀-UTF7编码
本文关键字:-UTF7 编码 前缀 C#BinaryWriter | 更新日期: 2023-09-27 18:09:39
我有一个项目,使用内存映射文件让两个应用程序相互共享数据。生产者应用程序是用C#编写的,消费者应用程序讲的是普通的老C。两者都使用VS2010。
MSDN表示,"BinaryWriter.Write方法(字符串("用UTF-7编码的无符号整数对数据进行预处理,然后写入有效负载。这正是我陷入困境的地方。如果我写一个长度为256个字符的字符串,C应用程序的调试器向我显示了这个字节序列:0x80 0x2<有效载荷char>的256倍。将长度前缀转换为我可以在消费者应用程序中安全使用的前缀的最佳方法是什么?
生产者应用程序:
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,Chris
虽然BinaryWriter.Write上的MSDN文档称其"首先将字符串的长度写入UTF-7编码的无符号整数",但这是错误的。首先,UTF-7是编码的字符串,不能使用UTF-7对整数进行编码。文档的意思是(代码也是(,它使用可变长度的7位编码写入长度,有时称为LEB128。在您的特定情况下,数据字节80 02
的含义如下:
1000 0000 0000 0010
Nbbb bbbb Eaaa aaaa
N
设置为1表示这不是最后一个字节E
设置为零意味着这是最后一个字节- CCD_ 6和CCD_;因此结果是:
00000100000000
aaaaaaabbbbbbb
即二进制100000000
,十进制为256。
不管微软文档怎么说,
- 写入的前缀号实际上是LEB128编码的计数
- 这是一个字节计数,而不是字符计数
我链接的Wiki页面提供了解码代码,但我会考虑使用我自己的方案。您可以使用Encoding.GetBytes()
手动将字符串转换为UTF8,并将其写入MMF,在其前面加一个普通的无符号短字符。这样你就可以完全控制一切。