文件存在却提示找不到:.txt/.doc正常但.jpg/.png异常求助
问题:图片文件触发“文件找不到”异常的原因与解决方法
代码示例
public void OnCreated(object sender, FileSystemEventArgs file) { Console.WriteLine("created called"); string[] files = Directory.GetFiles($"{textBox2.Text}", file.Name); if (files.Length > 0) { if (trueFalse == "true") { if (!File.Exists(Path.Combine($"C:\\Users\\{Environment.UserName}\\OneDrive", file.Name))) { File.Copy(files[0], Path.Combine($"C:\\Users\\{Environment.UserName}\\OneDrive", file.Name)); } else { Console.WriteLine("File already exists"); } } if (!File.Exists(Path.Combine(textBox3.Text, file.Name))) { File.Move(files[0], Path.Combine(textBox3.Text, file.Name)); } else { Console.WriteLine("File already exists"); } } else { Console.WriteLine($"File {file.Name} not found in directory {textBox2.Text}."); } }
异常现象
测试时发现,.txt、.doc、.docx文件可正常完成复制和移动操作,但.jpg、.png文件会进入else分支,提示文件找不到,尽管文件实际存在。
异常原因
- 文件写入时序不匹配:
FileSystemWatcher的Created事件会在文件开始创建时立即触发,而非文件完全写入磁盘后。图片文件体积通常比文本、文档类文件大,写入磁盘需要更长时间,此时调用Directory.GetFiles时,文件还未完全落地,导致检索不到。而小体积文件写入快,事件触发时文件已经存在,所以能正常检索。 - 潜在的文件名大小写问题:部分文件系统(如Linux环境)对文件名大小写敏感,若实际文件名与
file.Name返回的大小写不一致,可能导致Directory.GetFiles匹配失败(Windows默认不敏感,但特殊配置下也可能出现),不过这不是该场景下的核心原因。
解决方法
1. 利用事件自带的完整路径,避免重复检索
FileSystemEventArgs的FullPath属性已经包含了文件的完整路径,无需通过Directory.GetFiles查找,直接使用该路径更可靠:
public void OnCreated(object sender, FileSystemEventArgs file) { Console.WriteLine("created called"); string sourceFile = file.FullPath; if (File.Exists(sourceFile)) { if (trueFalse == "true") { string oneDriveDest = Path.Combine($"C:\\Users\\{Environment.UserName}\\OneDrive", file.Name); if (!File.Exists(oneDriveDest)) { File.Copy(sourceFile, oneDriveDest); } else { Console.WriteLine("File already exists"); } } string textBoxDest = Path.Combine(textBox3.Text, file.Name); if (!File.Exists(textBoxDest)) { File.Move(sourceFile, textBoxDest); } else { Console.WriteLine("File already exists"); } } else { Console.WriteLine($"File {file.Name} not found."); } }
2. 增加等待逻辑,确保文件写入完成
对于大文件,可以通过循环等待+重试的方式,确保文件完全写入磁盘后再操作:
public void OnCreated(object sender, FileSystemEventArgs file) { Console.WriteLine("created called"); string sourceFile = Path.Combine(textBox2.Text, file.Name); int maxRetries = 10; int retryCount = 0; bool fileExists = false; // 循环等待文件存在且可访问 while (retryCount < maxRetries) { if (File.Exists(sourceFile)) { try { // 尝试独占打开文件,确认未被写入进程占用 using (File.Open(sourceFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) { fileExists = true; break; } } catch (IOException) { // 文件被占用,继续等待 Thread.Sleep(500); retryCount++; } } else { Thread.Sleep(500); retryCount++; } } if (fileExists) { // 后续复制、移动逻辑... } else { Console.WriteLine($"File {file.Name} not found in directory {textBox2.Text}."); } }
3. 捕获文件访问异常,增加重试机制
即使文件存在,也可能因为被写入进程占用而无法操作,此时可以捕获IOException并重试:
// 在复制或移动时添加异常处理 try { File.Copy(sourceFile, destPath); } catch (IOException) { // 等待1秒后重试 Thread.Sleep(1000); File.Copy(sourceFile, destPath); }
内容的提问来源于stack exchange,提问作者AmsterdamGhoul
相关产品推荐
相关产品推荐

