{ LH> Very nice - and a dandy tutorial on OOP streaming. Thanks for the compliment. LH> My little step-up speeds things up by 3x, but I imagine yours is LH> a hefty margin faster than that. I further modified the original and my streaming version to send their outputs to a text file. In the original I used a variable of type Text, and in the streaming version, I used a variable of type pBufStream. This was to eliminate any screen scrolling delays. I ran both versions on COMMAND.COM, which has a file size of 47845 bytes on my system. In going back over my code, I also noticed that I had declared the read buffer as vInByte: BYTE. I changed this to vInChar: CHAR and eliminated the call to Chr(vInByte) when appending characters to the result string. The original took 243201.838 ms and the streaming version took 2351.532 ms to scan the file. The absolute numbers are less important than the ratio, which is 103.423. So in this instance the use of streams and in-memory searching resulted in a speed-up of almost 104x. I tried buffer sizes of 512 to 16384 bytes in increments of 512 bytes and found that 8192 was optimum on my system. The worst buffer size was 1024 bytes. This required 2765.426 ms to scan the file, an increase of 17.6% over the optimum. This was a very interesting and unexpected result, given that 1024 is the figure used in the TV and OWL documentation. Of course, this is probably very system dependent. I run dual IDE drives, one formatted FAT and the other formatted OS/2 HPFS. The above results were obtained off the FAT drive. On the HPFS drive, the best time was turned in by a buffer size of 4608 bytes. This size had given the second-best results on the FAT drive at 2368.464 ms, but clocked in on the HPFS drive at 2373.780. Using an 8192 byte buffer on the HPFS drive resulted in a time of 2449.082 ms. Comparing the speeds on the FAT and HPFS drives in this case isn't really apples and apples, since the two drives are from different manufacturers. A better test would be to use two logical partitions on the same drive. Even at that though the average boost in speed was around 100x over the original. } PROGRAM FindStr; (* Searches any file for printable strings of 6 or more characters. *) (* Useful for extracting messages and internal documentation from .EXE's *) USES Objects; VAR vInFile, vOutFile : pBufStream; vMemFile : pMemoryStream; vS : STRING; vInChar : CHAR; BEGIN vInFile := New(pBufStream, Init(ParamStr(1), stOpenRead, 8192)); IF vInFile = NIL THEN BEGIN WriteLn('Unable to open input file'); Halt; END; vOutFile := New(pBufStream, Init(ParamStr(2), stCreate, 8192)); IF vOutFile = NIL THEN BEGIN WriteLn('Unable to create output file'); Dispose(vInFile, Done); Halt; END; vMemFile := New(pMemoryStream, Init(vInFile^.GetSize, 8192)); IF vMemFile = NIL THEN BEGIN WriteLn('Insufficient memory'); Dispose(vInFile, Done); Dispose(vOutfile, Done); Halt; END; vInFile^.Seek(0); vOutFile^.Seek(0); vMemFile^.CopyFrom(vInFile^, vInFile^.GetSize); IF vInFile <> NIL THEN Dispose(vInFile, Done); vMemFile^.Seek(0); WriteLn('>>Searching ', ParamStr(1),'<<'); WITH vMemFile^ DO WHILE (Status = stOK) DO BEGIN vS := ''; Read(vInChar, 1); WHILE ((vInChar > #31) AND (vInChar < #127) AND (Status = stOK)) DO BEGIN vS := vS + vInChar; Read(vInChar, 1); END; IF Length(vS) > 5 THEN BEGIN vS := vS + #13#10; vOutFile^.Write(vS[1], Length(vS)); END; END; IF vMemFile <> NIL THEN Dispose(vMemFile, Done); IF vOutFile <> NIL THEN Dispose(vOutFile, Done); WriteLn('>>End of file<<'); END.