Contributor: ALEXANDER STAUBO { JB> AS>Use buffered streams. That way you can access fairly many records on JB> AS>disk without noticable speed degradation. JB> ^^^^^^^^^^^^^^^^^^^^^^^^^^^ JB> Do you mean from RAM?? Whoah! How do you go about using buffered JB> streams? Actually, you should write a local "cache" for your records. Ie., your implement an array of records, say 1..50, or, 1..MaxCacheSize, where MaxCacheSize is a defined constant. Then you have a couple of generalized procedures for putting/getting records; now, the point is, whenever the program asks for a record -that is in the cache-, that record is read directly from RAM. If the record is -not- in the cache, the record is read, and, if there is space in the cache, the record is inserted into the cache. Let's try a Pascal implementation. } const MaxCacheSize = 50; (* cache can hold 50 records *) type (* this is the cache item *) PCacheItem = ^TCacheItem; TCacheItem = record Offset : Longint; (* file offset of cache record *) Rec : TRecord; (* use your own record type here *) end; var Cache : array[1..MaxCacheSize] of PCacheItem; CacheSize : Word; procedure InitCache; {-Resets cache} begin CacheSize:=0; end; function FindCache (Offset : Longint) : PCacheItem; {-Returns cache item for Offset if found, otherwise nil} var W : Word; begin for W:=1 to CacheSize do if Cache[W]^.Offset = Offset then begin FindCache:=Cache[W]; Exit; end; FindCache:=nil; end; var F : file of TRecord; (* file in question *) procedure PutRecord (Offset : Longint; var Rec : TRecord); {-Put record into cache and file} var P : PCacheItem; begin Write(F, Rec); (* if exists in RAM (cache), update it *) P:=FindCache(Offset); if P <> nil then P^.Rec:=Rec else begin (* put into cache *) Inc(CacheSize); New(Cache[CacheSize]); Cache[CacheSize]^.Offset:=Offset; Cache[CacheSize]^.Rec:=Rec; end; end; procedure GetRecord (Offset : Longint; var Rec : TRecord); {-Get record from cached file} var P : PCacheItem; begin (* if exists in RAM (cache), get it *) P:=FindCache(Offset); if P <> nil then Rec:=P^.Rec else if CacheSize < MaxCacheSize then begin (* read record from file *) Read(F, Rec); (* put into cache *) Inc(CacheSize); New(Cache[CacheSize]); Cache[CacheSize]^.Offset:=Offset; Cache[CacheSize]^.Rec:=Rec; end; end; To use the routines: Assign(F, 'MYFILE.DAT'); Reset(F); GetRecord(FilePos(F), MyRec); GetRecord(FilePos(F), MyRec); GetRecord(FilePos(F), MyRec); PutRecord(FilePos(F), MyRec); Close(F); Or something like that, anyway. Now, there is a simpler way; "simpler" in this case means "some guy has already spent hours writing it just for you". The concept is called streams. Now, I don't know how "novice" a programmer you are, but knowledge of streams requires knowledge of OOP. I suggest you read about OOP right away. Streams work in a very simple way. You have a basic, "abstract" object, which provides some simple I/O tools. A stream is a type of (abstract) file, an input/output mechanism, that you may manipulate; most often it's on a hierarchical level, ie., the high-level procedures call low-level procedures, just like DOS. Think of streams as the Pascal type "file", except now the stream is a shell for anything. The shell implements a -standard- interface for any kind of information area. You have file streams, buffered streams (streams that caches areas of the file in memory to optimize access efficiency), EMS streams (yes, you can have a "virtual file" that lies in EMS memory and may be used just like a file), and so on. The standardization implies that you may write more flexible programs. A tiny example: var S : TBufStream; T : TRecord; Str : string; begin S.Init('MYFILE.DAT', stOpen, 2048); (* | | | file name file mode buffer size *) S.Read(T, SizeOf(T)); S.Write(T, SizeOf(T)); Str:=S.ReadStr^; S.Done; end; The corresponding boring-old-Dos example'd be: var F : file; T : TRecord; Str : string; begin (* note: no buffering -> slower! *) Assign(F, 'MYFILE.DAT'); Reset(F, 1); BlockRead(F, T, SizeOf(T)); BlockWrite(F, T, SizeOf(T)); Read(F, Str[0]); BlockRead(F, Str[1], Ord(Str[0])); Close(F); end; In the end, streams -are- simpler, too. And they are extremely fast; a friend of mine is writing a mail reader and is using object streams for the message/conference/etc. databases. Now, personally I use indexed, light-speed B-tree databases. And his work -just fine-.