从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;
但编译器抱怨; - )
有可能吗?
答案 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.ANSI
和TEncoding.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;