我有一个解决方案,可以充当两个系统之间的接口,读取放置在FTP站点上的文件并导入所有订单/产品/等。进入目标系统。
拾取文件后,将其移到相同位置的临时文件中,然后将内容读取到XmlDocument
中。
string[] files = Directory.GetFiles(pickupFolder, fileFilter, SearchOption.TopDirectoryOnly);
foreach (string pathToFile in files)
{
FileInfo srcFile = new FileInfo(pathToFile);
string tmpFilename = Path.Combine(srcFile.DirectoryName, $"~{Path.GetFileNameWithoutExtension(srcFile.Name)}.tmp");
srcFile.MoveTo(tmpFilename);
XmlDocument srcXml = new XmlDocument();
try
{
using (FileStream fs = srcFile.Open(FileMode.Open, FileAccess.Read))
{
srcXml.Load(fs);
}
}
catch (XmlException ex)
{
throw new FileException($"Invalid XML in {srcFile.Name}.", ex);
}
}
非常偶尔,界面会尝试打开文件,以便在移动过程尚未完成时将其加载到XmlDocument
中,并抛出IOException
。有什么方法可以防止这种情况发生?
创建需要迭代并处理文件的东西的最佳方法是什么?
答案 0 :(得分:0)
当FTP服务器仍在文件上锁定时,文件移动操作将引发异常。当文件仍在上载但尚未完成,但在磁盘上“可见”时,可能会发生这种情况。这种碰撞很少见,但是会发生。
首先检查您的FTP服务器设置和功能,看看它是否可以在上传过程中隐藏不完整的文件。另一种方法是,如果您控制上传文件的系统,则可以使用特殊的“请勿下载”扩展名上传文件,并在上传完成后对其进行重命名(原子操作)。最后,正如其他人指出的那样,您可以简单地捕获此特定异常并延迟重试。
答案 1 :(得分:0)
正如其他人指出的那样,如果进程定期运行,则只需用try / catch块将其包装即可:
try
{
srcFile.MoveTo(tmpFilename);
}
catch (Excption ex)
{
// Write log entry if required
continue;
}
如果这是一个一次性的过程,则需要定期尝试MoveTo
,直到文件被释放并可以移动为止。这样的事情可能会起作用:
int maxRetries = 60;
int retries = 0;
bool success = false;
while (retries < maxRetries)
{
try
{
retries++;
srcFile.MoveTo(tmpFilename);
success = true;
break;
}
catch (Excption ex)
{
// Log the error if required
Thread.Sleep(1000); // Wait 1 second
}
}
if (success == fale)
{
// Log the error
continue; // Skip the file if its still not released
}
该代码尝试在一分钟内每秒访问一次文件。如果失败,则程序将跳过此文件并继续下一个操作。