6

2 つのアプリが互いにデータを共有できるようにするために、メモリ マップ ファイルを使用するプロジェクトがあります。プロデューサー アプリは C# で記述され、コンシューマー アプリは単純な古い C を使用します。どちらも VS2010 を使用します。

MSDN によると、「BinaryWriter.Write Method(String)」は 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、クリス

4

2 に答える 2

8

BinaryWriter.Writeに関する MSDN ドキュメントには、「最初に文字列の長さを UTF-7 でエンコードされた符号なし整数として書き込む」と記載されていますが、これは誤りです。まず、UTF-7 は文字列エンコーディングです。UTF-7 を使用して整数をエンコードすることはできません。ドキュメントが意味すること(およびコードが意味すること) は、 LEB128として知られる可変長 7 ビット エンコーディングを使用して長さを書き込むことです。特定のケースでは、データバイト80 02は次のことを意味します。

1000 0000 0000 0010

Nbbb bbbb Eaaa aaaa

  • N1 に設定すると、これが最終バイトではないことを意味します
  • Eゼロに設定すると、これが最終バイトであることを意味します
  • aaaaaaabbbbbbbは実際のデータです。したがって、結果は次のようになります。

00000100000000

aaaaaaabbbbbbb

つまり100000000、バイナリでは 10 進数で 256 です。

于 2013-04-16T12:58:10.917 に答える
8

Microsoft のドキュメントに記載されている内容にもかかわらず、

  1. 書き込まれたプレフィックス番号は、実際にはLEB128 でエンコードされたカウントです。
  2. これはバイト数であり、文字数ではありません。

リンクした Wiki ページにはデコード コードが記載されていますが、独自のスキームを使用することを検討します。手動で文字列を UTF8 に変換し、Encoding.GetBytes()それを MMF に書き込んで、通常の署名なしの短い文字列を前に付けることができます。そうすれば、すべてを完全に制御できます。

于 2013-04-16T12:54:58.033 に答える