我正在学习C#,并在BinaryReader / Writer上进行堆栈。我如何在这个原因中读/写文件: 我需要将这些数据存储到二进制文件中。 (精灵班)
public class Sprite
{
public Int32 id; //spriteID
public Int32 size; //sprite byte size
public byte[] dump; //sprite image byte-array
public Sprite()
{
id = 0;
size = 0;
dump = null;
}
}
我通过这个函数得到精灵数据:
public Sprite createSprite(Image image, System.Drawing.Imaging.ImageFormat format)
{
using (MemoryStream ms = new MemoryStream())
{
Sprite tmpSpr = new Sprite();
image.Save(ms, format);
tmpSpr.dump = ms.ToArray();
tmpSpr.size = tmpSpr.Length;
tmpSpr.id = 1; //just for example
return tmpSpr;
}
}
但我正在堆叠解决这个问题:
public static bool save(string filename)
{
FileStream fileStream = new FileStream(filename, FileMode.Create);
MemoryStream ms = new MemoryStream();
BinaryWriter wr = new BinaryWriter(ms);
//How i am should write a sprites here?
}
这里有未完成的读者功能。堆叠在阅读上。
public static bool load(string filename, ref Dictionary<UInt32, Sprite> sprites)
{
FileStream fileStream = new FileStream(filename, FileMode.Open);
try
{
using (BinaryReader reader = new BinaryReader(fileStream))
{
UInt32 totalSprites = reader.ReadUInt32(); //total sprites in file
//something like that?
List<UInt32> spriteIndexes = new List<UInt32>();
for (uint i = 0; i < totalSprites; ++i)
{
UInt32 index = reader.ReadUInt32();
spriteIndexes.Add(index);
}
UInt32 id = 1;
foreach (UInt32 element in spriteIndexes)
{
//i am not sure here =(
reader.BaseStream.Seek(element, SeekOrigin.Begin);
UInt32 size = reader.ReadUInt32();
Sprite sprite;
if (sprites.TryGetValue(id, out sprite))
{
if (sprite != null && size > 0)
{
if (sprite.size > 0)
{
//generate warning
}
else
{
sprite.id = id;
sprite.size = size;
sprite.dump = reader.ReadBytes(size);
sprites[id] = sprite;
}
}
}
else
{
//i am not shure here too.
reader.BaseStream.Seek(size, SeekOrigin.Current);
}
++id;
}
}
}
finally
{
fileStream.Close();
}
return true;
}
Sprite文件应该有一个totalSprites参数,以及所有精灵的列表,以及它们的id,size,dump。加载功能“似乎”几乎“完成”,但我不知道,如何为该“读者”写文件。请显示解决方案。谢谢你提前!
答案 0 :(得分:2)
你的基本问题是你不知道精灵在文件中的位置,直到你写它(除非你通过数组并计算字节,这是可能的),但你想写索引在精灵之前。您有几个选择:
首先,为什么要有一个索引?如果你知道你有多少精灵,你可以写下这个数字,然后按顺序读取文件,一次一个精灵。这是最简单的:
using (var fs = File.OpenWrite(filename))
{
using (var writer = new BinaryWriter(fs))
{
// write sprite count
writer.Write(spriteList.Count);
// and write each sprite
foreach (var s in spriteList)
{
writer.Write(sprite.id);
writer.Write(sprite.size);
writer.Write(sprite.dump);
}
}
}
阅读正好相反:读取计数,然后读取那么多精灵。除非您希望能够读取第五个精灵,否则不需要索引,而无需先读取前四个精灵。
如果你真的需要索引,可以为它编写一个占位符,然后编写精灵,跟踪它们的位置,然后回到文件的开头并写下真实的索引。像这样:
var index = new List<long>(spriteList.Count);
using (var fs = File.OpenWrite(filename))
{
using (var writer = new BinaryWriter(fs))
{
// write sprite count
writer.Write(spriteList.Count);
var indexPos = writer.BaseStream.Position;
// write index placeholder
for (var i = 0; i < spriteList.Count; ++i)
{
writer.Write(0L);
}
// and write each sprite
for (var i = 0; i < spriteList.Count ++i)
{
// save current position
writer.Flush();
index[i] = writer.BaseStream.Position;
writer.Write(sprite.id);
writer.Write(sprite.size);
writer.Write(sprite.dump);
}
// Seek back to the index position
writer.Flush();
writer.BaseStream.Position = indexPos;
// and write the real index
foreach (var pos in index)
{
writer.Write(pos);
}
}
}
另一种方法是首先编写精灵,然后如上所述跟踪它们在索引数组中的位置,但在精灵后写入索引。然后,要读取,您从文件的开头读取精灵计数,将其乘以8(long
的大小),并寻找文件的末尾减去那么多。那就是:
var spriteCount = reader.ReadInt32();
long indexSize = spriteCount * 8;
reader.BaseStream.Seek(-indexSize, SeekOrigin.End);
// now read the index of spriteCount values