如何为TEncoding类型的函数参数设置默认值?

时间:2012-09-10 12:53:37

标签: delphi unicode encoding delphi-xe2

从D2007转换为XE2,我转换了这个函数

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;

理由:

  • 尽可能少地使用Add_Line更改代码

  • 接受自动更改为Unicode,仅在最后时刻写入8位文本文件(这在XML和CSV中使用)。如果我们愿意,将来我们仍然可以转移到UTF-16文件。

我希望定义类似的内容:

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

但编译器抱怨; - )

有可能吗?

2 个答案:

答案 0 :(得分:12)

默认参数必须是编译时常量,但是如果你需要更高级的东西,你可以创建重载:

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;

您甚至可以添加inline关键字,以获得与默认参数产生的完全相同的生成代码,如果它有效。

注意:除了TEncoding.ANSITEncoding.UTF8之外,您似乎不支持任何其他内容。在这种情况下,TEncoding参数似乎有些过分,您可以使用UTF8: Boolean参数(或者重新编写代码以使用任意编码的CodePage)。

注意2:FileStream.WriteBuffer( AStr[1], Length(ALine) );错误,因为Length(ALine)Length(AStr)不一定相同,您应该使用Length(AStr)。此外,当AStr[1]为空字符串时,AStr可能会导致异常,您可以添加一个特殊情况,仅在WriteBuffer不为空时才调用AStr

答案 1 :(得分:5)

其他人评论了如何为TEncoding参数指定默认值。我想指出,你使用TEncoding一般都是完全错误的。

TEncoding.UTF8不是获取UTF-8编码对象的唯一方法(TEncoding.GetEncoding(65001)是另一种方式),因此特别检查TEncoding.UTF8是不对的。更糟糕的是,你完全忽略了任何非UTF8编码,只是将其他信息编码到普通AnsiString,这完全违背了使用TEncoding的目的。例如,用户可以传入ISO-8859-X编码对象,并且您的输出不会像用户请求的那样进行ISO编码。您也可以将参数更改为UseUTF8: Boolean = False参数,因为这是您有效使用它的方式:

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;  

使用TEncoding的正确方法是让它进行实际编码,不要自己进行编码:

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;