我正在开发一个项目,其概念基本上就像文件容器一样,并将文件收集到一个文件中。 到目前为止,我创建了一个“容器”文件,它在开头分配了2mb用于索引文件。这部分是一个简单的XML文件,其中我存储了诸如文件名,偏移量,文件大小等信息。其余的是在分配2mb后分配给容器的文件。
目前,如果我创建一个容器并添加文件,它就像一个魅力。问题是,如果我想再添加一些,XmlDocument将在保存后删除其余内容。
我的问题是:我应该使用XML来执行索引,如果是,如何更新它而不会丢失,或者我应该采用不同的方式?
感谢您的建议!
答案 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;
}
它目前的工作方式就像一个魅力:)