2013-04-16 42 views
5

我有一个项目使用内存映射文件让两个应用程序彼此共享数据。 生产者应用程序是用C#编写的,消费者应用程序使用简单的老C语言。两者都使用VS2010。C#BinaryWriter长度前缀 - UTF7编码

MSDN说“BinaryWriter.Write方法(字符串)”用UTF-7编码的无符号整数前置数据,然后写入有效载荷。这正是我卡住的地方。如果我写了一个长度为256个字符的字符串 ,则C应用程序的调试器会显示此字节序列:0x80 0x2 <有效负载字符数的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, 克里斯

+0

'0x80 0x02'是无符号整数... –

+0

是的,几乎忘了;)如果<127个字节被写入,则长度前缀恰好是具有该值的第一个字节。否则,前两个字节似乎表示有效载荷长度,但我无法弄清楚如何使用它们 - 请参阅我的文章中的解释文字。 – user2286339

回答

6

尽管微软文档中说什么,

  1. 写入的前缀号码是在fa ct an LEB128 encoded count
  2. 这是一个字节数,不是个字符数。

我链接的Wiki页面为您提供解码代码,但是我会考虑使用我自己的方案。您可以使用Encoding.GetBytes()手动将字符串转换为UTF8,然后将其写入MMF,并用正常的无符号短格作为前缀。这样你就可以完全控制一切。

+0

我会按照你的建议去做,并组成我自己的字节/字符/任何计数功能,并将其用作我的前缀。问候,克里斯 – user2286339

6

尽管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。

+0

马修是快一点。感谢彻底的解释! – user2286339