首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用TFilestream获取真实的文件内容?

如何使用TFilestream获取真实的文件内容?
EN

Stack Overflow用户
提问于 2013-05-21 15:18:26
回答 2查看 2.8K关注 0票数 1

我尝试使用TFilestream获取文件内容:

代码语言:javascript
复制
procedure ShowFileCont(myfile : string);
var
tr : string;
fs : TFileStream;
Begin
   Fs   := TFileStream.Create(myfile, fmOpenRead or fmShareDenyNone); 
   SetLength(tr, Fs.Size);
   Fs.Read(tr[1], Fs.Size);
   Showmessage(tr); 
   Fs.Free;
end;

我只做了一个只有内容的小文本文件:aaaaaaaJ“њРЉTщЂ8ЈЏVд”ЈИaaaaaaa

  1. 并使用1251 (ansi)代码保存此文件(使用AkelPad)
  2. 使用65001 (UTF8)代码页保存。

这些文件有不同的大小,但内容是相等的-我在记事本中实现了它们,它们都有相同的内容。

但是,当我运行ShowFileCont proc时,它向我显示了不同的结果:

  1. aaaaaaaJ?ЊT?8?v?
  2. aaaaaaaJ“њРЉTщЂ8ЈЏVд”ЈИaaaaaaa

问题:

  1. 如何使用TFilestream获取真实的文件内容?
  2. 如何解释这两个文件有不同的大小,但内容(在记事本)是相等的?

添加:对不起,我没有说我使用Lazarus和string = utf8string

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-05-21 15:26:23

为什么文件大小不同?

因为他们使用不同的编码。1251编码将每个字符映射到一个字节。但是UTF-8对每个字符使用可变的字节数.

如何获得真正的文件内容?

您需要使用与文件中使用的编码匹配的字符串类型。因此,例如,如果内容是UTF-8编码的,这是最好的选择,那么您将内容加载到UTF-8字符串中。在一种模式下使用FPC,其中string是UTF-8编码的.在这种情况下,问题中的代码就是您所需要的。

比如说,用1251的代码页加载MBCS编码的文件要复杂得多。您可以将其加载到AnsiString变量中,只要系统的区域设置为1251,则任何转换都将正确执行。

但是,当在具有不同区域设置的计算机上运行时,代码的行为将有所不同。如果希望使用不同的MBCS编码(例如1252 )加载文本,则不能使用此方法。您需要加载到字节数组中,然后从1252转换为UTF-8,这样就可以将UTF-8存储在string变量中。

为了做到这一点,您可以使用来自LCL的LConvEncoding单元。例如,您可以使用CP1251ToUTF8CP1252ToUTF8等将MBCS转换为UTF-8.

如何从文件中确定使用了什么编码?

你不能。在很多情况下,你可以猜到这是准确的。但一般来说,要识别表示文本的字节数组的编码是根本不可能的。

有时可以获取一个文件并排除某些编码。例如,并非所有字节流都是有效的UTF-8或UTF-16文本.所以你可以排除这些文件。但是对于像1251,1252等编码,那么任何字节流都是有效的。你根本没有办法区分1251编码流和1252编码流,100%的准确性。

LConvEncoding单元有GuessEncoding,听起来可能有些用处。

票数 3
EN

Stack Overflow用户

发布于 2013-05-21 15:28:50

它们的内容显然不平等。您可以自己看到文件大小是不同的。大小不同的东西从来都不相等。

您的文件在记事本中可能显示为相等,因为记事本知道如何识别某些字符编码。你用两种不同的方式保存了你的文件。一种方法是使用一种编码方式,将一个字节分配给256个可能的值中的每个。另一种方式是使用一种编码,为超过10,000个可能的值中的每一个分配1到6个字节。您保存的一些字符需要多个字节,这就解释了为什么一个版本的文件比另一个版本大。

TFileStream没有注意到这一点。它只处理字节。根据您的Delphi版本,您的string变量可能注意编码,也可能不注意编码。在Delphi2009之前,string每个字符存储一个字节。截至Delphi2009,string每个字符使用两个字节,因此您的SetLength调用是错误的,之后的一切都没有意义进一步研究。

使用每个字符一个字节,您的ShowMessage调用将不会将字符串解释为UTF-8编码。相反,它将使用系统代码页来解释您的字符串。如果您知道所读取的字符串是用UTF-8编码的,那么您将希望在显示之前通过调用UTF8Decode将其转换为UTF-16。这将返回一个WideString,您可以使用任意数量的函数来显示它,例如MessageBoxW。如果您有Delphi2009或更高版本,那么如果您使用了Utf8String而不是string,编译器将自动为您插入转换代码。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16673564

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档