- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我成功地使用了 VirtualFileDataObject code from Delay's blog ,但我想避免将整个文件流式传输到内存中。
我在 Stack Overflow Drag and Drop large virtual files from c# to Windows Explorer 上发现了这个之前回答过的问题matthieu 通过更改 SetData 方法的签名回答了这个问题。
这是我的问题,在更改了 SetData 方法的签名后,其他调用它的地方仍然在寻找旧的签名。
这里是原始的SetData;
public void SetData(short dataFormat, int index, Action<Stream> streamData)
{
_dataObjects.Add(
new DataObject
{
FORMATETC = new FORMATETC
{
cfFormat = dataFormat,
ptd = IntPtr.Zero,
dwAspect = DVASPECT.DVASPECT_CONTENT,
lindex = index,
tymed = TYMED.TYMED_ISTREAM
},
GetData = () =>
{
// Create IStream for data
var ptr = IntPtr.Zero;
var iStream = NativeMethods.CreateStreamOnHGlobal(IntPtr.Zero, true);
if (streamData != null)
{
// Wrap in a .NET-friendly Stream and call provided code to fill it
using (var stream = new IStreamWrapper(iStream))
{
streamData(stream);
}
}
// Return an IntPtr for the IStream
ptr = Marshal.GetComInterfaceForObject(iStream, typeof(IStream));
Marshal.ReleaseComObject(iStream);
return new Tuple<IntPtr, int>(ptr, NativeMethods.S_OK);
},
});
}
matthieu 建议改成;
public void SetData(short dataFormat, int index, Stream stream)
{
...
var iStream = new StreamWrapper(stream);
...
// Ensure the following line is commented out:
//Marshal.ReleaseComObject(iStream);
return new Tuple<IntPtr, int>(ptr, NativeMethods.S_OK);
...
}
在我进行这些更改后,以下调用将不起作用; (这就是我需要帮助的地方)我该如何解决这个电话问题;
foreach (var fileDescriptor in fileDescriptors)
{
**SetData(FILECONTENTS, index, fileDescriptor.StreamContents);**
index++;
}
基本上将“Action streamData”更改为“Stream stream”导致了我的问题。我不确定在进行更改后如何调用它。
所有这些代码都来自 Delays VirtualFileDataObject。我不知道我是否应该把它贴在这里。但是,如果您点击上面的链接,它会将您带到该博客,以便您查看。
我太接近了,只是想不出这最后一步,谢谢你看一看
最佳答案
我遇到了完全相同的问题。这是我为解决此问题所做的工作(正如您所说,其他答案中尚未完全解决)
1) 修改 FileDescriptor
的 StreamContents
属性:
public Action<Stream> StreamContents { get; set; }
为此:
public Func<Stream> StreamContents { get; set; }
(而不是传递客户端可以写入的 Stream
,我们期望一个我们可以从中读取的 Stream
,这正是 Explorer 的工作方式和它所期望的)
2) 从这里修改 SetData
方法重载:
public void SetData(short dataFormat, int index, Action<Stream> streamData)
为此:
public void SetData(short dataFormat, int index, Func<Stream> streamData)
3) 将 SetData
代码的 GetData
lambda 更改为:
GetData = () =>
{
ManagedIStream istream = null;
if (streamData != null)
{
Stream stream = streamData();
if (stream != null)
{
istream = new ManagedIStream(stream);
}
}
IntPtr ptr = istream != null ? Marshal.GetComInterfaceForObject(istream, typeof(IStream)) : IntPtr.Zero;
return new Tuple<IntPtr, int>(ptr, NativeMethods.S_OK);
},
4)在代码中加入这个ManagedIStream
类(也可以完全删除IStreamWrapper
类)
private class ManagedIStream : IStream
{
private Stream _stream;
public ManagedIStream(Stream stream)
{
_stream = stream;
}
public void Clone(out IStream ppstm)
{
throw new NotImplementedException();
}
public void Commit(int grfCommitFlags)
{
throw new NotImplementedException();
}
public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten)
{
throw new NotImplementedException();
}
public void LockRegion(long libOffset, long cb, int dwLockType)
{
throw new NotImplementedException();
}
public void Read(byte[] pv, int cb, IntPtr pcbRead)
{
int read = _stream.Read(pv, 0, cb);
if (pcbRead != IntPtr.Zero)
{
Marshal.WriteInt32(pcbRead, read);
}
}
public void Revert()
{
throw new NotImplementedException();
}
public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition)
{
long newPos = _stream.Seek(dlibMove, (SeekOrigin)dwOrigin);
if (plibNewPosition != IntPtr.Zero)
{
Marshal.WriteInt64(plibNewPosition, newPos);
}
}
public void SetSize(long libNewSize)
{
_stream.SetLength(libNewSize);
}
public void Stat(out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, int grfStatFlag)
{
const int STGTY_STREAM = 2;
pstatstg = new System.Runtime.InteropServices.ComTypes.STATSTG();
pstatstg.type = STGTY_STREAM;
pstatstg.cbSize = _stream.Length;
pstatstg.grfMode = 0;
if (_stream.CanRead && _stream.CanWrite)
{
const int STGM_READWRITE = 0x00000002;
pstatstg.grfMode |= STGM_READWRITE;
return;
}
if (_stream.CanRead)
{
const int STGM_READ = 0x00000000;
pstatstg.grfMode |= STGM_READ;
return;
}
if (_stream.CanWrite)
{
const int STGM_WRITE = 0x00000001;
pstatstg.grfMode |= STGM_WRITE;
return;
}
throw new IOException();
}
public void UnlockRegion(long libOffset, long cb, int dwLockType)
{
throw new NotImplementedException();
}
public void Write(byte[] pv, int cb, IntPtr pcbWritten)
{
_stream.Write(pv, 0, cb);
if (pcbWritten != IntPtr.Zero)
{
Marshal.WriteInt32(pcbWritten, cb);
}
}
}
就是这样。现在您可以像这样使用代码(使用与此处提供的原始文章中相同的示例:http://dlaa.me/blog/post/9913083):
new VirtualFileDataObject.FileDescriptor
{
Name = "Alphabet.txt",
Length = 26,
ChangeTimeUtc = DateTime.Now.AddDays(-1),
StreamContents = () =>
{
var contents = Enumerable.Range('a', 26).Select(i => (byte)i).ToArray();
MemoryStream ms = new MemoryStream(contents); // don't dispose/using here, it would be too early
return ms;
}
};
关于c# - 使用 VirtualFileDataObject 使用 IStream 拖放大型虚拟文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22700195/
我正在尝试弄清楚如何让一个成员变量代表传入的 istream 或类自己创建的成员变量。 我认为,如果我动态分配类创建的 istream,那么使用指向 istream 的指针可能会起作用;然而,问题在于
我正在尝试理解这段代码 istream &read(istream &is, Sales_data &item) { double price = 0; is >> item.b
我编写了一个实现 IStream(COM 接口(interface)而不是 C++ 标准库类)的过滤器。这一切都很好,但我的问题是我不确定何时(如果有的话)我可以确定不会发送进一步的 IStream
我正在测试 C++PL 书中的一段代码并找到了下一段代码(我不想感觉我是在将它从书中复制粘贴到我的 IDE,所以我至少改变了变量名): istream& operator>> (istream& is
我正在阅读 C++ Practical Programming by Example by Andrew Koenig (Author)并在 4.1.3 Reading homework grades
我正在尝试使用 istream& getline 而不是使用 istream& operator 从文件中读取行。 结果cpp #include "Result.h" Result::Result()
我试图通过套接字连接发送图像,但我遇到了以下代码的问题: //stream to char array STATSTG myStreamStats; ULONG bytesSaved; myStrea
这里有两段代码,我起初认为它们应该是等价的: { std::ifstream stream("test.bin", std::ios_base::in | std::ios_base::bin
我在网上查了,但没找到合适的。 怎么可能有这样的主线(原始主线): int main() { Image left; std::ifstream ifs("l
假设我有以下代码: std::ifstream file(name, flags); file.seekg(0, std::ios::beg); // Check for error file.rea
在 Windows 上的 C++ 中,是否有任何简单的方法可以为现有 std::stream 对象创建 (COM) IStream 接口(interface)? 一个示例是使用 IWICStream:
考虑以下简单程序,它将输入拆分为空白并每行打印出一个非空白标记: #include int main(int argc, char* argv[]) { while (std::ci
istream& getline (istream& is, string& str); 此处 str 在换行符后终止。但是,如果我想处理 str cotents 2-3 行的情况,那么还有什么选择呢
这个问题已经有答案了: Java multiple file transfer over socket (3 个回答) 已关闭 5 年前。 我正在编写一个程序在两台计算机之间传输文件,但我没有关闭套接
void transferData(ifstream& input_file, ofstream& output_file) { char ch; while (input_file
我正在读取包含以下行的文本文件: deltaT 0.005; 在字符串中找到正确的行后,我想使用如下代码读出该值: double deltaT;
我正在查看 istream 类,但没有看到可以完全清除缓冲区并将输入设置为为下一个“干净”输入做好准备的方法。 我为我的类定义了提取运算符,在我的主程序中我要求用户输入,如下所示: while (tr
我正在编写一个解析器,之前我在尝试解析标识符(任何对 C++ 变量名有效的东西)和未闭合的字符串文字(任何以 " 开头的东西)时遇到了麻烦,但是在我的输入末尾缺少结束符 ")。我认为这是因为词法分析器
我得到了一个具有以下签名的函数。我无法改变它,我必须接受它。 void parse(std::istream & in); 我应该测试这个函数,所以基本上用预定义的内容调用它并检查值是否被正确解析。因
我的运算符(operator)有问题>> istream& operator>> (istream& is, Matrix& M) { char first; is>>first;
我是一名优秀的程序员,十分优秀!