C#将多个文件合并为一个

时间:2013-09-18 07:10:25

标签: c# xml file

我正在开发一个项目,其概念基本上就像文件容器一样,并将文件收集到一个文件中。 到目前为止,我创建了一个“容器”文件,它在开头分配了2mb用于索引文件。这部分是一个简单的XML文件,其中我存储了诸如文件名,偏移量,文件大小等信息。其余的是在分配2mb后分配给容器的文件。

目前,如果我创建一个容器并添加文件,它就像一个魅力。问题是,如果我想再添加一些,XmlDocument将在保存后删除其余内容。

我的问题是:我应该使用XML来执行索引,如果是,如何更新它而不会丢失,或者我应该采用不同的方式?

感谢您的建议!

2 个答案:

答案 0 :(得分:4)

我认为你应该在重新发明轮子之前先看看SharpZipLib。

对于您的问题的答案,您应该首先将xml保存到内存流,然后将该流复制到您的文件中。 (这样你会知道你是否超过2mb大小) 我不会建议xml这个,也是2mb因为起始器大小非常多。 我会使用像binaryreader / writer

这样的东西

这只是例如:

public class FileData
{
    public string Filename { get; set; }
    public int Size {get; set; }
    public int ContainerFileOffset { get; set; }
}

List<FileData> files = new List<FileData>();

using(Stream stream = new ...Stream(...))
{
    BinaryWriter writer = new BinaryWriter(stream);

    writer.Write(files.Count);
    foreach(FileData fd in files)
    {
        writer.Write(Filename);
        writer.Write(Size);
        writer.Write(ContainerFileOffset);
    }
}

但我认为更好的方法是在文件前创建标题:

  File 1                                    File 2
+--------------------------+--------------+--------------------------+--------------+
| NextOffset|Filename|Size | FileData     | NextOffset|Filename|Size | FileData     |
+--------------------------+--------------+--------------------------+--------------+

通过这种方式,您可以轻松添加/删除文件。


另一个想法可能是在文件末尾写入fileinfolist。像:

+----------+----------+----------+---------------+------------------------------+
| Filedata | Filedata | Filedata | FileInfoTable | FileInfoTableOffset (4bytes) |
+----------+----------+----------+---------------+------------------------------+

FileInfoTableOffset将指向FileInfoTable的起始地址。如果你想读取文件,只需将整个FileInfoTable放入内存,准备好后再写回来。

答案 1 :(得分:0)

我尝试了另一种方式。

我创建了一个这样的可序列化类:

[Serializable]
public class FileEntry
{
    public string Name { get; set; }
    public byte[] Content { get; set; }
}

在类处理文件中:

public void AddFiles(string[] Files)
{
    int index = _files.Count;
    foreach (string file in Files)
    {
    {
        _files.Add(new FileEntry());
        _files[index].Name = Path.GetFileNameWithoutExtension(file);
        _files[index].Content = File.ReadAllBytes(file);
        index++;
    }

    byte[] bytes = null;
    BinaryFormatter serializer = new BinaryFormatter();
    using (MemoryStream memoryStream = new MemoryStream())
    {
        serializer.Serialize(memoryStream, _files);
        bytes = memoryStream.ToArray();
    }
    File.WriteAllBytes(_filePath, bytes);
}

还有:

public List<FileEntry> GetFiles()
{
    byte[] bytes = File.ReadAllBytes(_filePath);
    if (bytes.Length > 0)
    {
        BinaryFormatter serializer = new BinaryFormatter();
        using (MemoryStream memoryStream = new MemoryStream(bytes))
            _files = serializer.Deserialize(memoryStream) as List<FileEntry>;
    }
    return _files;
}

它目前的工作方式就像一个魅力:)