我用Delphi (7)写了一个应用程序(心理测试测试),它创建了一个标准的文本文件--即该文件是ANSI类型的。
有人将该程序移植到Internet上运行,可能是使用Java,生成的文本文件是UTF-8类型。
读取这些结果文件的程序必须读取由Delphi创建的文件和通过Internet创建的文件。
虽然我可以将UTF-8文本转换为ANSI (使用巧妙命名的函数UTF8ToANSI),但我如何提前知道我有哪种文件?
考虑到我“拥有”文件格式,我想处理这个问题的最简单方法是在文件中的已知位置放置一个标记,它将告诉我程序的来源(Delphi/Internet),但这似乎是作弊。
提前谢谢。
发布于 2011-02-06 00:15:24
如果UTF文件以UTF-8字节顺序标记(BOM)开头,这很容易:
function UTF8FileBOM(const FileName: string): boolean;
var
txt: file;
bytes: array[0..2] of byte;
amt: integer;
begin
FileMode := fmOpenRead;
AssignFile(txt, FileName);
Reset(txt, 1);
try
BlockRead(txt, bytes, 3, amt);
result := (amt=3) and (bytes[0] = $EF) and (bytes[1] = $BB) and (bytes[2] = $BF);
finally
CloseFile(txt);
end;
end;否则,就会困难得多。
发布于 2011-02-06 00:28:17
没有100%确定的方法来识别ANSI (例如Windows-1250)编码和UTF-8编码。有些ANSI文件不能是有效的UTF-8,但每个有效的UTF-8文件都可能是不同的ANSI文件。(更不用说定义为ANSI和UTF-8的纯ASCII数据,但这纯粹是一个理论方面。)
例如,序列C4 8D在UTF-8中可能是“č”字符,在windows-1250中可能是“Ť”。这两种方法都是可能的,而且都是正确的。然而,例如8D 9A可以是windows-1250中的“Ťš”,但它不是有效的UTF-8字符串。
你必须求助于某种启发式方法,例如:
如果文件包含的序列不能是有效的UTF-8,则假定它是ANSI.
另请参见the method used by Notepad。
发布于 2011-02-25 17:34:05
如果我们对求和,那么:
人们可能会感兴趣的其他信息:
function FileMayBeUTF8(FileName: WideString): Boolean;
var
Stream: TMemoryStream;
BytesRead: integer;
ArrayBuff: array[0..127] of byte;
PreviousByte: byte;
i: integer;
YesSequences, NoSequences: integer;
begin
if not WideFileExists(FileName) then
Exit;
YesSequences := 0;
NoSequences := 0;
Stream := TMemoryStream.Create;
try
Stream.LoadFromFile(FileName);
repeat
{read from the TMemoryStream}
BytesRead := Stream.Read(ArrayBuff, High(ArrayBuff) + 1);
{Do the work on the bytes in the buffer}
if BytesRead > 1 then
begin
for i := 1 to BytesRead-1 do
begin
PreviousByte := ArrayBuff[i-1];
if ((ArrayBuff[i] and $c0) = $80) then
begin
if ((PreviousByte and $c0) = $c0) then
begin
inc(YesSequences)
end
else
begin
if ((PreviousByte and $80) = $0) then
inc(NoSequences);
end;
end;
end;
end;
until (BytesRead < (High(ArrayBuff) + 1));
//Below, >= makes ASCII files = UTF-8, which is no problem.
//Simple > would catch only UTF-8;
Result := (YesSequences >= NoSequences);
finally
Stream.Free;
end;
end;现在测试这个函数...
在我看来,如何正确地开始检查的唯一方法是首先检查操作系统字符集,因为在最后,几乎所有的情况下都会引用一些操作系统。不管怎么说都没办法让它消失。
备注:
https://stackoverflow.com/questions/4907942
复制相似问题