Резервное копирование в файл, чтобы предотвратить его повреждение во время обработки


Моя программа выполняет итерации по списку файлов и обработки каждой из них с помощью какой-то библиотеки. Вполне возможно, что файл может быть поврежден в процессе, так что я хочу создать ее резервную копию, чтобы предотвратить потенциальное повреждение.

Я реализовал это так:

private static void ComprocessFiles(List<string> files)
{
    FileInfo file = null;                    
    foreach (string filepath in files)
    {
        bool backedUp = false;
        bool keepBackup = false;
        try
        {
            file = new FileInfo(filepath);
            if (!file.Exists) continue;
            if (file.IsReadOnly) continue;

            BackupHelper.Backup(file);
            backedUp = true;
            ProcessFile(file);

            BackupHelper.RestoreTimestamps(file);
            file.Refresh();
        }
        catch (Exception ex)
        {
            try
            {
                Logger.LogSkippedFile(ex.GetType().Name, ex.Message, filepath);
                if (backedUp) BackupHelper.RestoreFile(file);
            }
            catch (Exception ex)
            {
                keepBackup = true;
            }
            // Listed exceptions are not critical.
            if (!(ex is IOException || ex is UnauthorizedAccessException || ex is System.Security.SecurityException))
            {
                throw;
            }
        }
        finally
        {
            if (!IsCorrupted(file)) keepBackup = true;
            if (!keepBackup) BackupHelper.DeleteBackup(file);
        }
    }
}

BackupHelper класс:

static class BackupHelper
{
    static private DateTime[] timestamps = new DateTime[3];

    static internal void Backup(FileInfo originalFile)
    {
        timestamps[0] = originalFile.CreationTime;
        timestamps[1] = originalFile.LastWriteTime;
        timestamps[2] = originalFile.LastAccessTime;

        File.Copy(originalFile.FullName, originalFile.FullName + "_backup", true);
    }

    static internal void Backup(string originalFile)
    {
        Backup(new FileInfo(originalFile));
    }

    static internal void RestoreFile(FileInfo originalFile)
    {
        File.Copy(originalFile.FullName + "_backup", originalFile.FullName, true);
    }

    static internal void RestoreFile(string originalFile)
    {
        RestoreFile(new FileInfo(originalFile));
    }

    static internal void RestoreTimestamps(FileInfo originalFile)
    {
        originalFile.CreationTime   = timestamps[0];
        originalFile.LastWriteTime  = timestamps[1];
        originalFile.LastAccessTime = timestamps[2];
    }

    static internal void RestoreTimestamps(string originalFile)
    {
        RestoreTimestamps(new FileInfo(originalFile));
    }

    static internal void DeleteBackup(FileInfo originalFile)
    {
        timestamps = new DateTime[3];
        File.Delete(originalFile + "_backup");
    }

    static internal void DeleteBackup(string originalFile)
    {
        DeleteBackup(new FileInfo(originalFile));
    }
}

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

Я думаю, методы ProcessFile() и IsCorrupted() не важно на этот вопрос, а также Logger класс.

Важное примечание - StackOverflowException и OutOfMemoryException Не могу быть брошенным в соответствии с настоящим Кодексом это не делать много вызовов методов и не использовать много памяти.



141
2
задан 9 февраля 2018 в 09:02 Источник Поделиться
Комментарии
3 ответа

Насколько велик риск, что ваши файлы будут повреждены? Есть ли особая причина, почему вы думаете, что это может произойти, и если так, что что-то можно решить?

Вы обеспокоены тем, что это ваш акт обработки файла, которые могут повредить его? Если это так, вы можете хотеть делать противоположное тому, что ты делаешь. Не создавайте резервную копию, но вместо того, чтобы оставить оригинал в покое и создать рабочую копию, которую вы выбросите, когда вы закончите. Если что-то пойдет не так, то, по крайней мере, исходный файл все равно есть, нетронутым.

Это может показаться смешным, но это не так: Если вы не доверяете вашей файловой системе, то это не очень хорошее место для данных приложения. Откуда вы знаете, что даже после резервного копирования, файл Вы читаете не станем разлагать, как ты читаешь? Как вы знаете, он не был уже поврежден, когда он был создан? Откуда вы знаете, что резервные копии не будут повреждены?

Наилучший подход зависит не только от степени доверия (или недоверия) хранения, но и как велик риск, если ваши данные были утеряны. Если ваш сервер получает регулярное резервное копирование, то, что может быть все защиты вам нужно. Возможно, вы могли бы создать хэш или контрольная сумма каждого файла и сохранить его в файле. При обработке файла, проверьте, что он совпадает с хэш. Это дает вам столько же уверенности, как вы, возможно, хотят.

2
ответ дан 10 февраля 2018 в 03:02 Источник Поделиться

Я немного обеспокоен статические поля, используемого для хранения временных меток в BackupHelper класс. Если кто-то использовал ваш класс в разных потоках, или резервное копирование более чем одной за раз, обработке их всех, а затем восстанавливая их всех, они потенциально в конечном итоге с неправильным поля типа timestamp.

Одним из путей ее решения может стать использование Dictionary<string, List<string>>, где ключ-это путь и время-это ценность.

Другое дело было бы хранить строку "_backup" как const. Повторил жестко закодированные строки иногда может привести к проблемам.

2
ответ дан 10 февраля 2018 в 05:02 Источник Поделиться

Все, что у меня сейчас

Мне не нравится

File.Delete(originalFile + "_backup");

Передается FileInfo может. Я не проверял, но подозреваю, что вы получаете неявное приведение к строке.

FileInfo имеет удалить методом. У BackupHelper вернуть FileInfo может так можно удалить напрямую.

1
ответ дан 9 февраля 2018 в 03:02 Источник Поделиться