Как я могу записать в один файл XML из двух программ одновременно? - PullRequest
0 голосов
/ 10 июня 2010

Мы недавно начали работать с XML-файлами, после многолетнего опыта работы со старыми INI-файлами.

Мой коллега нашел пример кода CodeProject, который использует System.Xml.XmlDocument.Save.Мы получаем исключения, когда две программы пытаются записать в один и тот же файл одновременно.

System.IO.IOException: процесс не может получить доступ к файлу 'C: \ Test.xml', поскольку он используется другим процессом.

Это кажется очевиднымОглядываясь назад, мы не ожидали этого, потому что доступ к файлам INI через Win32 API не имеет этого ограничения.Я предполагаю, что некоторые вызовы Win32 выполняют арбитраж, который работает на более высоком уровне, чем метод XmlDocument.Save.

Я надеюсь, что где-то в библиотеке .Net есть процедуры XML более высокого уровня, которые работают аналогичноWin32 работает, но не знаю, с чего начать.

Или, может быть, мы можем настроить наши права доступа к файлу, чтобы позволить нескольким программам писать в один и тот же файл?

Время короткое(как почти все проекты ПО), и если мы не сможем быстро найти решение, нам придется держать нос и возвращаться к файлам INI.

Ответы [ 6 ]

5 голосов
/ 10 июня 2010

Это не сработает. Даже если 2 процесса могут записать в один и тот же файл, он просто повредит ваш файл. Если вам действительно нужно писать несколько программ одновременно, я бы вместо этого использовал базу данных.

Или вы могли бы разделить ваш отдельный XML-файл на отдельные файлы? Пусть каждый процесс записывает в свой собственный файл, а затем объединяет все файлы вместе во время вашего метода «Чтение».

2 голосов
/ 10 июня 2010

Если эти программы выполняются в одном и том же сеансе, вы можете создать отдельный класс для обработки записи в файлы и использовать шаблон проектирования Singleton (или Multiton для сопоставления с несколькими именами файлов), чтобы гарантировать только один экземпляр этого класса. Это исключит ваши исключения ввода / вывода. Просто убедитесь, что вы очищаете буфер в этом новом классе при каждом запросе «записи в файл».

Осторожно: это представит глобальное состояние вашей программе. По этой причине некоторые считают, что синглтон является анти-паттерном.

Кроме того, это может не сработать для файлов XML, потому что они образуют древовидную структуру, что означает, что весь файл необходимо перечитать перед тем, как вносить в него изменения записи (вы не можете просто «добавить»). в конец файла или вы его испортите).

Я думаю, вам нужно изучить причину, по которой вы пытаетесь использовать XML. Если вы пытаетесь использовать его как «тупую базу данных», вам следует подумать о переходе на настоящую «облегченную» базу данных, такую ​​как SQLite. Если вам просто нужно несколько раз добавить конец файла, нет ничего плохого в использовании плоского файла, такого как .ini.

1 голос
/ 10 июня 2010

Что ж, вы можете решить свою первую проблему, убедившись, что вы закрываете файл, когда пишете его, и повторите попытку, чтобы открыть его.Затем вам нужно держать его открытым, читать, объединять любые изменения, а затем записывать снова.(вы должны объединить изменения, в противном случае вы перезапишете изменения, сделанные между вашим приложением, читающим файл и записывающим его снова).

Файлы INI были заменены дважды - один раз реестром, а затем ConfigurationManager Возможно, вы захотите поэкспериментировать с ConfigurationManager.Похоже, Configuration.Save сгенерирует исключение, если файл изменился или не может записать в него - в этом случае перехватить исключение и повторить попытку несколько раз.

1 голос
/ 10 июня 2010

Альтернативой разбиению файла может быть использование базы данных - там есть базы данных XML, Википедия содержит некоторые из них в списке.

Я не могу поручиться за любого из них.

1 голос
/ 10 июня 2010

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

Однако, если вы хотите, чтобы один файл читался, при этомдругой пишет, что это сработает (если вы не против читателя, возможно, читающего слегка старый файл).Если это так, используйте функции XmlDocument.Load, передаваемые в FileStream, который был инициализирован с доступом к файлу только для чтения.

Многие (большинство?) Пространства имен System.Xml также будут иметь перегрузки, безопасные для потоков, но это звучит таквам нужен межпроцессный доступ к файлам, так что это не поможет, если вы не сможете свести все свои экземпляры своих приложений в один процесс.

Поэтому, если бы я был вами, я бы рассмотрел более богатое хранилище данных, которое поддерживает несколько-процесс доступа.Самым очевидным ответом была бы какая-то база данных.

РЕДАКТИРОВАТЬ: Исправлено согласно комментарию.

0 голосов
/ 10 июня 2010

Файл XML намного более чувствителен к своей структуре (схема / DTD и т. Д.), Чем файл INI.Кроме того, методы INI в Win32 скрывают от вас сложности доступа к файлам.Теоретически вы могли бы придумать какой-нибудь многопоточный писатель, который заблокирован на уровне тегов, а не на уровне файлов, но это не готовая функция.

...