3

最初に何かを明確にするためだけに。バイト配列を単一の文字列に変換しようとはしていません。バイト配列を文字列配列に変換しようとしています。

GetClipboardDataAPIを使用してクリップボードからデータをフェッチし、メモリからデータをバイト配列としてコピーしています。複数のファイル(したがってCF_HDROPクリップボード形式)をコピーする場合、このバイト配列をコピーされたファイルの文字列配列に変換したいと思います。

これが私のこれまでのコードです。

//Get pointer to clipboard data in the selected format
var clipboardDataPointer = GetClipboardData(format);

//Do a bunch of crap necessary to copy the data from the memory
//the above pointer points at to a place we can access it.
var length = GlobalSize(clipboardDataPointer);
var @lock = GlobalLock(clipboardDataPointer);

//Init a buffer which will contain the clipboard data
var buffer = new byte[(int)length];

//Copy clipboard data to buffer
Marshal.Copy(@lock, buffer, 0, (int)length);

GlobalUnlock(clipboardDataPointer);

snapshot.InsertData(format, buffer);

さて、これが後でバッファデータを読み取るための私のコードです。

var formatter = new BinaryFormatter();
using (var serializedData = new MemoryStream(buffer))
{
    paths = (string[]) formatter.Deserialize(serializedData);
}

これは機能せず、ストリームにバイナリヘッダーが含まれていないという例外を除いてクラッシュします。これは、どのタイプにデシリアライズするかがわからないためだと思います。

Marshalクラスを調べてみました。関連性はないようです。

4

2 に答える 2

2

データが Win32 API 経由で取得された場合、文字列配列は、最後に二重の null ターミネータが付いた、null で終わる文字列のシーケンスになります。(文字列は UTF-16 なので、 1 文字につき2バイトであることに注意してください)。基本的に、文字列を一度に 1 つずつ配列に引き出す必要があります。

ここで探しているメソッドは です。これはで動作するため、Marshal.PtrToStringUni代わりに使用する必要があります。あなたから最初のヌル文字までの文字列を抽出し、それを文字列にコピーします。Marshal.CopyIntPtrIntPtr

アイデアは、単一の文字列を継続的に抽出IntPtrし、バッファがなくなるまで、null バイトを超えて次の文字列の先頭に進めることです。私はこれをテストしていませんが、おそらく改善される可能性があります(特に、バッファの終わりを検出するよりスマートな方法があると思います)が、基本的な考え方は次のとおりです。

var myptr = GetClipboardData(format);
var length = GlobalSize(myptr);

var result = new List<string>();

var pos = 0;
while ( pos < length )
{
    var str = Marshal.PtrToStringUni(myptr);
    var count = Encoding.Unicode.GetByteCount(str);

    myptr = IntPtr.Add(myptr, count + 1);
    pos += count + 1;

    result.Add(str);
}

return result.ToArray();

(ちなみに、デシリアライゼーションが機能しない理由は、シリアライズがstring[]文字をバイトとして書き出すだけでなく、.NET が長さのように使用する追加の内部ビットを含む文字列配列の構造を書き出すためです。および型情報を含むバイナリ ヘッダー.クリップボードから返されるものには、その存在がまったくないため、逆シリアル化できません。)

于 2012-07-25T19:33:54.093 に答える
1

これはどう:

var strings = Encoding.Unicode
    .GetString(buffer)
    .Split(new[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
于 2012-07-25T19:55:52.100 に答える