如何正确使用FileRead,FileWrite,缓冲区(或使用TFileStream)。
我需要将整个文本文件读取到String,然后将String写回此文件(将其替换为新字符串)。
答案 0 :(得分:11)
TStringList
就是您想要的。
如果您只想将其视为单个字符串blob,则有TStringStream
。
Stream := TStringStream.Create('', TEncoding.UTF8);
Try
Stream.LoadFromFile('c:\desktop\in.txt');
ShowMessage(Stream.DataString);
Stream.Clear;
Stream.WriteString('Greetings earthlings!');
Stream.SaveToFile('c:\desktop\out.txt');
Finally
Stream.Free;
End;
答案 1 :(得分:5)
将文件读入字符串的最简单,最简单的方法是使用TStringList,如下所示:
sl := TStringList.Create;
try
sl.LoadFromFile('C:\myfile.txt');
//String can be read and modified using the Text property:
oldString := sl.Text;
sl.Text := 'foo bar';
//Text can be written back to the file using:
sl.WriteToFile('C:\myfile.txt');
finally
sl.Free;
end;
正如您在问题下面的评论中所指出的,这可能最终会改变您的字符串中的换行符 - 因此,根据您尝试阅读/执行的操作,您需要注意这一点。
答案 2 :(得分:2)
我的一些实用程序例程(您可以从我的网站上完整下载代码)...
//------------------------------------------------------------------------------
// CsiStrToBytes
//
// Convert pInStr to an array of bytes using the string encoding
// pStringEncoding (one of automatic, Ansi, UTF-16, or UTF-8) and optionally
// include the byte order mark according to the pIncludeBom flag
//------------------------------------------------------------------------------
function CsiStrToBytes(const pInStr: string;
pStringEncoding: TECsiStringEncoding;
pIncludeBom: Boolean): TByteDynArray;
var
{$IFDEF UNICODE}
lStringEncoding: TECsiStringEncoding;
lStringStream: TStringStream;
lPreambleBytes: TBytes;
lStringBytes: TBytes;
lPreambleLen: Integer;
lStringLen: Integer;
{$ENDIF}
lLen: Integer;
{$IFDEF UNICODE}
lIndex: Integer;
{$ENDIF}
begin
if pInStr <> '' then begin
{$IFDEF UNICODE}
if pStringEncoding = seAuto then
lStringEncoding := CsiGetPreferredEncoding(pInStr)
else
lStringEncoding := pStringEncoding;
// UTF-8 and UTF-16 encoding can be handled by the TStringStream class
if (lStringEncoding = seUtf8) or (lStringEncoding = seUtf16) then begin
if lStringEncoding = seUtf8 then
lStringStream := TStringStream.Create(pInStr, TEncoding.Utf8)
else
lStringStream := TStringStream.Create(pInStr, TEncoding.Unicode);
try
// add the UTF-8 or UTF-16 byte order mark to the start of the array of
// bytes if required
if pIncludeBom then
lPreambleBytes := lStringStream.Encoding.GetPreamble
else
SetLength(lPreambleBytes, 0);
lStringBytes := lStringStream.Bytes;
lPreambleLen := Length(lPreambleBytes);
lStringLen := Length(lStringBytes);
SetLength(Result, lPreambleLen + lStringLen);
if lPreambleLen > 0 then
Move(lPreambleBytes[0], Result[0], lPreambleLen);
if lStringLen > 0 then
Move(lStringBytes[0], Result[lPreambleLen], lStringLen);
finally
lStringStream.Free;
end;
end else begin
{$ENDIF}
// Ansi encoding must be handled manually
lLen := Length(pInStr);
SetLength(Result, lLen);
{$IFDEF UNICODE}
for lIndex := 1 to lLen do
Result[lIndex - 1] := Ord(pInStr[lIndex]) and $00ff;
{$ELSE}
Move(pInStr[1], Result[0], lLen);
{$ENDIF}
{$IFDEF UNICODE}
end;
{$ENDIF}
end else
SetLength(Result, 0);
end;
//------------------------------------------------------------------------------
// CsiSaveToFile
//
// Saves pData, an array of bytes, to pFileName
//------------------------------------------------------------------------------
procedure CsiSaveToFile(const pData: TByteDynArray; const pFileName: string);
var
lFileStream: TFileStream;
lLen: Integer;
begin
lFileStream := TFileStream.Create(pFileName, fmCreate);
try
lLen := Length(pData);
if lLen > 0 then
lFileStream.WriteBuffer(pData[0], lLen);
finally
lFileStream.Free;
end;
end;
//------------------------------------------------------------------------------
// CsiSaveToFile
//
// Saves pText to pFileName using the string encoding pStringEncoding, which is
// one of automatic, Ansi, UTF-16, or UTF-8
//------------------------------------------------------------------------------
procedure CsiSaveToFile(const pText: string; const pFileName: string;
pStringEncoding: TECsiStringEncoding);
begin
CsiSaveToFile(CsiStrToBytes(pText, pStringEncoding), pFileName);
end;
答案 3 :(得分:2)
以下两个功能正在执行您想要的任务:
function StringFromFile(const FileName: TFileName): RawByteString;
var F: THandle;
Size: integer;
begin
result := '';
if FileName='' then
exit;
F := FileOpen(FileName,fmOpenRead or fmShareDenyNone);
if PtrInt(F)>=0 then begin
{$ifdef LINUX}
Size := FileSeek(F,0,soFromEnd);
FileSeek(F,0,soFromBeginning);
{$else}
Size := GetFileSize(F,nil);
{$endif}
SetLength(result,Size);
if FileRead(F,pointer(Result)^,Size)<>Size then
result := '';
FileClose(F);
end;
end;
function FileFromString(const Content: RawByteString; const FileName: TFileName;
FlushOnDisk: boolean=false): boolean;
var F: THandle;
L: integer;
begin
result := false;
F := FileCreate(FileName);
if PtrInt(F)<0 then
exit;
if pointer(Content)<>nil then
L := FileWrite(F,pointer(Content)^,length(Content)) else
L := 0;
result := (L=length(Content));
{$ifdef MSWINDOWS}
if FlushOnDisk then
FlushFileBuffers(F);
{$endif}
FileClose(F);
end;
他们使用低级FileOpen / FIleSeek / FileRead / FileWrite函数。
您可以指定所需的任何fmShare*
选项。
它使用RawByteString
类型,因此它希望以面向字节的方式处理文本。它不适用于Unicode文本文件,但使用Ansi Text。如果你想从Delphi 2009开始使用字符串类型与它进行交互,你必须设置适当的代码页。
在Delphi 2009之前,只需定义:
type
RawByteString = AnsiString;
答案 4 :(得分:1)
添加了使用FileXXX功能系列的请求示例。
关于使用RawByteString
和文件I / O的注意事项 - 它完全有效。
另一个注意事项:为了简化低级代码,我省略了一些错误检查断言,以防止发生错误的可能性较小。注意事项!
const
FileName = 'Unit14.pas'; // this program is a stuntmaster,
// reads and writes its own source
procedure TForm14.FormClick(Sender: TObject);
var
Stream: TFileStream;
Buffer: RawByteString;
begin
Stream := TFileStream.Create(FileName, fmOpenReadWrite or fmShareExclusive);
// read entire file into string buffer
SetLength(Buffer, Stream.Size);
Stream.ReadBuffer(Buffer[1], Stream.Size);
// do something with string
OutputDebugString(PChar(Format('Buffer = "%s"', [Buffer])));
// prepare to write
Stream.Position := 0; // rewind file pointer
Stream.Size := 0; // truncate the file
// write entire string into the file
Stream.WriteBuffer(Buffer[1], Length(Buffer));
Stream.Free;
end;
// on right click - do exactly the same but using low-level FileXXX calls
procedure TForm14.FormContextPopup(Sender: TObject; MousePos: TPoint; var
Handled: Boolean);
var
Handle: Integer;
Size: Cardinal;
Buffer: RawByteString;
Transferred: Integer;
begin
Handle := FileOpen(FileName, fmOpenReadWrite or fmShareExclusive);
Assert(Handle >= 0);
// read entire file into string buffer
Size := GetFileSize(Handle, nil);
Assert(Size <> INVALID_FILE_SIZE);
SetLength(Buffer, Size);
Transferred := FileRead(Handle, Buffer[1], Size);
Assert(not (Transferred < Size));
// do something with string
OutputDebugString(PChar(Format('Buffer = "%s"', [Buffer])));
// prepare to write
FileSeek(Handle, 0, 0); // rewind file pointer
SetEndOfFile(Handle); // truncate the file
// write entire string into the file
Transferred := FileWrite(Handle, Buffer[1], Length(Buffer));
Assert(not (Transferred < Length(Buffer)));
FileClose(Handle);
end;