Jan*_*gen 6 delphi unicode encoding delphi-xe2
从D2007转换为XE2,我转换了这个功能
function Add_Line( FileStream : TFileStream; ALine : string) : boolean;
Run Code Online (Sandbox Code Playgroud)
至
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;
Run Code Online (Sandbox Code Playgroud)
理由:
尽可能少地使用Add_Line更改代码
接受自动更改为Unicode,仅在最后时刻写入8位文本文件(这在XML和CSV中使用).如果我们想要的话,未来我们仍然可以转向UTF-16文件.
我本来希望定义类似的东西:
function Add_Line( FileStream : TFileStream; ALine : string; Enc: TEncoding = TEncoding.ANSI) : boolean;
Run Code Online (Sandbox Code Playgroud)
但编译器抱怨;-)
有可能吗?
小智 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;
Run Code Online (Sandbox Code Playgroud)
您甚至可以添加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非空时调用.
其他人评论了如何为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;
Run Code Online (Sandbox Code Playgroud)
正确的使用方法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;
Run Code Online (Sandbox Code Playgroud)