1

想象一下有一个内容很多的游戏,比如汽车模型。我不想将它们一直放在 RAM 中以节省内存,并且只想在需要时加载它们。当每辆车只有一个文件时,这很容易 - 但最后我会有这么多文件,项目将变得难以共享等。

但是当我将所有内容存储到一个文件中时,我不知道是什么。有没有办法将所有内容存储到一个文件中并像每个内容条目一样轻松导航到内容?我能想象的唯一一件事是保存在第二个文件中开始的字节位置(或作为内容文件中的标题),但我对这个解决方案非常不确定。

4

2 回答 2

1

There are quite a few different compression and archiving methods you could use to hold your files if you're looking to store them temporarily in a larger file for transport. Almost any compression method could work, which you choose is entirely up to you.

Example .zip compression can be found here: http://msdn.microsoft.com/en-us/library/ms404280.aspx

There's also the .cab file format that you can easily pack multiple files into and unpack later when you have need for them. There's an interesting article on creating .cab files in C# found here:

http://mnarinsky.blogspot.com/2009/11/creating-cab-file-in-c.html

It does require that you add references to Microsoft.Deployment.Compression.Cab.dll and Microsoft.Deployment.Compression.dll but the code itself is fairly simple after that. If you find none of those to be a suitable answer to your question, my only other suggestion is that you better organize the files rather than cramming them all into a single folder as that can make it quite difficult to navigate.

Also try using a collection to keep track of the file names if that helps too. You could define files in the XML and load everything into a dictionary or hash table if it needs to be more dynamic or define it in the code itself if you prefer that.

EDIT:

You can also try using a third party installer for transport. They offer many functions outside of compressing and packing files and will handle the data compression for you. I prefer NSIS personally as I find it to be highly user friendly but any installer can work. A few example installers are:

Installshield: http://www.installshield.com/ (integrates with Visual Studio)

WIX: http://wix.sourceforge.net/ (also integrates with Visual Studio, good if you're looking for something more XML based)

NSIS: http://nsis.sourceforge.net/Main_Page (scriptable, doesn't integrate with Visual Studio, easy guided design with Nsisqssg if you'd prefer not to do the bulk of the scripting on your own)

They all function differently but essentially achieve the same end result. It all depends on exactly what you're looking for.

于 2013-07-17T19:10:55.293 回答
1

一个简单的方法是当你编写文件时,你会跟踪(在内存中)东西在哪里。然后,在文件的末尾写一个索引。所以你的文件看起来像这样:

offset 0: data for object 1
offset 0x0473: data for object 2
offset 0x1034: data for object 3
etc.

您可以使用BinaryWriter. 在编写每个对象之前,查询writer.BaseStream.Position以获取文件的当前位置。您将该信息保存在内存中(只是对象名称及其位置)。

写完所有对象后,保存当前位置:

indexPosition = writer.BaseStream.Position;

然后在文件末尾写下索引:

name: "object 1", position: 0
name: "object 2", position: 0x0473
etc.

写一个空的索引条目来表示对象的结束:

name: "", position: 0xFFFFFFFF

你做的最后一件事是在文件末尾写下索引位置:

writer.Write(indexPosition);

现在,您可以使用BinaryReader. 寻找文件结尾减去 8 个字节,读取那里的长整数。这给了你索引的位置。查找索引并开始向前读取索引条目,直到到达位置为 0xFFFFFFFF 的条目。

您现在在内存中有索引。您可以创建一个Dictionary<string, long>,这样,给定一个对象名称,您就可以在文件中找到它的位置。获得位置,在那里寻找,并阅读对象。

当我们在 90 年代后期编写游戏时,这种事情非常普遍。您仍然可以这样做,尽管使用简单的数据库可能会更好。

于 2013-07-17T20:42:43.790 回答