Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/5: Рейтинг темы: голосов - 5, средняя оценка - 5.00
129 / 31 / 3
Регистрация: 03.08.2010
Сообщений: 630
1

Копирование файла с проверкой

09.11.2017, 22:41. Показов 984. Ответов 11
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Код:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
Program Do(string[] args)
{
    if (args == null || args.Length != 2)
        throw new ArgumentException("Necessary to specify source and destination files");
 
    string sourceFile = args[0];
    string destinationFile = args[1];
    const int bufferSize = 8 * 1024 * 1024;
    const int partSize = 250 * 1024 * 1024;
    byte[] part = new byte[partSize];
    byte[] verifyPart = new byte[partSize];
 
    using (FileStream sourceFS = new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize))
    using (FileStream destinationFS = new FileStream(destinationFile, FileMode.CreateNew, FileAccess.Write, FileShare.Read, bufferSize))
    using (FileStream verifyFS = new FileStream(destinationFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, bufferSize))
    {
        int partCounter = 1;
        long lastBytes = sourceFS.Length;
        while (lastBytes != 0)
        {
            int currentPartSize = lastBytes < partSize ? (int)lastBytes : partSize;
            long currentPosition = sourceFS.Position;
            Console.WriteLine($"Part {partCounter} of {sourceFS.Length / partSize + (sourceFS.Length % partSize != 0 ? 1 : 0)}:");
 
            ConsoleWriteFromStart("Reading from source");
            sourceFS.Read(part, 0, currentPartSize);
 
            ConsoleWriteFromStart("Writing to destination");
            destinationFS.Write(part, 0, currentPartSize);
            destinationFS.Flush();
            //destinationFS.Seek(-currentPartSize, SeekOrigin.Current);
 
            ConsoleWriteFromStart("Reading from destination");
            verifyFS.Read(verifyPart, 0, currentPartSize);
 
            ConsoleWriteFromStart("Verifying");
            bool successful = true;
            for (int i = 0; i < currentPartSize; i++)
                if (verifyPart[i] != part[i])
                {
                    successful = false;
                    break;
                }
            if (!successful)
            {
                sourceFS.Seek(currentPosition, SeekOrigin.Begin);
                destinationFS.Seek(currentPosition, SeekOrigin.Begin);
                verifyFS.Seek(currentPosition, SeekOrigin.Begin);
                ConsoleWriteFromStart("Fail");
            }
            else
            {
                lastBytes -= currentPartSize;
                ConsoleWriteFromStart("Successful");
                partCounter++;
            }
            Console.WriteLine();
        }
    }
    Console.WriteLine("Done!");
    return this;
}


Задача: скопировать файл по частям, проверяя копирование на ошибки после каждой части.
Зачем: конечное устройство часто совершает ошибки при записи на него, поэтому копировании больших файлов (>1ГБ) возможно только по частям и с проверкой каждой части.
Алгоритм:
1. Открываем FileStream на чтение исходного файла, на запись в конечный и на чтение с конечного.
2. Читаем часть исходного файла (размер каждой части, допустим, 250 Мб) в память, затем пишем в конечный. Затем читаем, что записали в конечный и сверяем с тем, что записывали.
3. Если не совпадает, то повторно копируем часть. Если совпадает, переходим к следующему.
4. Так до конца файла.

Проблема: каждая часть всегда с первого раза проходит проверку (part == verifyPart). Но если в конце просто сравнить файлы исходный и конечный файлы, то они всегда разные (из-за конечного ошибок конечного устройства). Т.е. алгоритм не работает и verifyFS почему-то всегда читает верные данные.

Добавлено через 16 минут
Я думаю, здесь дело в буферизации и кэшировании. verifyFS по факту читает не с конечного файла, а с кэша (оно и видно по скорости чтения - слишком уж быстро).
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
09.11.2017, 22:41
Ответы с готовыми решениями:

Копирование определенного текста из файла, копирование и вставка в статичную переменную
Доброго вечера. Делаю программу которая бы выводила погоду на сегодня через данные сайта. Завис на...

Копирование с проверкой
добрый день. на форме выполняю копирование файлов следующим образом: Sub Copy_File() Dim...

Копирование файлов с проверкой
Подскажите как правильно написать батник для копирования файла из каталога в другой каталог с...

Копирование с одной таблицы в другую с проверкой
С макросами никогда дел не имел, но появилась необходимость, для упрощения себе жизни. Есть 2...

11
Эксперт .NET
10545 / 6473 / 1502
Регистрация: 25.05.2015
Сообщений: 19,612
Записей в блоге: 14
10.11.2017, 08:05 2
Цитата Сообщение от Сидорович Посмотреть сообщение
конечное устройство часто совершает ошибки при записи на него
Что за устройство? Не пора ли его заменить на исправное?
0
129 / 31 / 3
Регистрация: 03.08.2010
Сообщений: 630
10.11.2017, 08:12  [ТС] 3
Rius, любое устройство, подключенное по USB. Исправить пока нет возможности, поэтому приходится придумывать вот такое.
0
Usaga
10.11.2017, 11:29
  #4

Не по теме:

Цитата Сообщение от Сидорович Посмотреть сообщение
Зачем: конечное устройство часто совершает ошибки при записи на него, поэтому копировании больших файлов (>1ГБ) возможно только по частям и с проверкой каждой части.
Любите фигнёй пострадать, да?

0
129 / 31 / 3
Регистрация: 03.08.2010
Сообщений: 630
10.11.2017, 11:40  [ТС] 5
Usaga, не понял. У вас есть альтернативный вариант?
0
Эксперт .NET
12074 / 8383 / 1281
Регистрация: 21.01.2016
Сообщений: 31,578
10.11.2017, 11:48 6
Сидорович, заменить устройство. И это основной вариант.
0
129 / 31 / 3
Регистрация: 03.08.2010
Сообщений: 630
10.11.2017, 11:48  [ТС] 7
Usaga,
Цитата Сообщение от Сидорович Посмотреть сообщение
Исправить пока нет возможности, поэтому приходится придумывать вот такое.
Дело не столько в самом устройстве, сколько в USB-контроллере. Соответственно, любая флешка, подключённая в любому USB порту лажает.
0
Эксперт .NET
12074 / 8383 / 1281
Регистрация: 21.01.2016
Сообщений: 31,578
10.11.2017, 11:52 8
Сидорович, проблема (по мимо сбойного ПК, воевать с багами которого - дурость) в том, что буферизация и кеширование - вопросы драйверов ОС, а не вашей программы. Т.е. повлиять на что-то тут будет сложно.
0
129 / 31 / 3
Регистрация: 03.08.2010
Сообщений: 630
10.11.2017, 11:57  [ТС] 9
Итак: как сделать файловый поток, который не будет читать из буфера? *пошёл гуглить*
0
Эксперт .NET
12074 / 8383 / 1281
Регистрация: 21.01.2016
Сообщений: 31,578
10.11.2017, 12:24 10
Сидорович, вы это

Цитата Сообщение от Usaga Посмотреть сообщение
буферизация и кеширование - вопросы драйверов ОС
... не заметили, да?

Гуглите, как работать с драйверами устройств или ФС напрямую (такое возможно).

Добавлено через 1 минуту

Не по теме:

Цитата Сообщение от Usaga Посмотреть сообщение
Гуглите, как работать с драйверами устройств или ФС напрямую (такое возможно).
Есть неслабая вероятность того, что к тому моменту, когда разберётся и наваяете что-то рабочее (если получится), вы бы уже два раза успели заработать на новый ПК или, как минимум, на ремонт старого.



Добавлено через 10 минут
Кстати, я так и не понял как в такой ситуации:
Цитата Сообщение от Сидорович Посмотреть сообщение
Дело не столько в самом устройстве, сколько в USB-контроллере.
... вы собрались что-то проверять. Если контроллер гонит, то вы никак уже не можете доверять всем его действиям и данным, что он возвращает.
0
129 / 31 / 3
Регистрация: 03.08.2010
Сообщений: 630
10.11.2017, 12:25  [ТС] 11
Цитата Сообщение от Usaga Посмотреть сообщение
вы собрались что-то проверять. Если контроллер гонит, то вы никак уже не можете доверять всем его действиям и данным, что он возвращает.
Он "гонит" только на запись, на чтение всё ок (проверено).
0
1142 / 851 / 262
Регистрация: 30.04.2009
Сообщений: 3,580
12.11.2017, 21:08 12
Цитата Сообщение от Сидорович Посмотреть сообщение
Он "гонит" только на запись, на чтение всё ок (проверено).
Если контроллер не пропускает данные т.е. с размером файла при записи все нормально, то можно попробовать записать весь файл, а потом по кускам проверять. Если кусок плохой - то перезаписывать его прямо внутри файла (используя FileMode.Open при открытии и установку позиции записи с помощью FileStream.Seek, не проверял, но должно сработать).
0
12.11.2017, 21:08
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.11.2017, 21:08
Помогаю со студенческими работами здесь

Копирование файлов с проверкой их наличия в списке копированных ранее
Добрый день! Помогите написать батник, суть ниже: Нужно копировать файлы по сети с записью лога...

Копирование данных из одной книги excel в другую с проверкой параметров
Добрый день, мои поиски решения не увенчались успехом, поэтому надеюсь на вашу помощь в написании...

Получение данных из файла с проверкой даты изменения файла
Скрипт, который получит данные их файла (get-content -File &quot;C:\File.txt&quot; в файле написано число),...

Написать форму для загрузки файла на сервер, в свою рабочую папку (с проверкой размера файла)
Написать форму для загрузки файла на сервер, в свою рабочую папку. И должен проверяться размер...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru