2012-09-10 34 views
6

Chuyển đổi từ D2007 để XE2, tôi chuyển đổi chức năng nàyLàm cách nào để đặt giá trị mặc định cho tham số chức năng của loại TEncoding?

function Add_Line(FileStream : TFileStream; ALine : string) : boolean; 

để

function Add_Line(FileStream : TFileStream; ALine : string; Enc: TEncoding = nil) : boolean; 
var 
    AStr: ANSISTring; 
begin 
    Result := True; 
    if Enc = nil then Enc := TEncoding.ANSI; 
    try 
//Old FileStream.WriteBuffer(Pointer(ALine)^, Length(ALine)); 
    if Enc = TEncoding.UTF8 then 
     AStr := UTF8Encode(ALine) 
    else 
     AStr := ANSIString(ALine); 
    FileStream.WriteBuffer(AStr[1], Length(ALine)); 
    end; 
    except 
    Result := False; 
    end; 
end; 

Lý do:

  • Thay đổi mã sử dụng Add_Line càng ít càng tốt

  • Chấp nhận sự thay đổi tự động sang Unic ode, chỉ vào phút cuối ghi các tập tin văn bản 8-bit (điều này được sử dụng trong XML và CSV). Trong tương lai, chúng tôi vẫn có thể chuyển sang các tệp UTF-16 nếu chúng tôi muốn.

tôi đã có thể thích để xác định cái gì đó như:

function Add_Line(FileStream : TFileStream; ALine : string; Enc: TEncoding = TEncoding.ANSI) : boolean; 

nhưng trình biên dịch phàn nàn ;-)

là bất cứ điều gì như thế có thể?

+2

Việc hạn chế tham số mặc định là giá trị không đổi là một lý do khiến tôi luôn ưu tiên sử dụng quá tải. –

+0

Quá tải không bao giờ vượt qua tâm trí của tôi ;-) –

Trả lời

12

đối số mặc định phải là một thời gian biên dịch không đổi, nhưng nếu bạn cần bất cứ điều gì cao cấp hơn, bạn có thể tạo ra quá tải:

function Add_Line(FileStream : TFileStream; ALine : string) : boolean; overload; 
function Add_Line(FileStream : TFileStream; ALine : string; Enc: TEncoding) : boolean; overload; 


function Add_Line(FileStream : TFileStream; ALine : string) : boolean; 
begin 
    Result := Add_Line(FileStream, ALine, TEncoding.ANSI); 
end; 

Bạn thậm chí có thể thêm từ khóa inline để có được chính xác mã được tạo tương tự mà các đối số mặc định sẽ có kết quả là nó hợp lệ.

Lưu ý: bạn dường như không hỗ trợ bất kỳ điều gì khác ngoài TEncoding.ANSITEncoding.UTF8. Trong trường hợp đó, thông số TEncoding có vẻ quá mức cần thiết, bạn có thể sử dụng thông số UTF8: Boolean để thay thế (hoặc làm lại mã của bạn để hoạt động với mã hóa tùy ý CodePage).

Note 2: FileStream.WriteBuffer(AStr[1], Length(ALine)); là sai vì Length(ALine)Length(AStr) không nhất thiết phải giống nhau, bạn nên sử dụng Length(AStr) để thay thế. Ngoài ra, AStr[1] có thể dẫn đến ngoại lệ khi AStr là một chuỗi trống, bạn có thể thêm trường hợp đặc biệt để chỉ gọi WriteBuffer khi AStr không trống.

+0

Để sử dụng trong tương lai, tôi sẽ để lại thông số TEncoding và cảm ơn bạn đã chỉ ra lỗi chính tả Length()! Có thể dẫn đến dữ liệu khủng khiếp ;-) –

5

Những người khác đã nhận xét về cách bạn có thể chỉ định giá trị mặc định cho thông số TEncoding. Tôi muốn chỉ ra rằng việc bạn sử dụng số TEncoding hoàn toàn sai.

TEncoding.UTF8 không phải là cách duy nhất bạn có thể có được đối tượng mã hóa UTF-8 (TEncoding.GetEncoding(65001) là một cách khác), vì vậy hãy kiểm tra TEncoding.UTF8 cụ thể là điều sai. Tệ hơn nữa, bạn hoàn toàn phớt lờ bất kỳ mã hóa không phải UTF8 nào và chỉ mã hóa everuthing khác thành một số AnsiString đơn giản, đánh bại toàn bộ mục đích sử dụng TEncoding. Ví dụ, một người dùng có thể chuyển vào một đối tượng mã hóa ISO-8859-X và đầu ra của bạn sẽ KHÔNG được mã hóa ISO như người dùng được yêu cầu.Bạn cũng có thể thay đổi thông số của bạn thành một tham số UseUTF8: Boolean = False thay vào đó, bởi vì đó là cách bạn được hiệu quả sử dụng nó:

function Add_Line(FileStream : TFileStream; ALine : string; UseUTF8: Boolean = False) : boolean; 
var 
    AStr: AnsiString; 
begin 
    Result := True; 
    try 
    if UseUTF8 then 
     AStr := UTF8Encode(ALine) 
    else 
     AStr := AnsiString(ALine); 
    if AStr <> '' then 
     FileStream.WriteBuffer(AStr[1], Length(AStr)); 
    except 
    Result := False; 
    end; 
end; 

Các cách chính xác để sử dụng TEncoding là để cho nó làm mã hóa thực tế, không làm mã hóa chính mình:

function Add_Line(FileStream : TFileStream; ALine : string; Enc: TEncoding = nil) : boolean; 
var 
    AStr: TBytes; 
begin 
    if ALine = '' then 
    begin 
    Result := True; 
    Exit; 
    end; 
    Result := False; 
    try 
    if Enc = nil then Enc := TEncoding.Ansi; 
    AStr := Enc.GetBytes(ALine); 
    // GetBytes() returns 0 bytes if it fails to encode, it does not raise an exception! 
    if Length(AStr) = 0 then Exit; 
    FileStream.WriteBuffer(AStr[0], Length(AStr)) 
    except 
    Exit; 
    end; 
    Result := True; 
end; 
Các vấn đề liên quan