2010-08-15 9 views
5

Während ich etwas Code von Delphi 7 nach Delphi 2010 portierte, schrieb ich meine LoadTextFromFile() Funktion um.Hat Delphi 2010 eine LoadTextFromFile-Funktion?

function LoadTextFromFile(const aFullFileName: string): string; 
var 
    lBuffer:  TBytes; 
    lEncoding: TEncoding; 
    lFileStream: TFileStream; 
    lSize:  Integer; 

begin 

    if not FileExists(aFullFileName) then 
    begin 
    raise Exception.Create('File "' + aFullFileName + '" not found.'); 
    end; 

    lFileStream := TFileStream.Create(aFullFileName, fmOpenRead + fmShareDenyNone); 
    try 

    if lFileStream.Size <= 0 then 
    begin 
     Result := ''; 
    end 
    else 
    begin 

     lSize := lFileStream.Size - lFileStream.Position; 

     SetLength(lBuffer, lSize); 

     // Read file into TBytes buffer 
     lFileStream.Read(lBuffer[0], lSize); 

     // Read encoding from buffer 
     TEncoding.GetBufferEncoding(lBuffer, lEncoding); 

     // Get string from buffer 
     Result := lEncoding.GetString(lBuffer); 

    end; 

    finally 
    lFileStream.Free; 
    end; 

end; 

Wenn mir ein Gedanke durch den Kopf schlagen war: Es muss so etwas wie dies in der Standardbibliothek sein. Viele Benutzer möchten eine Textdatei in eine Zeichenfolge lesen, aber ich konnte eine solche Standardfunktion nicht finden. Am nächsten kam ich mit TStringlist, um Text zu laden. Aber A) das Erstellen einer TStringlist sieht unnötig aus und B) Ich möchte nicht den Overhead von TStringlist erleiden.

Frage: Gibt es eine standardmäßige LoadTextFromFile-Funktion in Delphi 2010?

+0

Auch in Delphi 7, Sie nicht alles, was zu tun hatte. Verwenden Sie einen 'TStringStream' anstelle von' TFileStream' und verwenden Sie Marcos Antwort. Ich bin auch neugierig: Unter welchen Umständen haben Sie jemals festgestellt, dass die 'Position'-Eigenschaft unmittelbar nach dem Erstellen eines Streams nicht Null war, so dass Sie sie von' Size' abziehen müssten, um 'lSize' zu ​​berechnen? –

+0

Hallo Rob, in Delphi 7 musste ich in UTF8-Dateien laden/speichern können. Und noch wichtiger: Ich wusste nichts von TStringStream. Die Position muss nicht da sein. Es ist da, weil ich etwas Code aus der TStrings.Loadfromstream-Methode kopiert habe, die die Position darin hat. Es gibt auch einen anderen Fehler in meinem Code, da er keine Dateien mit BOM verarbeitet. Also jemand, der darüber nachdenkt, mein Beispiel zu verwenden: nicht. Verwenden Sie stattdessen TFile.ReadAllText. –

Antwort

14

Ja gibt es eine Funktion wie diese in Delphi 2010, heißt ReadAllText und ist Teil der TFile Datensatz in der IOUtils Einheit deklariert.

prüfen diese Erklärung

class function ReadAllText(const Path: string): string; overload; inline; static; 
class function ReadAllText(const Path: string; const Encoding: TEncoding): string; overload; inline; static; 

sehen diese Probe

program Project80; 

{$APPTYPE CONSOLE} 

uses 
    IOUtils, 
    SysUtils; 
Var 
Content : string; 
begin 
    try 
    Content:=TFile.ReadAllText('C:\Downloads\test.css'); //load the text of the file in a single line of code 
    //Content:=TFile.ReadAllText('C:\Downloads\test.css',TEncoding.UTF8); //you can an encoding too. 
    Writeln(Content); 
    Readln; 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
end. 
+0

Danke, genau das, was ich gesucht habe. Aus Neugier: Wann haben IOUtils und TFile zu Delphi hinzugefügt? –

+1

@Jan Derk: Delphi 2010. –

+2

Ich habe festgestellt, dass TFile.ReadAllText eine exklusive Sperre auf die Datei beim Lesen setzt. Ich hätte eine fmShareDenyWrite-Sperre bevorzugt. –

4

TStringStream.LoadFromStream/Datei? Jedenfalls sind sehr große Saiten immer etwas verschwenderisch. Sie müssen sehr vorsichtig sein, um es nicht versehentlich zu kopieren.

1

Ein schneller Weg ist TStringList.LoadFromFile(). Verwenden Sie dann TStringlist.Text, um auf die Daten als eine große Zeichenfolge zuzugreifen. Vergessen Sie nicht zu erstellen/frei, idealerweise mit einem try..finally Block.

+2

Diese Methode erfordert ein Vielfaches der Größe der Datei, und ich würde es nicht für große Dateien empfehlen. –

2

Ich versuchte die gleiche Lösung, aber machte lEncoding eine Klassenvariable, um es persistent zu machen, also würde ich meine Datei auf die gleiche Codierung speichern, wie ich es gelesen habe. Der Aufruf an GetBufferEncoding führt jedoch nichts aus, wenn lEncoding bereits auf etwas festgelegt ist (wie es wäre, wenn eine vorherige Datei gelesen wurde). Also, zuerst habe ich versucht, es zu befreien und das verursachte Zugriffsverletzungen überall. Jetzt setze ich es einfach auf Null, bevor ich den zweiten Anruf mache und es scheint zu funktionieren.

Etwas wie folgt aus:

if Assigned(lEncoding) then begin 
    lEncoding := nil; 
end; 
GetBufferedEncoding(buffer, lEncoding); 
Verwandte Themen