-1

我有一个 C# Windows 服务正在监视一个文件夹。看起来如果文件是使用传统的 windows 文件名结构创建的,一切都很好,例如 foo.zip。但随之而来的是那些为他们的文件命名的讨厌的 unix 人之一:foo.bar.11-10-2013.zip。

我的程序中的 File Watcher 永远不会看到这个文件。没有设置过滤器,因此默认为*.*.

如果我重命名文件以删除点并用下划线替换它们,则文件观察器会看到该文件。

我尝试用谷歌搜索答案,但我的另一个问题是我不确定如何陈述这个问题 - 我们称之为多个扩展名还是多个点或多个句点?所有这些都返回了无益的结果。

所以我的问题是:是否可以设置一个文件观察器来检测带有多个点扩展名的 linux 样式文件名?如果您碰巧知道“多点文件扩展名”的正式术语,我很想知道它们叫什么。

4

2 回答 2

0

我昨晚发布的答案没有通过回归测试。我得到了混合的结果和文件系统观察程序的不同过滤器设置,它偶尔会错过不可接受的文件。有很多关于网络共享问题的文章,但我认为这意味着观察者正在观察映射到另一台计算机的网络共享,而不是被观察的目录本身就是运行服务的同一台机器上的网络共享。延迟可能是我的一些失误的一个因素,但即使在本地,该组件似乎也无法识别多点文件名。

由于这是一项服务,我们已经有了一种方法来检测服务启动时已经存在的任何文件。这种方法有效并且不依赖于组件。所以最优雅的解决方案是简单地将代码放在计时器上。以下是该类的相关部分(即,此代码段并非设计为可复制/粘贴,仅用于展示我如何解决问题)。不要让 FTP 绰号让您偏离正题——它实际上只是在查看一个可能映射到也可能不映射到 FTP 服务器的共享文件夹。

using System.Collections.Generic;
using Timer = System.Timers.Timer;

public partial class VsiFtpManager : ServiceBase
{
    private Timer _searchTimer;
    private Queue<string> _filesToProcess;
    private string _ftpRoot; //this is set elsewhere from the registry

    protected override void OnStart(string[] args)
    {

        //process any files that are already there when the service starts
        LoadExistingFtpFiles(); 

        //Handle new files
        _searchTimer = new Timer(10000);
        _searchTimer.Elapsed += LoadExistingFtpFiles;
    }

    //convenience overload to allow this to handle timer events
    private void LoadExistingFtpFiles(object source, ElapsedEventArgs evtArgs)
    {
        LoadExistingFtpFiles();
    }

    private void LoadExistingFtpFiles()
    {
        _searchTimer.Stop();
        var di = new DirectoryInfo(_ftpRoot);
        FileInfo[] fileInfos = di.GetFiles("*.*", SearchOption.AllDirectories);
        foreach (FileInfo fi in fileInfos.Where(fi => fi != null))
        {
            if (fi.Extension != "processed" && !_filesToProcess.Contains(fi.FullName))
            {
                LogHelper.BroadcastLogMessage("INFO:  File " + fi.Name + " was uploaded.", EventLogEntryType.Information);
                _filesToProcess.Enqueue(fi.FullName);
                LogHelper.BroadcastLogMessage("File received: " + fi.Name, EventLogEntryType.Information);
            }
        }
        _searchTimer.Start();

    }
}

您看不到的部分超出了我的问题范围,它本质上是针对队列 _filesToProcess 运行的协同程序,它处理文件然后将它们重命名为具有 .processed 的扩展名。

所以我的最终答案是:我的研究,通过自动回归测试证实,表明文件系统观察器对我的用例不可靠,这需要我处理复制到文件夹中的文件。其中一些文件将来自 Unix 系统,因此可能具有非 Windows 文件名。.net 附带的文件系统观察程序组件无法可靠地检测名称中带有多个点的 unix 样式文件名称。

我用一个简单的轮询机制替换了文件系统观察程序。执行速度明显较慢但可靠,这是我的主要目标。整体解决方案减少了我的代码行数,尽管微不足道,并删除了我在服务设计表面上的唯一组件,由于我自己可能有特殊的偏好,我认为这两者都有好处。

于 2014-11-11T18:49:35.903 回答
0

我已经决定答案是你不能,至少在没有大量工作的情况下不能。我考虑了一个每隔几秒钟重命名多点文件的计时器,但这似乎很破旧。

创建文件时,我将文件观察程序设置为触发 - 这是您将控件拖到设计图面上时得到的结果。

我更改了事件以检测更改,并过滤了大小。看来排除“多点”文件扩展名,为什么不呢?foo.bar.blah.zip 不适合. 图案。我们需要的是类似 ant 的文件模式描述符(因为没有人提供更好的术语 :-),但文档似乎不支持这些描述符。

通过让它监视文件大小的变化似乎会在创建文件时触发(从零到某个东西),这对我来说已经足够好了。一旦我知道文件在那里,无论控件的过滤器如何,我都可以获得它的名称。

于 2014-11-10T23:19:10.623 回答