且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何直接访问文件而不是顺序访问

更新时间:2023-12-03 08:36:28

尚无直接方法,但可以使用BinaryReader并将其基础流定位:
There is no direct way to do that, but you can use a BinaryReader and Position it''s underlying stream:
BinaryReader br = new BinaryReader(File.OpenRead(@"D:\Temp\MyList.txt"));
int recordLength = 16;
br.BaseStream.Position = recordLength * 3;
byte[] record = br.ReadBytes(recordLength);
foreach (byte b in record)
    {
    Console.Write((char) b);
    }
Console.WriteLine();

如今很少有直接使用基于记录的文件的情况:大多数情况下,我们会通过DB或XML文件.

It''s rare these days to use record-based files directly: mostly we would go via a DB or an XML file instead.


如果(且仅当)您如果知道要读取的记录的起始位置(以字节为单位),则可以在文件中进行随机访问以找到它. Griff已经发布了一种方法,我更喜欢直接使用FileStream:

If (and only if) you know the starting location of the record you want to read (in bytes), you can do random access in the file to find it. Griff already posted one way to do it, I prefer to use the FileStream directly:

FileStream fs = new FileStream("test.dat", FileMode.Open);
try {
 int recordStart = some way to get the position of the record;
 fs.Position = recordStart;
 int recordLength = some way to get the record size;
 byte[] buf = new byte[recordLength];
 fs.Read(buf, 0, recordLength);
} finally {
 fs.Close();
}



这样做或使用BinaryReader本质上是样式问题,它们执行相同的工作.

如果文件的记录长度是固定的,那么获取recordStart和recordLength并不容易:



Doing that or using the BinaryReader is essentially a matter of style, they do the same job.

If your file is fixed record length, getting recordStart and recordLength is trivial:

const int recordStart = 80;
int recordStart = index * recordLength;



如果它的长度可变,但具有交叉引用表,则需要先读取该表以获取所有记录的起始偏移量,然后从表或记录的开头确定长度(如果有的话)已指定.

如果您不了解记录长度,则可以开始并读取数据,直到确定已读取完整记录(例如找到\ r \ n对或EOF)为止.

我对Fortran不熟悉,所以我不知道您要加载的数据的格式是什么,但听起来是固定格式.***将整个记录集包装在一个类中,以使文件处理处于保密状态,根据您的要求(例如,文件共享,资源限制,请求记录的频率等).



If it''s variable length but with a cross reference table, you need to read that table first to get all the record start offsets, and then determine the length either from the table or from the start of a record, if it''s specified.

If you don''t have pre-knowledge of the record length, you can start and read data until you determine that you''ve read a complete record (e.g. found a \r\n pair or EOF).

I''m not familiar with Fortran so I don''t know what the format of the data you''re trying to load is, but it sounds fixed format. It might be worth wrapping the whole record set in a class which keeps the file handling under wraps, either keeping a FileStream open for its whole lifetime or opening and closing it each time a record is requested, depending on your requirements (i.e. file sharing, resource limits, how often records are asked for etc).


如果所有记录的长度都相同,则可以使用FileStream.Seek()
访问特定记录.
If all records have the same length, you can access a specific record with FileStream.Seek()

FileStream f = new FileStream("foo.dat", FileMode.Open, FileAccess.Read);

f.Seek(size_of_your_record_in_bytes * record_index, SeekOrigin.Begin);



要到达文件末尾,请尝试



To reach the end of file try

FileStream f = new FileStream("foo.dat", FileMode.Open, FileAccess.Write);
f.Seek(0, SeekOrigin.End);
f.Write(...);



如果记录的大小不同,则需要另一种方法,例如将记录大小保存为记录的第一个元素,以了解要查找下一个元素的距离.



If your records have different size you need another approach, like saving the record size as the first element of your record to know how far you have to seek for the next element.