【发布时间】:2015-03-05 02:58:49
【问题描述】:
假设我有一个由一系列对象组成的文件格式,其中每个对象都有以下格式的标题:
public struct FileObjectHeader {
//The type of the object (not important for this question, but it exists)
public byte TypeID;
//The length of the object's data, which DOES NOT include the size of the header.
public UInt16 Length;
}
后跟指定长度的数据。
我首先通过为每个对象和对象的标题创建一个位置列表来读取这些数据:
struct FileObjectIndex {
public FileObjectHeader Header;
public long Location;
}
public List<FileObject> ReadObjects(Stream s) {
List<FileObjectReference> objectRefs = new List<FileObjectReference>();
try {
while (true) {
FileObjectHeader header = ReadObjectHeader(s);
//The above advances the stream by the size of the header as well.
FileObjectReference reference = new FileObjectReference() { Header = header, Position = stream.Position };
objectRefs.add(reference);
//Advance the stream to the next object's header.
s.Seek(header.Length, SeekOrigin.Current);
}
} catch (EndOfStreamException) {
//Do nothing as this is an expected case
}
//Now we'd read all of the objects that we've previously located.
//This code isn't too important for the question but I'm including it for reference.
List<FileObject> objects = new List<FileObject>();
foreach (var reference in objectRefs) {
s.seek(reference.Location, SeekOrigin.Begin);
objects.add(ReadObject(reference.Header, s));
}
return objects;
}
一些注意事项:
-
ReadObjectHeader和ReadObject方法如果未能读取所有需要的数据(IE,如果它们到达流的末尾)将抛出 EndOfStreamException。 - 我在这里使用 Seek 是因为对象可以引用其他对象,并且将有逻辑确保父对象在其子对象之前加载(文件格式不能保证父对象位于子对象之前)。我没有在上面的示例代码中包含它,因为它会使示例变得复杂,但不会改进它。
- 在大多数情况下,这可能是只读的
FileStream,但我也不能确定。但是,对于这种情况,我主要担心 FileStreams。
我的问题是这样的:
由于我使用的是FileStream.seek,使用搜索是否会导致超出流的末尾并无限期地扩展文件?根据文档:
您可以搜索到流长度之外的任何位置。当您搜索超出文件长度时,文件大小会增加。在 Windows NT 和更高版本中,添加到文件末尾的数据设置为零。在 Windows 98 或更早版本中,添加到文件末尾的数据不会设置为零,这意味着之前删除的数据对流可见。
按照规定的方式,它似乎可以在没有我扩展的情况下扩展文件,从而导致文件不断增长,因为它从标题中读取 3 个字节。实际上,这似乎不会发生,但我想确认它不会发生。
【问题讨论】:
-
我可能遗漏了一些东西,但是如果您害怕寻找超过原始长度并且只进行读取,为什么不在开始时捕获最大寻找位置,然后进行检查以确保您没有'不过去吗?我认为关于 seek 过去的文档是,如果您要回到位置 0,然后保存流或在需要原始大小的地方使用它——它会比您最初阅读的更大。
-
我不相信 Seek 实际上会改变文件本身的任何内容...如果您写入文件,它就会增长。请注意,无论如何您都应该打开
FileAccess.Read的文件,因此没有任何操作会更改文件...查看参考源以获取确切的详细信息。
标签: c# .net filestream seek