1
如果系统剪贴板上有大量文本(例如150MB文本文件),我希望能够以Unicode文本的形式从流中读取系统剪贴板,例如避免OutOfMemoryException。这是否可以通过调整下面的pinvoke例子来完成?将系统剪贴板作为流而不是字符串读取
对于这些非常大的剪贴板,Clipboard.GetText(TextDataFormat.UnicodeText)将返回一个空字符串而不会引发异常。
或者,如果我使用的PInvoke像从这里的例子中,我会得到一个OutOfMemoryException http://komalmangal.blogspot.ca/2016/04/how-to-get-clipboard-data-and-its-size.html
[DllImport("user32.dll")]
static extern IntPtr GetClipboardData(uint uFormat);
[DllImport("user32.dll")]
static extern bool IsClipboardFormatAvailable(uint format);
[DllImport("user32.dll", SetLastError = true)]
static extern bool OpenClipboard(IntPtr hWndNewOwner);
[DllImport("user32.dll", SetLastError = true)]
static extern bool CloseClipboard();
[DllImport("kernel32.dll")]
static extern IntPtr GlobalLock(IntPtr hMem);
[DllImport("kernel32.dll")]
static extern bool GlobalUnlock(IntPtr hMem);
const uint CF_UNICODETEXT = 13;
public static string GetText()
{
if (!IsClipboardFormatAvailable(CF_UNICODETEXT))
return null;
if (!OpenClipboard(IntPtr.Zero))
return null;
string data = null;
var hGlobal = GetClipboardData(CF_UNICODETEXT);
if (hGlobal != IntPtr.Zero)
{
var lpwcstr = GlobalLock(hGlobal);
if (lpwcstr != IntPtr.Zero)
{
data = Marshal.PtrToStringUni(lpwcstr);
GlobalUnlock(lpwcstr);
}
}
CloseClipboard();
return data;
}
您选择了文件并复制或打开,然后选择所有文本,然后复制? –
作为测试我在Notepad ++中打开一个大文件并选择全部然后复制,但实际上,剪贴板可能来自其他地方,例如SQL Server Management Studio。 – tjsmith
150Mb(在ANSI或UTF8中)为unicode〜=> 300Mb的内存。所以你最终会得到300M(剪贴板)+ 300M(你的.NET字符串)=> 600M的进程内存,流或不流。内存不足可能会发生在剪贴板中的大量信息中。除非你想用剪贴板内容做别的事情,比如直接将它保存为一个文件,而不是将它实现为一个字符串。这样做会导致潜在的记忆问题。 –