C # - копировать файл только тогда, когда он был полностью скопирован на диск - PullRequest
0 голосов
/ 04 ноября 2019

Я пишу приложение, которое ожидает копирования файла в папку. Когда файл копируется, я пытаюсь открыть файл.

У меня возникла проблема, когда иногда длина файла равна нулю. Я считаю, что это потому, что файл не полностью завершен копирование на диск.

Я следовал https://stackoverflow.com/a/937558/5330854 решению, где я проверяю, заблокирован ли файл, но это все же позволяет мне открыть файл с нулевой длиной (я бы предположил, если файл в процессе выполнениябудучи скопированным на диск, он будет заблокирован, и я не смогу его открыть), когда файл не равен нулю.

Есть идеи, как проверить, закончил ли файл копирование на диск?

 while (stream == null && IsWithingTimeCap(startTime))
            {
                stream = GetFileStream(fileInfo);
                if (stream == null)
                {

                    Thread.Sleep(5000);

                }
    }

    if (fileInfo.Length == 0)
      {
           //log
    }


    private static Stream GetFileStream(IFileInfo fileInfo)
    {
        Stream stream = null;

        try
        {
            stream = fileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.None);
        }
        catch (IOException)
        {
            //the file is unavailable because it is:
            //still being written to
            //or being processed by another thread
            //or does not exist (has already been processed)
            return null;
        }

        return stream;
    }

1 Ответ

0 голосов
/ 04 ноября 2019

A. FileSystemWatcher

Вы можете подписаться на изменения в каталоге назначения, используя FileSystemWatcher Class .

Однако я не знаю ни одного события, на которое можно было бы надежно подписаться, которое происходит после завершения копирования. (Обратите также внимание, что метод Copy возвращается после последнего события, но это может быть нормально).

Вот пример.

var fileName = "a.zip";
var src = "c:\\tmp\\src";
var dst = "c:\\tmp\\dst";


using (FileSystemWatcher watcher = new FileSystemWatcher())
{
    watcher.Path = dst;

    void OnChanged(object source, FileSystemEventArgs e) =>
            Console.WriteLine($"{DateTime.Now:O}, OnChanged, file: {e.FullPath} {e.ChangeType}, size: {new System.IO.FileInfo(Path.Combine(dst,fileName)).Length}");

    void OnCreated(object source, FileSystemEventArgs e) =>
            Console.WriteLine($"{DateTime.Now:O}, OnCreated, file: {e.FullPath} {e.ChangeType}, size: {new System.IO.FileInfo(Path.Combine(dst,fileName)).Length}");


    watcher.NotifyFilter = NotifyFilters.Size
                        | NotifyFilters.DirectoryName
                        | NotifyFilters.Attributes
                        | NotifyFilters.Size
                        | NotifyFilters.LastWrite
                        | NotifyFilters.LastAccess
                        | NotifyFilters.CreationTime
                        | NotifyFilters.Security
                        ;

    watcher.Changed += OnChanged;
    watcher.Created += OnCreated;

    // Begin watching.
    watcher.EnableRaisingEvents = true;

    Console.WriteLine($"{DateTime.Now:O} Let's start copying");
    var t = Task.Run(() => {
        Console.WriteLine($"{DateTime.Now:O} Copy start");
        System.IO.File.Copy(Path.Combine(src, fileName), Path.Combine(dst,fileName), overwrite: false);
        Console.WriteLine($"{DateTime.Now:O} Copy end");
    });

    await t;

    Console.ReadLine();
}
2019-11-04T10:54:26.4737696+10:00 Let's start copying
2019-11-04T10:54:26.4972070+10:00 Copy start
2019-11-04T10:54:26.5093223+10:00, OnChanged, file: c:\tmp\dst\a.zip Changed, size: 1232583046
2019-11-04T10:54:26.5195866+10:00, OnChanged, file: c:\tmp\dst\a.zip Changed, size: 1232583046
2019-11-04T10:54:30.6444434+10:00 Copy end
2019-11-04T10:54:30.5599570+10:00, OnChanged, file: c:\tmp\dst\a.zip Changed, size: 1232583046

B. Нулевая длина

У вас уже есть один возможный ответ:

У меня возникла проблема, когда иногда длина файла равна нулю.

Вы можете проверитьдлина файла и дождитесь, пока он больше не станет нулевым.


Хотя это не строго копирование, здесь показан вид папки во время загрузки файла Firefox.

[! [Введите описание изображения здесь] [1]] [1]

04/11/2019  10:01    <DIR>          .
04/11/2019  10:01    <DIR>          ..
04/11/2019  10:01                 0 SSMS-Setup-ENU.exe
04/11/2019  10:01        56,512,149 SSMS-Setup-ENU.exe.part
               2 File(s)     56,512,149 bytes

Это тот же файл, загружаемый Internet Explorer.

04/11/2019  10:04    <DIR>          .
04/11/2019  10:04    <DIR>          ..
04/11/2019  10:04                 0 SSMS-Setup-ENU.exe.pz0u92s.partial
               1 File(s)              0 bytes
...