Как создать файл, содержащий файлы и каталоги?

#c# #wpf #file #package

#c# #wpf #файл #пакет

Вопрос:

Я работаю над редактором markdown с открытым исходным кодом WPF, и я нахожусь в точке, где мне нужно сохранять и загружать документы.

«Документ» содержит 3 файла:

  • XML-файл для метаданных
  • Файл MD для текста markdown
  • HTML-файл для представления документа в формате HTML.

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

Я провел небольшое исследование и обнаружил, что документы Office имеют аналогичную структуру, где каждый файл на самом деле представляет собой пакет, содержащий несколько каталогов и файлов. Чтобы открыть такой документ office, все, что вам нужно сделать, измените расширение на ZIP, и вы сможете просматривать файлы, но снаружи это выглядит как один файл.

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

Есть ли какой-нибудь элегантный способ архивировать несколько файлов и каталогов в один файл и получить к ним доступ, если они мне нужны на C #?

Любые советы будут оценены.

Ответ №1:

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

Ответ №2:

Если кому-то интересно, как я применил ответ Эда Планкетта, вот код:

 var saveDialog = new SaveFileDialog
{
    CreatePrompt = true,
    OverwritePrompt = true,
    Filter = "Project Markdown File | *.pmd"
};

var result = saveDialog.ShowDialog();

if (result != null)
{
    if (result == true)
    {
        if (!Directory.Exists(saveDialog.FileName   "_temp"))
        {
            var parentFolder = Directory.CreateDirectory(saveDialog.FileName   "_temp").FullName;

            var mp = new MarkdownParser();
            // Generate HTML
            var html = mp.Parse(document.Markdown.Markdown);

            var markdownFilePath = parentFolder   "\"   saveDialog.SafeFileName   ".md";
            var htmlFilePath = parentFolder   "\"   saveDialog.SafeFileName   ".html";
            var metadataFilePath = parentFolder   "\"   saveDialog.SafeFileName   ".xml";
            // Generate MD file
            using (var sw = new StreamWriter(markdownFilePath))
            {
                sw.Write(document.Markdown.Markdown);
            }
            // Generate HTML file
            using (var sw = new StreamWriter(htmlFilePath))
            {
                sw.Write(html);
            }
            // Generate XML file
            document.Metadata.FileName = saveDialog.SafeFileName;
            var gxs = new GenericXmlSerializer<DocumentMetadata>();
            gxs.Serialize(document.Metadata, metadataFilePath);
            // Generate style
            var cssFilePath = AppDomain.CurrentDomain.BaseDirectory   "Styles\github-markdown.css";
            if (!Directory.Exists(parentFolder   "\Styles"))
            {
                Directory.CreateDirectory(parentFolder   "\Styles");
            }

            if (!File.Exists(parentFolder   "\Styles\github-markdown.css"))
            {
                File.Copy(cssFilePath, parentFolder   "\Styles\github-markdown.css");
            }
            // Generate the package
            ZipFile.CreateFromDirectory(parentFolder, saveDialog.FileName);
            // Update the view
            var saveResult = new SaveResult
            {
                FileName = saveDialog.SafeFileName,
                Source = htmlFilePath.ToUri(),
                TempFile = saveDialog.FileName   "_temp"
            };
            return saveResu<
        }
    }
}