Click here to Skip to main content
15,906,341 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Dear Buddies:

I wonder if you could tell me about a class and its members that provides direct access to a records of a data file instead of sequential access.

for example I have one data file that each record consist of 4 sections. I want to open a file and without reading the all file I want to access to record no. 19 without reading records 1 to 18. In FORTRAN language we have option for this setting in the OPEN command. But I do not know the corresponding command in C#.





Yours
Posted
Updated 8-Mar-12 0:26am
v3
Comments
OriginalGriff 8-Mar-12 6:19am    
That's not really a question we can answer just like that - it depends on what kind of data file you are talking about, and how you want to access it.
Use the "Improve question" widget to edit your question and provide better information.
Mmohmmad 8-Mar-12 6:31am    
Dear OriginalGriff:

I modify the question. If you still think that my question is not clear to you do not hesitate to inform me.

Yours
Mahdavi

There is no direct way to do that, but you can use a BinaryReader and Position it's underlying stream:
C#
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();
It's rare these days to use record-based files directly: mostly we would go via a DB or an XML file instead.
 
Share this answer
 
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();
}


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;


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).
 
Share this answer
 
Comments
Mmohmmad 8-Mar-12 7:23am    
Dear My friends:

Your responds are really awsome. However, I think if I explain my challenge for you, I will get better result. My records are as follow:

record1:
1. some string
2. some image file that must write as bytes
3. some sound attached to this record

record2:
1. some string
2. some image file that must write as bytes
3. some sound attached to this record

record3:
1. some string
2. some image file that must write as bytes
3. some sound attached to this record

.
.
.
all these records paste to 3 richtextboxes and these textboxes.text are read and then write to a data file in the format of binary.
so firstly, the lenght of each section of a record is not specific.
secondly, if I close the file, and I want to add some other records to the current file, I must find the no. of last record and add additional records to the file. So is it a straight forward procedure for doing this?
Finally, if I want to encrypt this file is it possible for others to extract it's
content?

Sincerely
BobJanova 8-Mar-12 9:48am    
If you don't have any known location where you can read the starting location of all the records, you're pretty much screwed. You have to read sequentially through the file, up to the point you want, at least once to find all the places where the records start.

This is a consequence of a nice human-readable text format.

However, I'm guessing the file is so small (anything under megabytes) that just reading it sequentially and loading the whole object structure into memory and manipulating it there would be fine.
If all records have the same length, you can access a specific record with FileStream.Seek()

C#
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
C#
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.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900