Author: Jonas Bilinkevicius How to determine whether a string contains binary data or normal readable text Answer: Solve 1: Well, actually there is not really a difference between binary and not. There is just a common "agreement" that everything below ASCII code 32 is a "binary" character. 1 function IsReadable(st: string): Boolean; 2 var 3 i: Integer; 4 begin 5 Result := false; 6 for i := 1 to Length(st) do 7 if st[i] < #32 then 8 Exit; 9 Result := true; 10 end; Solve 2: 11 procedure GetVeryBasicFileType(const Path: string; 12 var VeryBasicFileType: LongWord); overload; 13 var 14 Fs: TFileStream; 15 ExtCharCount, NothingCount, SpaceCount, LfCount, i, DidRead: Word; 16 LastB, 17 B: byte; 18 ReadBuffer: array[0..MAX_FILE_DETECT_BUFFER] of byte; 19 begin 20 VeryBasicFileType := VERY_BASIC_FILETYPE_UNKNOWN; 21 if (FileExists(Path)) then 22 begin 23 Fs := TFileStream.Create(Path, fmOpenRead); 24 try 25 if (Fs.Size >= 1) then 26 begin 27 LfCount := 0; 28 ExtCharCount := 0; 29 SpaceCount := 0; 30 NothingCount := 0; 31 LastB := 0; 32 Fs.Seek(0, soFromBeginning); 33 DidRead := Fs.read(ReadBuffer, SizeOf(ReadBuffer)); 34 for i := 0 to DidRead - 2 do 35 begin 36 B := ReadBuffer[i]; 37 if (B < 1) then 38 Inc(NothingCount) 39 else if (((B < 32) or (B > 127)) and not (B in [$0A, $0D, $21])) then 40 Inc(ExtCharCount) 41 else if ((B = $0A) or (B = $0D)) then 42 Inc(LfCount) 43 else if ((B = $21) and (LastB <> $21)) then 44 Inc(SpaceCount); 45 LastB := B; 46 end; 47 if (NothingCount > (DidRead div 30)) then 48 begin 49 if ((DidRead >= 4) and ((ReadBuffer[0] = $FF) and (ReadBuffer[1] = $FE)) 50 or 51 ((ReadBuffer[0] = $FE) and (ReadBuffer[1] = $FF))) then 52 begin 53 VeryBasicFileType := VERY_BASIC_FILETYPE_TEXT_UNICODE; 54 Exit; 55 end 56 else 57 begin 58 VeryBasicFileType := VERY_BASIC_FILETYPE_BINARY; 59 Exit; 60 end; 61 end; 62 if (ExtCharCount > (DidRead div 3)) then 63 begin 64 if ((LfCount >= (DidRead div 60)) or (SpaceCount > (DidRead div 6))) then 65 VeryBasicFileType := VERY_BASIC_FILETYPE_TEXT 66 else 67 VeryBasicFileType := VERY_BASIC_FILETYPE_BINARY; 68 end 69 else 70 begin 71 if ((ReadBuffer[0] = $EF) and (ReadBuffer[1] = $BB) and 72 (ReadBuffer[2] = $BF) and (LfCount > (DidRead div 60))) then 73 VeryBasicFileType := VERY_BASIC_FILETYPE_TEXT_UTF8 74 else 75 VeryBasicFileType := VERY_BASIC_FILETYPE_TEXT; 76 end; 77 end 78 else 79 VeryBasicFileType := VERY_BASIC_FILETYPE_EMPTY; 80 finally 81 Fs.Free; 82 end; 83 end; 84 end;