C# 为什么我在尝试读取要写入的文件时遇到未处理的异常:System.IO.IOException?
我有两个C#应用程序,一个是逐行读取文件(文件a),然后将其内容写入另一个文件(文件B) 第二个应用程序使用FileSystemWatcher for File B查看文件何时更新,并报告程序启动时与文件更改时的行号差异 这就是我现在所要做的,最终我想读取文件上次读取和当前读取之间的行,但直到我可以得到保留的行差 应用程序1的代码是C# 为什么我在尝试读取要写入的文件时遇到未处理的异常:System.IO.IOException?,c#,file,filesystemwatcher,C#,File,Filesystemwatcher,我有两个C#应用程序,一个是逐行读取文件(文件a),然后将其内容写入另一个文件(文件B) 第二个应用程序使用FileSystemWatcher for File B查看文件何时更新,并报告程序启动时与文件更改时的行号差异 这就是我现在所要做的,最终我想读取文件上次读取和当前读取之间的行,但直到我可以得到保留的行差 应用程序1的代码是 static void Main(string[] args) { String line; Stream
static void Main(string[] args)
{
String line;
StreamReader sr = new StreamReader("f:\\watch\\input.txt");
FileStream fs = new FileStream("f:\\watch\\Chat.log", FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
StreamWriter sw = new StreamWriter(fs);
while ((line = sr.ReadLine()) != null)
{
sw.WriteLine(line);
Thread.Sleep(200);
Console.WriteLine(line);
sw.Flush();
}
sw.Close();
sr.Close();
}
应用程序2的代码是
public static int lines = 0;
public static void Main()
{
Run();
}
public static void Run()
{
string[] args = System.Environment.GetCommandLineArgs();
if (args.Length != 2)
{
Console.WriteLine("Usage: Watcher.exe (directory)");
return;
}
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = args[1];
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
watcher.Filter = "Chat.log";
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.EnableRaisingEvents = true;
lines = File.ReadAllLines(args[1] + "\\Chat.log").Length;
Console.WriteLine("File lines: " + lines);
while(Console.Read()!='q');
}
private static void OnChanged(object source, FileSystemEventArgs e)
{
Linework(e.FullPath);
Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType);
}
public static string Linework(string path)
{
string newstring = " ";
using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
int newlines = File.ReadAllLines(path).Length;
Console.WriteLine("Lines now: " + newlines);
}
return newstring;
}
现在,当我尝试同时运行这两个应用程序时,我得到了一个异常:“未处理的异常:System.IO.IOException:进程无法访问该文件,因为它正被另一个进程使用”
我有两个用于读写访问的filestreams设置,一个用于FileAccess.Write,另一个用于FileAccess.Read
有什么线索可以解释为什么我会得到这个异常
谢谢
Hew.提供了两种不获得独占持有权的方法:
FileStream对象将不具有
当您需要时,请独家握住手柄
SafeFileHandle属性为
访问以公开句柄或
FileStream对象被赋予
在其
构造器
文件表明,反过来是正确的:
在不设置SafeFileHandle的情况下打开文件流意味着
FileStream对文件句柄(即
与应该引发的IO异常内联)
input.txt可能无法读取
在第一个应用程序中也使用using
语句而不是Close()(以防引发异常)
否则就可以了。但是,文件共享可能需要额外的权限(实际上不会影响这一点)
我遗漏了一段代码:
int newlines = File.ReadAllLines(path).Length;
将
流
与流读取器
一起使用。在这种情况下,允许对文件进行第二次程序读写访问将起作用
//lines = File.ReadAllLines(args[1] + "\\Chat.log").Length;
//Commenting the above lines as this would again open a new filestream on the chat.log
//without the proper access mode required.
using (FileStream fsReader = new FileStream(args[1] + "\\Chat.log", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
{
using (StreamReader sr = new StreamReader(fsReader))
{
while (sr.ReadLine() != null)
lines++;
}
}
lines=File.ReadAllLines(args[1]+“\Chat.log”).Length
这是你的问题。该方法打开文件,读取所有行,然后再次关闭。它在打开文件FileShare.Read时使用“普通”文件共享设置。拒绝对也打开了文件的任何其他进程的写入访问
这在这里不起作用,您已经用写访问权限打开了文件。第二个过程不能否认它。IOException就是结果
您不能使用File.ReadAllLines(),因为在这里,您需要使用FileShare.ReadWrite打开文件流,将其传递给StreamReader并读取所有行
注意你在这里遇到的非常麻烦的比赛潜力,不能保证你将读到的最后一行是完整的。在行尾仅获取一个\r而不是\n是一个特别棘手的问题。这将随机且不频繁地攻击,这是最难排除的bug。可能是你的Flush()调用修复了它,我从来没有勇气对此进行测试。哪个应用程序出现了错误?FileShare.ReadWrite负责同时打开文件,但这是否也有助于允许同时访问?@apoorv020:是的,即使对于其他进程也是如此。但它可能需要额外的权限。@spinon抱歉,引发异常的应用程序是FileSystemWatcher应用程序(应用程序2)。安全句柄通常通过网络套接字操作或文件映射公开(应用程序中不使用公开文件句柄的代码)。文件在哪里暗示了这一点?报价中暗示了这一点。反过来说,如果既没有访问SafeFileHandle属性来公开句柄,也没有在其构造函数中为fileStream对象提供SafeFileHandle属性,则fileStream对象将对其句柄具有独占性保留。简单的句子演算:句子A:FS将不具有独占性保留。句子B:使用SafeFileHandle。您使用了
(B=>A)
和(~B=>~A)
,这是不等价的(B=>A)
和(~A=>~B)
是等价的。原来的一句话相当于:如果使用了SafeFileHandle,FS将不具有独占性。因此,等价的反向含义是:(不使用SafeFileHandle)当(FS具有独占持有)时,这与:(如果FS具有独占持有),(不使用SafeFileHandle)等价。这意味着你答案中的句子不正确!底线-文本允许FS即使在不使用SafeHandle的情况下也不具有独占性保留。感谢使用“using”的提示,我将应用程序更改为这样做。权限应该可以,因为我可以打开input.txt。我正在以对系统的完全访问权限运行。对于input.txt
,我的意思是如果没有共享,其他进程无法打开它。+1令人印象深刻。我看到了一些类似的东西,但无法用语言表达。其他答案中已经有了。至于阅读,你是对的。他可以使用一个命名的互斥来轻松解决这个问题。此外,他并不真正阅读这些行(如其内容),只是对它们进行计数。谢谢你,汉斯,我尝试使用Streamreader,它确实起了作用,但我认为阅读每一行来计算要比较的总行数是低效的。我打算这样做,因为我一直在研究如何删除SafeFileHandles,但这似乎不是一个选项。非常感谢。它与File.ReadAllLines()一样有效。没有办法提高效率,只有一种方法可以在引擎盖下读取文本文件。无论如何,文件数据应该从文件系统缓存中出来。+1正是OP所需要的。而不是args[1]+“\\Chat.log”
他将使用path
s
//lines = File.ReadAllLines(args[1] + "\\Chat.log").Length;
//Commenting the above lines as this would again open a new filestream on the chat.log
//without the proper access mode required.
using (FileStream fsReader = new FileStream(args[1] + "\\Chat.log", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
{
using (StreamReader sr = new StreamReader(fsReader))
{
while (sr.ReadLine() != null)
lines++;
}
}