2010-08-15 27 views
5

Trong khi chuyển một số mã từ Delphi 7 sang Delphi 2010, tôi đã viết lại hàm LoadTextFromFile() của mình.Delphi 2010 có chức năng LoadTextFromFile không?

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; 

Khi một ý nghĩ đánh vào đầu tôi: phải có thứ gì đó như thế này trong thư viện chuẩn. Nhiều người dùng muốn đọc một tệp văn bản thành một chuỗi, nhưng tôi không thể tìm thấy một hàm chuẩn như vậy. Gần nhất tôi đến là sử dụng TStringlist để tải văn bản. Nhưng A) tạo ra một TStringlist trông không cần thiết và B) Tôi không muốn bị chi phí từ TStringlist.

Câu hỏi: có chức năng LoadTextFromFile tiêu chuẩn trong Delphi 2010 không?

+0

Ngay cả trong Delphi 7, bạn không cần phải làm tất cả những gì. Sử dụng 'TStringStream' thay vì' TFileStream' và sử dụng câu trả lời của Marco. Ngoài ra, tôi tò mò: Trong trường hợp nào bạn đã từng thấy rằng thuộc tính 'Position' không phải là 0 ngay lập tức sau khi tạo một luồng, sao cho bạn cần phải trừ nó khỏi' Kích thước' để tính 'lSize'? –

+0

Hi Rob, Trong Delphi 7 Tôi đã có thể tải/lưu vào các tập tin UTF8. Và quan trọng hơn là tôi không biết về TStringStream. Vị trí không cần phải ở đó. Đó là vì tôi đã sao chép một số mã trong phương thức TStrings.Loadfromstream có vị trí trong đó. Ngoài ra còn có một lỗi trong mã của tôi vì nó không xử lý các tập tin với BOM. Vì vậy, bất cứ ai nghĩ về việc sử dụng ví dụ của tôi: không. Sử dụng TFile.ReadAllText thay thế. –

Trả lời

14

Có tồn tại một chức năng giống như vậy trong Delphi 2010, được gọi là ReadAllText và là một phần của bản ghi TFile được khai báo trong đơn vị IOUtils.

Kiểm tra khai

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

này xem mẫu này

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

Cảm ơn, chỉ là những gì tôi đang tìm kiếm. Trong tò mò: khi IOUtils và TFile được thêm vào Delphi ở đâu? –

+1

@Jan Derk: Delphi 2010. –

+2

Tôi đã nhận thấy rằng TFile.ReadAllText đặt khóa độc quyền trên tệp khi đọc tệp. Tôi đã có thể ưa thích một khóa fmShareDenyWrite. –

4

TStringStream.LoadFromStream/file? Dù sao dây rất lớn luôn luôn là một chút lãng phí. Bạn phải rất cẩn thận để không vô tình sao chép nó.

1

Một cách nhanh chóng là TStringList.LoadFromFile(). Sau đó sử dụng TStringlist.Text để truy cập dữ liệu dưới dạng một chuỗi lớn. Đừng quên tạo/miễn phí, lý tưởng nhất là sử dụng try..finally block.

+2

Phương pháp này đòi hỏi nhiều lần kích thước của tệp và tôi sẽ không đề xuất tệp này cho các tệp lớn. –

2

Tôi đã thử giải pháp tương tự, nhưng đã biến lEncoding biến lớp thành liên tục, vì vậy tôi sẽ lưu tệp của mình vào cùng một mã hóa như tôi đã đọc. Tuy nhiên, cuộc gọi đến GetBufferEncoding sẽ không thành công nếu lEncoding đã được đặt thành thứ gì đó (vì nó sẽ là nếu tệp trước đó được đọc). Vì vậy, trước tiên, tôi đã cố gắng giải phóng nó và điều đó đã gây ra các vi phạm truy cập khắp nơi. Bây giờ tôi chỉ cần thiết lập nó để nil trước khi thực hiện cuộc gọi thứ hai và nó có vẻ làm việc.

Something như thế này:

if Assigned(lEncoding) then begin 
    lEncoding := nil; 
end; 
GetBufferedEncoding(buffer, lEncoding); 
Các vấn đề liên quan