Thanks, -Bob
Handle.Search is a bit overoptimistic. Merely opening a file
does not read in the contents and it doesn't present you with
magical find/replace functionality. If you were to read the
file contents into a string buffer, Pos would work on that.
As for TStrings.LoadFromFile, loading binary data into a string
buffer is unlikely to work well. It's quite possible that the
string will be truncated after the first nul character. But you
don't say how exactly you're trying to get at the text anyway.
Guessing from that Handle.Search, you may have a glitch there,
too.
Groetjes,
Maarten Wiltink
If you are happy reading the file 'all in one go' into a TStringList,
then you should have no worries about reading it into a String
More after sample code :-
Const FileName = 'c:\t\test.dat';
Const TestData = 'ABCDEFGHIJKTESTDATA';
procedure TForm1.Button1Click(Sender: TObject);
Var
FS :TFileStream;
S :String;
begin
// Create a file - if necessary
If FileExists( FileName ) = False Then
Begin
FS := TFileStream.Create( FileName, fmCreate );
FS.Position := 0;
S := TestData;
FS.Write( S[1], Length( S ) );
FS.Free;
ShowMessage( 'Created:' + S );
End;
// So we definitely have a file by now
FS := TFileStream.Create( FileName, fmOpenReadWrite );
FS.Position := 0; // not really needed
SetLength( S, FS.Size );
FS.Read( S[1], FS.Size );
// Replace
S := StringReplace( S, 'A', '{A}', [rfReplaceAll] );
// Put back to Disk
FS.Position := 0; // essential
FS.Write( S[1], Length( S ) );
FS.Size := Length( S ); // We may have shortened the file
FS.Free;
//
ShowMessage( 'New Data:' + S );
end;
// ---- End of Code ---
You could have done just the same using FileOpen, FileRead, FileWrite
Note that the Handle that they use is a DOS style File Handle, nothing
to do with Windows Handles
Also, unless you are absolutely certain that the file will be fairly
small, it is incredibly bad practise to 'wolf' an entire file into
memory.
That makes things a bit more complicated, but the use of Pos(), Move()
and Delete() in conjunction with two largish Strings should get round
that inconvenience. (Don't use String replace on partial strings)
HTH
-Bob
>This worked great except for
> S := StringReplace( S, 'A', '{A}', [rfReplaceAll] );
>Dont know why... I test it with sample data and it worked fine but when used
>on the small binary file it couldn't find the text?
>
RTFM
- or at least the File
Apologies - you were quite right
I've just checked
- StringReplace appears to use AnsiStrPos which is one of those
idiotic #0 terminated string routines
This is basically a bug in the Delphi Library
StringReplace does not handle #0 properly
- it bugs out after the first #0
Here is a proper alternative
( See StrReplaceStr below )
I suggest that you run it through a few tests, as I cut it out of my
existing libraries
{#################################################################
Result := InStr( 2, 'ABCDEF', 'BCD' ) rev: 20/6/02 JF
}
Function InStr( Start:Integer; Const BigStr,SmallStr:String):Integer;
Var
L9, L8, Max, P: Integer;
BigL, SmallL: Integer;
C : Char;
Begin
Result := 0; // Set Default
// Should be illegal
If Start <= 0 Then
Start := 1;
// Take String Lengths
BigL := Length( BigStr );
SmallL := Length( SmallStr );
// '' Target always returns 0
If BigL = 0 Then
Exit;
// '' Convention returns Start
If SmallL = 0 Then
Begin
Result := Start;
Exit;
End;
// Find last possible Start pos
Max := BigL - SmallL + 1;
If Max < Start Then
Exit;
// Take First Char of Search String
C := SmallStr[1];
// Hunt Forwards for a match
For L9 := Start To Max Do
If BigStr[L9] = C Then // If first Char Found
Begin
P := L9 + SmallL - 1;
For L8 := SmallL DownTo 2 Do // Scan Backwards
Begin
If BigStr[P] <> SmallStr[L8] Then
Break;
P := P - 1;
End;
// Success - we know first Char matches
If P = L9 Then
Begin
Result := L9;
Break;
End;
End;
End;{InStr}
{
########################################################################
also see: SysUtils.StringReplace - which fails on #0
}
Function StrReplaceStr( Const Tgt, OldStr, NewStr :String ):String ;
Var
Q, L : Integer ;
S : String ;
Begin
If OldStr = '' Then // Nasty Error
Begin
Result := Tgt ;
Exit;
End;
L := Length( OldStr ) ;
S := Tgt ;
Q := 1 ;
Q := Instr( Q, S, OldStr ) ;
While Q > 0 Do
Begin
S := Copy( S, 1, Q-1 ) + NewStr + Copy( S, Q + L, MAXINT ) ;
Q := Q + Length( NewStr ) ;
Q := Instr( Q, S, OldStr ) ;
End; {While}
Result := S ;
End; {StrReplaceStr}
Const FileName = 'c:\t\test.dat';
Const TestData = 'ABCDE'#0'FGHIJK'#1'TESTDATA';
procedure TForm1.Button1Click(Sender: TObject);
Var
FS :TFileStream;
S :String;
begin
// Create a file - if necessary
If FileExists( FileName ) = False Then
Begin
FS := TFileStream.Create( FileName, fmCreate );
FS.Position := 0;
S := TestData;
FS.Write( S[1], Length( S ) );
FS.Free;
ShowMessage( 'Created:' + S );
End;
// So we definitely have a file by now
FS := TFileStream.Create( FileName, fmOpenReadWrite );
FS.Position := 0; // not really needed
SetLength( S, FS.Size );
FS.Read( S[1], FS.Size );
// Replace
S := StrReplaceStr( S, 'A', '{A}'#0 );