Почему мой файл иногда исчезает в процессе чтения или записи в него?
У меня есть приложение, которое читает из текстовых файлов, чтобы определить, какие отчеты должны быть созданы. Большую часть времени он работает как надо, но время от времени программа удаляет один из текстовых файлов, из которых она читает / записывает. Затем генерируется исключение ("Не удалось найти файл"), и выполнение прекращается.
Вот некоторый соответствующий код.
Сначала читаем из файла:
List<String> delPerfRecords = ReadFileContents(DelPerfFile);
. . .
private static List<String> ReadFileContents(string fileName)
{
List<String> fileContents = new List<string>();
try
{
fileContents = File.ReadAllLines(fileName).ToList();
}
catch (Exception ex)
{
RoboReporterConstsAndUtils.HandleException(ex);
}
return fileContents;
}
Затем, запись в файл - он помечает запись / строку в этом файле как обработанную, чтобы тот же отчет не был повторно сгенерирован при следующей проверке файла:
MarkAsProcessed(DelPerfFile, qrRecord);
. . .
private static void MarkAsProcessed(string fileToUpdate, string
qrRecord)
{
try
{
var fileContents = File.ReadAllLines(fileToUpdate).ToList();
for (int i = 0; i < fileContents.Count; i++)
{
if (fileContents[i] == qrRecord)
{
fileContents[i] = string.Format("{0}{1} {2}"
qrRecord, RoboReporterConstsAndUtils.COMPLETED_FLAG, DateTime.Now);
}
}
// Will this automatically overwrite the existing?
File.Delete(fileToUpdate);
File.WriteAllLines(fileToUpdate, fileContents);
}
catch (Exception ex)
{
RoboReporterConstsAndUtils.HandleException(ex);
}
}
Поэтому я удаляю файл, но сразу заменяю его:
File.Delete(fileToUpdate);
File.WriteAllLines(fileToUpdate, fileContents);
Читаемые файлы имеют следующее содержимое:
Opas,20170110,20161127,20161231-COMPLETED 1/10/2017 12:33:27 AM
Opas,20170209,20170101,20170128-COMPLETED 2/9/2017 11:26:04 AM
Opas,20170309,20170129,20170225-COMPLETED
Opas,20170409,20170226,20170401
Если "-COMPLETED" появляется в конце записи / строки / строки, оно игнорируется - не будет обработано.
Кроме того, если второй элемент (с индексом 1) является датой в будущем, он не будет обработан (пока).
Таким образом, для этих примеров, показанных выше, первые три уже выполнены, и впоследствии будут игнорироваться. Четвертый не будет действовать до или после 9 апреля 2017 года (когда будут получены данные в диапазоне данных за последние две даты).
Почему файл иногда удаляется? Что я могу сделать, чтобы предотвратить это?
Если полезно, в более широком контексте, логика выглядит так:
internal static string GenerateAndSaveDelPerfReports()
{
string allUnitsProcessed = String.Empty;
bool success = false;
try
{
List<String> delPerfRecords = ReadFileContents(DelPerfFile);
List<QueuedReports> qrList = new List<QueuedReports>();
foreach (string qrRecord in delPerfRecords)
{
var qr = ConvertCRVRecordToQueuedReport(qrRecord);
// Rows that have already been processed return null
if (null == qr) continue;
// If the report has not yet been run, and it is due, add i
to the list
if (qr.DateToGenerate <= DateTime.Today)
{
var unit = qr.Unit;
qrList.Add(qr);
MarkAsProcessed(DelPerfFile, qrRecord);
if (String.IsNullOrWhiteSpace(allUnitsProcessed))
{
allUnitsProcessed = unit;
}
else if (!allUnitsProcessed.Contains(unit))
{
allUnitsProcessed = allUnitsProcessed + " and "
unit;
}
}
}
foreach (QueuedReports qrs in qrList)
{
GenerateAndSaveDelPerfReport(qrs);
success = true;
}
}
catch
{
success = false;
}
if (success)
{
return String.Format("Delivery Performance report[s] generate
for {0} by RoboReporter2017", allUnitsProcessed);
}
return String.Empty;
}
Как я могу использовать этот код для предотвращения периодической загрузки файлов?
ОБНОВИТЬ
Я не могу проверить это, потому что проблема возникает так редко, но мне интересно, решит ли это добавление "паузы" между File.Delete() и File.WriteAllLines()?
ОБНОВЛЕНИЕ 2
Я не совсем уверен, что ответ на мой вопрос, поэтому я не буду добавлять это как ответ, но я предполагаю, что File.Delete() и File.WriteAllLines() происходили слишком близко друг к другу, и поэтому иногда происходило удаление как старой, так и новой копии файла.
Если это так, то пауза между двумя вызовами могла бы решить проблему в 99,42% случаев, но из того, что я нашел здесь, кажется, что File.Delete() в любом случае избыточен / избыточен, и поэтому я протестировал с File.Delete() прокомментировал, и он работал нормально; так что теперь я просто обхожусь без этого иногда проблемного звонка. Я ожидаю, что это решит проблему.
1 ответ
// Will this automatically overwrite the existing?
File.Delete(fileToUpdate);
File.WriteAllLines(fileToUpdate, fileContents);
Я бы просто добавил дополнительный параметр в WriteAllLines()
(который может по умолчанию false
) сообщить функции открыть файл в режиме перезаписи, а не вызывать File.Delete()
тогда вообще.
Вы в настоящее время проверяете возвращаемое значение открытого файла?
Обновление: хорошо, похоже WriteAllLines()
является функцией.Net Framework и поэтому не может быть изменен, поэтому я удалил этот ответ. Однако теперь это проявляется в комментариях в качестве предлагаемого решения на другом форуме:
"просто используйте что-то вроде File.WriteAllText, где, если файл существует, данные просто перезаписываются, если файл не существует, он будет создан".
И это было именно то, что я имел в виду (думая, WriteAllLines()
была пользовательская функция), потому что у меня были подобные проблемы в прошлом.
Таким образом, подобное решение могло бы решить некоторые хитрые проблемы (вместо удаления / быстрого повторного открытия, просто перезаписи файла) - также меньше работы для ОС и, возможно, меньше фрагментации файла / диска.