问题描述
我正在使用 C# 处理文件观察器项目,我试图将更改文件复制到新创建的文件中,但出现错误:路径中有非法字符,如下所示
我认为问题出在 .4 之前的空白处,我用黄色下划线标出了它。我试图摆脱这个空白,但我不能。代码在下面
private void OnChanged(object source,FileSystemEventArgs e)
{
if (e.ChangeType == WatcherChangeTypes.Changed || e.ChangeType == WatcherChangeTypes.Created)
{
String targetname = null;
String fn = "";
try
{
bool copy = true;
targetname = GetShortcutTarget(e.FullPath);
if (targetname == null)
{
Console.WriteLine($"File: {e.FullPath} {e.ChangeType}");
}
else
{
c += 1;
fn = targetname.Replace('\\','_').Replace(":","_c_");
DateTime lmt = File.GetLastWriteTime(targetname);
if (lastSeen.ContainsKey(targetname))
{
if (lastSeen[targetname] < lmt)
{
copy = true;
}
else
{
copy = false;
}
}
else
{
lastSeen[targetname] = lmt;
copy = true;
}
if (copy)
{
Console.WriteLine($"Filec: {e.FullPath} {targetname} {e.ChangeType}");
//HERE
System.IO.File.copy(targetname,$"{_lfile}\\{fn}.{c}",true);
// Only keep copy if copy worked
latest[fn] = c;
}
else
{
Console.WriteLine($"Have {e.FullPath} {targetname}");
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Failure to copy {e.FullPath} {targetname} {$"{_lfile}\\{fn}.{c}"} {ex.Message}");
}
}
else
{
Console.WriteLine($"File: {e.FullPath} {e.ChangeType}");
}
}
我注意到一个“HERE”注释,向您显示文件名的创建位置。我尝试了很多方法,如修剪、替换,但它不起作用。你能帮我么?我将不胜感激。
namespace FileWatcher
{
class Program
{
static void Main(string[] args)
{
String userName;
String expt;
if (args.Length < 2)
{
Console.WriteLine($"FileWatcher <user> <exptName>");
Console.WriteLine($"Captures files into /temp/<exptName>-log and /temp/<exptName>-files");
userName = "lashi";
expt = "expt1";
}
else
{
userName = args[0];
expt = args[1];
}
String lexpt = $"c:\\temp\\{expt}-log";
String fexpt = $"c:\\temp\\{expt}-file";
if (!Directory.Exists(fexpt))
{
Directory.CreateDirectory(fexpt);
}
if (!Directory.Exists(lexpt))
{
Directory.CreateDirectory(lexpt);
}
Watcher w = new Watcher(lexpt,fexpt,userName);
w.Watch();
}
}
class Watcher
{
Dictionary<String,int> latest = new Dictionary<String,int>();
String _username;
String _ext;
String _lfile;
String _ffile;
int c = 0;
Dictionary<String,DateTime> lastSeen;
public Watcher(String lfile,String fFile,String uName)
{
_username = uName;
_ext = "*";
_lfile = lfile;
_ffile = fFile;
lastSeen = new Dictionary<string,DateTime>();
Console.CancelKeyPress += copyFiles;
}
public void copyFiles(object sender,ConsoleCancelEventArgs e)
{
Console.WriteLine("Acting on ctrl-c");
copyFiles();
}
public void copyFiles()
{
foreach (keyvaluePair<string,int> entry in latest)
{
try
{
System.IO.File.copy($"{_lfile}\\{entry.Key}.{entry.Value}",$"{ _ffile}\\{entry.Key}",true);
}
catch (Exception e)
{
Console.WriteLine($"Failure to take last copy {entry.Key} {entry.Value}");
}
}
}
public void Watch()
{
using (FileSystemWatcher watcher = new FileSystemWatcher($"C:\\Users\\{_username}\\AppData\\Roaming\\Microsoft\\Windows\\Recent",_ext))
{
// watcher.Path = args[1];
// Watch for changes in LastAccess and LastWrite times,and
// the renaming of files or directories.
watcher.NotifyFilter = NotifyFilters.LastAccess
| NotifyFilters.LastWrite
| NotifyFilters.FileName
| NotifyFilters.DirectoryName;
// Only watch text files.
// watcher.Filter = "*.txt";
watcher.IncludeSubdirectories = false;
// Add event handlers.
watcher.Changed += OnChanged;
watcher.Created += OnChanged;
watcher.Deleted += OnChanged;
watcher.Renamed += OnRenamed;
// Begin watching.
watcher.EnableRaisingEvents = true;
// Wait for the user to quit the program.
Console.WriteLine("Press 'q' to quit the sample.");
while (Console.Read() != 'q') ;
}
// After a q then
}
Failure to copy C:\Users\lashi\AppData\Roaming\Microsoft\Windows\Recent\MSIX+VHD.docx.lnk C:\Users\lashi\Desktop\Klera_Internship\MSIX+VHD.docx c:\temp\expt1-log\C_c__Users_lashi_Desktop_Klera_Internship_MSIX+VHD.docx .1 Illegal characters in path.
解决方法
我没有看到您实际上试图去除空格,也没有看到您在哪里摆脱了这些括号。我也不喜欢输入你的路径——我希望我没有弄错。也许您现在可以明白为什么每个人都要求您为您的价值观提供实际文本,而不是屏幕截图...
就我个人而言,我会使用正则表达式并将字符限制为字母数字和其他一些特殊字符(如下划线)。您可以根据需要修改正则表达式并添加其他特殊字符。但是,您可能会得到 2 个原始名称不同但目标名称相同的文件(例如“test one.jpg”和“testone.jpg”),因此您应该考虑
也许这样的方法可能更好:
using System;
using System.Text.RegularExpressions;
public class Program
{
public static void Main()
{
var fn = "";
var targetname = @"C:\Users\lashi\Desktop\Klera_Internship (2).lnk";
var _lfile = @"c:\temp\expt1-log";
var c = 12; // arbitrary int
// what you're doing now... I don't see you trying to clean any spaces,nor brackets:
fn = targetname.Replace('\\','_').Replace(":","_c_");
Console.WriteLine($"Target Before: {targetname}");
Console.WriteLine($"Destination Before: {_lfile}\\{fn}.{c}");
// what you could do with a few more replacements:
fn = targetname.ToSafeFilename();
Console.WriteLine($"Target After: {targetname}");
Console.WriteLine($"Destination After: {_lfile}\\{fn}.{c}");
}
}
public static class StringExtensions{
public static string ToSafeFilename(this string inString)
{
inString = Regex.Replace(inString,@"\\","_");
inString = Regex.Replace(inString,@":","_c_");
return Regex.Replace(inString,@"[^0-9a-zA-Z_]+","");
}
}
输出:
//Target Before: C:\Users\lashi\Desktop\Klera_Internship (2).lnk
//Destination Before: c:\temp\expt1-log\C_c__Users_lashi_Desktop_Klera_Internship (2).lnk.12
//Target After: C:\Users\lashi\Desktop\Klera_Internship (2).lnk
//Destination After: c:\temp\expt1-log\C_c__Users_lashi_Desktop_Klera_Internship2lnk.12
见: