当前位置: 首页 > 编程语言 > C#

在同一个进程中对同一个文件创建2个FileStreams分享

时间:2023-04-10 16:25:12 C#

在同一个进程中对同一个文件创建2个FileStreams我正在尝试创建一个将被自动删除的临时文件。stream=newFileStream(tmpFilePath,FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.ReadWrite,4096,FileOptions.DeleteOnClose|FileOptions.RandomAccess);该文件将由3rd方API使用,该API还将创建一个FileStream:stream=newFileStream(tmpFilePath,FileMode.Open,FileAccess.Read,FileShare.Read);我想我已经尝试了所有可能的标志组合,但我总是得到“该进程无法访问文件'XXX',因为它正在被另一个进程使用......”我做错了什么吗?有办法吗?根据文档,是的。http://msdn.microsoft.com/en-us/library/system.io.fileshare.aspx摘录:阅读:允许随后打开文件进行阅读。如果未指定此标志,则任何打开文件进行读取的请求(通过此进程或其他进程)都将失败,直到文件关闭。但是,即使指定了此标志,仍可能需要额外的权限才能访问该文件。我有完全相同的用例并遇到了同样的问题。我尝试使用(FileShare.ReadWrite|FileShare.Delete)这两个流并且它有效。听起来您可能希望使用内存映射文件作为与多个进程共享单个文件的方式。http://msdn.microsoft.com/en-us/library/system.io.memorymappedfiles.memorymappedfile.aspx问题是您仍然拥有您创建的第一个流。您需要创建文件,然后释放它(关闭流),然后让3rd方API执行它,然后删除文件。将所有这些包装在一个IDispoable的类中可能是一个很好的解决方案;在构造函数中创建和释放文件,包装第三方工作的方法,在处置方法中删除。您可以将现有流传递给第三方Api,或者如果您只想让第三方Api以只读模式传递StreamReader实例,请使用(varstream=newFileStream("trace.txt",FileMode.OpenOrCreate,FileAccess.ReadWrite)){using(varanotherStream=newStreamReader(stream)){//这里很神奇}}只有当第三方API使用FileShare.ReadWrite,或者您的打开使用FileAccess.Read时,此调用序列才会起作用。您正在以读/写方式打开它,同时允许其他人也以读/写方式打开它。第三方代码试图以只读方式打开它,同时允许其他人也可以打开它,但只能以只读方式打开。由于您仍然可以打开进行读写,因此这将失败。假设您无法更改第3方代码,则需要以下模式:按照您当前的方式打开文件,但没有DeleteOnClose标志。写下阅读其他代码所需的任何内容。关闭文件。(可选)使用FileAccess.Read(可能还有DeleteOnClose)重新打开它。调用第三方代码。做你想做的任何其他阅读(但不是写作)。根据我的经验,无论FileShare值如何,您都无法通过将文件路径传递给另一个FileStream来打开使用FileOptions.DeleteOnClose打开的FileStream。当您拥有所有代码(抱歉,显然不是您的情况)时,DuplicateHandle可用于多次deleteOnClose文件,甚至来自不同的进程。下面是.NET4.5.1的一些示例代码。以上就是C#学习教程:在同一个进程中对同一个文件创建2个FileStreams,共享所有内容。如果对大家有用,需要详细了解C#学习教程,希望大家多多关注——usingSystem;使用系统。诊断;使用System.IO;使用System.Runtime.InteropServices;使用系统文本;使用System.Windows.Forms;使用Microsoft.Win32.SafeHandles;命名空间示例{publicstaticclassDuplicatedHandleExample{[DllImport("kernel32.dll")]privatestaticexternboolDuplicateHandle(SafeFileHandlehSourceProcessHandle,IntPtrhSourceHandle,SafeFileHandlehTargetProcessHandle,outSafeFileHandlelpTargetHandle,UInt32dwDesiredAccess,boolbInherit2dwOptions,UInt3);[DllImport("kernel32.dll")]privatestaticexternSafeFileHandleOpenProcess(UInt32dwDesiredAccess,boolbInheritHandle,intdwProcessId);私有常量UInt32PROCESS_DUP_HANDLE=0x0040;私有常量UInt32DUPLICATE_SAME_ACCESS=0x0002;publicstaticvoidCreateFileInProcessA(){try{//使用FileOptions.Delete打开新的临时文件Path=Path.Combine(Path.GetTempPath(),Guid.NewGuid().ToString("D"));using(FileStreamfs=newFileStream(tempFilePath,FileMode.CreateNew,FileAccess.ReadWrite,FileShare.Read|FileShare.Write|FileShare.Delete,4096,FileOptions.DeleteOnClose)){//将消息放入临时文件fs.Write(new[]{(byte)'h',(byte)'i',(byte)'!'},0,3);fs.Flush();//将我们的进程ID和文件句柄放在剪贴板中Clipboard.SetData(DataFormats.UnicodeText,数据);//显示消息框(同时保持文件打开!)并等待用户单击确定}}catch(Exceptionex){MessageBox.Show(ex.ToString());}}publicstaticvoidOpenFileInProcessB(){try{//从剪贴板获取进程ID和文件句柄stringdata=(string)Clipboard.GetData(DataFormats.UnicodeText);string[]dataParts=data.Split(',');intsourceProcessId=int.Parse(dataParts[0]);IntPtrsourceFileHandle=newIntPtr(Int64.Parse(dataParts[1]));//使用(SafeFileHandlesourceProcessHandle=OpenProcess(PROCESS_DUP_HANDLE,false,sourceProcessId))获取目标进程的句柄{//使用(SafeFileHandledestinationProcessHandle=OpenProcess(PROCESS_DUP_HANDLE,false,Process.GetCurrentProcess().Id)){//将句柄复制到我们的进程中SafeFileHandledestinationFileHandle;DuplicateHandle(sourceProcessHandle,sourceFileHandle,destinationProcessHandle,outdestinationFileHandle,0,false,DUPLICATE_SAME_ACCESS);//使用(FileStreamfs=newFileStream(destinationFileHandle,FileAccess.ReadWrite,4096))在其周围获取一个FileStream包装器{//读取文件内容fs.Position=0;字节[]缓冲区=新字节[100];intnumBytes=fs.Read(buffer,0,100);字符串消息=Encoding.ASCII.GetString(缓冲区,0,numBytes);//显示消息框(同时保持文件打开!)并等待用户单击确定}}}}catch(Exceptionex){MessageBox.Show(ex.ToString());}}}}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: