无法访问该文件,因为它正在被使用
Cannot acces the file because it is being used
我需要使用 FileSystemWatcher 将操作从 dir1 同步到 dir2。当我在 dir1 中创建一个新文件时,相同的文件必须在 dir2 中,如果我 delete/rename/move,在 dir2 中也应该。
当我在 dir1 中创建文件时,它也在 dir2 中创建,但是当我尝试在 dir1 中重命名文件时,出现此异常:未处理的异常。 System.IO.IOException: 进程无法访问文件 'C:\Users\artio\Desktop\FASassignment\root\dir1\g.txt' 因为它正被另一个进程使用。 正如我在谷歌上搜索的那样,这个错误可能会出现,因为流没有关闭,但我没有知道我是否和一个人一起工作。另外,当我在其中创建一个子文件夹和一个文件时,我收到一条错误消息,指出找不到路径并且在 dir2 中它没有创建,你能帮我解决这两个错误吗?提前致谢!
程序:
public class Program2
{
public static void Main(string[] args)
{
string sourcePath = @"C:\Users\artio\Desktop\FASassignment\root\dir1";
string destinationPath = @"C:\Users\artio\Desktop\FASassignment\root\dir2";
var source = new DirectoryInfo(sourcePath);
var destination = new DirectoryInfo(destinationPath);
using var sourceWatcher = new FileSystemWatcher(sourcePath);
sourceWatcher.NotifyFilter = NotifyFilters.Attributes
| NotifyFilters.CreationTime
| NotifyFilters.DirectoryName
| NotifyFilters.FileName
| NotifyFilters.LastAccess
| NotifyFilters.LastWrite
| NotifyFilters.Security
| NotifyFilters.Size;
sourceWatcher.Changed += OnChanged;
sourceWatcher.Created += OnCreated;
sourceWatcher.Deleted += OnDeleted;
sourceWatcher.Renamed += OnRenamed;
sourceWatcher.Error += OnError;
sourceWatcher.Filter = "*.txt";
sourceWatcher.IncludeSubdirectories = true;
sourceWatcher.EnableRaisingEvents = true;
Console.WriteLine("Press enter to exit.");
Console.ReadLine();
}
private static void OnChanged(object sender, FileSystemEventArgs e)
{
if (e.ChangeType != WatcherChangeTypes.Changed)
{
return;
}
Console.WriteLine($"Changed: {e.FullPath}");
}
private static void OnCreated(object sender, FileSystemEventArgs e)
{
string value = $"Created: {e.FullPath}";
string destinationPath = @"C:\Users\artio\Desktop\FASassignment\root\dir2";
var name = e.Name;
var fullPath = e.FullPath;
string destination = Path.Combine(destinationPath, name);
File.Copy(fullPath, destination,true);
Console.WriteLine(value);
}
private static void OnDeleted(object sender, FileSystemEventArgs e)
{
Console.WriteLine($"Deleted: {e.FullPath}");
var name = e.Name;
string destinationPath = @"C:\Users\artio\Desktop\FASassignment\root\dir2";
string destination = Path.Combine(destinationPath, name);
File.Delete(destination);
}
private static void OnRenamed(object sender, RenamedEventArgs e)
{
var oldFullPath = e.OldFullPath;
var fullPath = e?.FullPath;
Console.WriteLine($"Renamed:");
Console.WriteLine($" Old: {e.OldFullPath}");
Console.WriteLine($" New: {e.FullPath}");
string destinationPath = @"C:\Users\artio\Desktop\FASassignment\root\dir2";
string destination = Path.Combine(destinationPath, fullPath);
File.Copy(fullPath, destination, true);
File.Delete(oldFullPath);
}
private static void OnError(object sender, ErrorEventArgs e) =>
PrintException(e.GetException());
private static void PrintException(Exception? ex)
{
if (ex != null)
{
Console.WriteLine($"Message: {ex.Message}");
Console.WriteLine("Stacktrace:");
Console.WriteLine(ex.StackTrace);
Console.WriteLine();
PrintException(ex.InnerException);
}
}
}
你的问题是这一行:
string destination = Path.Combine(destinationPath, fullPath);
调试一下,你会发现这并不是你想的那样。您正在尝试合并两个完整路径。
改为使用:
private void OnRenamed(object sender, RenamedEventArgs e)
{
Console.WriteLine($"Renamed:");
Console.WriteLine($" Old: {e.OldFullPath}");
Console.WriteLine($" New: {e.FullPath}");
var oldFileName = Path.GetFileName(e.OldFullPath);
var newFileName = Path.GetFileName(e.FullPath);
var oldDestinationPath = Path.Combine(Destination, oldFileName);
var newDestinationPath = Path.Combine(Destination, newFileName);
var info = new FileInfo(oldDestinationPath);
info.MoveTo(newDestinationPath);
}
注意我没有使用 File
class。众所周知,这是有问题的。
此外,我建议使用某种进程日志并重试,以便您可以恢复。否则,这可能会留下很多更改,因为文件可能会保留它们,这可能会导致您的操作失败。
更新:
关于您关于其他文件的其他问题,看起来您正试图在创建文件的进程释放其句柄之前访问该文件,因此您可以尝试引入一秒左右的小延迟:
private void OnCreated(object sender, FileSystemEventArgs e)
{
var name = e.Name;
var fullPath = e.FullPath;
string destination = Path.Combine(Destination, name);
Console.WriteLine($"Copy to: {destination}");
Thread.Sleep(1000); //Intentional delay
File.Copy(fullPath, destination, true);
Console.WriteLine("File copied successfully.");
}
我需要使用 FileSystemWatcher 将操作从 dir1 同步到 dir2。当我在 dir1 中创建一个新文件时,相同的文件必须在 dir2 中,如果我 delete/rename/move,在 dir2 中也应该。
当我在 dir1 中创建文件时,它也在 dir2 中创建,但是当我尝试在 dir1 中重命名文件时,出现此异常:未处理的异常。 System.IO.IOException: 进程无法访问文件 'C:\Users\artio\Desktop\FASassignment\root\dir1\g.txt' 因为它正被另一个进程使用。 正如我在谷歌上搜索的那样,这个错误可能会出现,因为流没有关闭,但我没有知道我是否和一个人一起工作。另外,当我在其中创建一个子文件夹和一个文件时,我收到一条错误消息,指出找不到路径并且在 dir2 中它没有创建,你能帮我解决这两个错误吗?提前致谢!
程序:
public class Program2
{
public static void Main(string[] args)
{
string sourcePath = @"C:\Users\artio\Desktop\FASassignment\root\dir1";
string destinationPath = @"C:\Users\artio\Desktop\FASassignment\root\dir2";
var source = new DirectoryInfo(sourcePath);
var destination = new DirectoryInfo(destinationPath);
using var sourceWatcher = new FileSystemWatcher(sourcePath);
sourceWatcher.NotifyFilter = NotifyFilters.Attributes
| NotifyFilters.CreationTime
| NotifyFilters.DirectoryName
| NotifyFilters.FileName
| NotifyFilters.LastAccess
| NotifyFilters.LastWrite
| NotifyFilters.Security
| NotifyFilters.Size;
sourceWatcher.Changed += OnChanged;
sourceWatcher.Created += OnCreated;
sourceWatcher.Deleted += OnDeleted;
sourceWatcher.Renamed += OnRenamed;
sourceWatcher.Error += OnError;
sourceWatcher.Filter = "*.txt";
sourceWatcher.IncludeSubdirectories = true;
sourceWatcher.EnableRaisingEvents = true;
Console.WriteLine("Press enter to exit.");
Console.ReadLine();
}
private static void OnChanged(object sender, FileSystemEventArgs e)
{
if (e.ChangeType != WatcherChangeTypes.Changed)
{
return;
}
Console.WriteLine($"Changed: {e.FullPath}");
}
private static void OnCreated(object sender, FileSystemEventArgs e)
{
string value = $"Created: {e.FullPath}";
string destinationPath = @"C:\Users\artio\Desktop\FASassignment\root\dir2";
var name = e.Name;
var fullPath = e.FullPath;
string destination = Path.Combine(destinationPath, name);
File.Copy(fullPath, destination,true);
Console.WriteLine(value);
}
private static void OnDeleted(object sender, FileSystemEventArgs e)
{
Console.WriteLine($"Deleted: {e.FullPath}");
var name = e.Name;
string destinationPath = @"C:\Users\artio\Desktop\FASassignment\root\dir2";
string destination = Path.Combine(destinationPath, name);
File.Delete(destination);
}
private static void OnRenamed(object sender, RenamedEventArgs e)
{
var oldFullPath = e.OldFullPath;
var fullPath = e?.FullPath;
Console.WriteLine($"Renamed:");
Console.WriteLine($" Old: {e.OldFullPath}");
Console.WriteLine($" New: {e.FullPath}");
string destinationPath = @"C:\Users\artio\Desktop\FASassignment\root\dir2";
string destination = Path.Combine(destinationPath, fullPath);
File.Copy(fullPath, destination, true);
File.Delete(oldFullPath);
}
private static void OnError(object sender, ErrorEventArgs e) =>
PrintException(e.GetException());
private static void PrintException(Exception? ex)
{
if (ex != null)
{
Console.WriteLine($"Message: {ex.Message}");
Console.WriteLine("Stacktrace:");
Console.WriteLine(ex.StackTrace);
Console.WriteLine();
PrintException(ex.InnerException);
}
}
}
你的问题是这一行:
string destination = Path.Combine(destinationPath, fullPath);
调试一下,你会发现这并不是你想的那样。您正在尝试合并两个完整路径。
改为使用:
private void OnRenamed(object sender, RenamedEventArgs e)
{
Console.WriteLine($"Renamed:");
Console.WriteLine($" Old: {e.OldFullPath}");
Console.WriteLine($" New: {e.FullPath}");
var oldFileName = Path.GetFileName(e.OldFullPath);
var newFileName = Path.GetFileName(e.FullPath);
var oldDestinationPath = Path.Combine(Destination, oldFileName);
var newDestinationPath = Path.Combine(Destination, newFileName);
var info = new FileInfo(oldDestinationPath);
info.MoveTo(newDestinationPath);
}
注意我没有使用 File
class。众所周知,这是有问题的。
此外,我建议使用某种进程日志并重试,以便您可以恢复。否则,这可能会留下很多更改,因为文件可能会保留它们,这可能会导致您的操作失败。
更新:
关于您关于其他文件的其他问题,看起来您正试图在创建文件的进程释放其句柄之前访问该文件,因此您可以尝试引入一秒左右的小延迟:
private void OnCreated(object sender, FileSystemEventArgs e)
{
var name = e.Name;
var fullPath = e.FullPath;
string destination = Path.Combine(Destination, name);
Console.WriteLine($"Copy to: {destination}");
Thread.Sleep(1000); //Intentional delay
File.Copy(fullPath, destination, true);
Console.WriteLine("File copied successfully.");
}