The best approach here is probably to use memory mapped files.
First you need a file descriptor, to do this, use the CreateFile API function.
Then go to CreateFileMapping to get the file association descriptor. Finally, use MapViewOfFile to map the file in memory.
To process large files, MapViewOfFile can only display a specific range in memory, so you can, for example, map the first 32 MB, then use UnmapViewOfFile to unmount it, and then MapViewOfFile for the next 32 MB, etc. (EDIT: as indicated below, make sure that the blocks you overlap in this way overlap with a multiple of 4kb and at least as long as the length of the text you are looking for so that you don't skip any text that might be divided at the border of the block)
To perform an actual search when (part) of a file is mapped to memory, you can make a copy of the source for StrPosLen from SysUtils.pas (unfortunately, it is defined only in the implementation section and does not appear in the interface). Leave one copy as is and make another copy, replacing Wide with Ansi every time. In addition, if you want to be able to search in binaries that may contain embedded #0 , you can delete the (Str1[I] <> #0) and .
Either find a way to determine if the file is ANSI or Unicode, or simply call both versions of Ansi and Unicode for each displayed part of the file.
Once you are done with each file, be sure to call CloseHandle first in the file association descriptor, and then when processing the files. (And don't forget to call UnmapViewOfFile first).
EDIT:
The big advantage of using memory mapped files instead of using, for example. TFileStream, to read a file in memory in blocks, is that bytes will only be inserted into memory once.
Usually, when accessing a file, Windows first reads the bytes into the OS file cache. Then copies them from there to the application memory.
If you use memory mapped files, the OS can directly map physical pages from the OS file cache to the application address space without creating another copy (reducing the time it takes to copy and use memory).
Bonus answer: By calling StrLIComp instead of StrLComp, you can do a case insensitive search.