【问题标题】:Delphi (2009) - Converting AnsiString reading or preserving line breaks?Delphi (2009) - 转换 AnsiString 读取或保留换行符?
【发布时间】:2013-01-09 00:58:16
【问题描述】:

使用此(测试)代码从 PNG 中读取文本块:

procedure TForm1.Button1Click(Sender: TObject);
var
  PngVar: TPngImage;
  n: Integer;
begin
  PngVar := TPNGImage.Create;
  PngVar.LoadFromFile('C:\test.png');
  for n := 0 to pred(PngVar.Chunks.count) do
  if PngVar.Chunks.item[n].Name='tEXt' then
  with PngVar.Chunks.item[n] as TChunkTEXT do
  memo1.lines.add(KeyWord+'='+Text);
end;

代码来自 TPNGObject 原作者的示例,并从 embercardo 网站下载。 KeyWord 包含文本块的值,在本例中为注释。文本包含我们需要的文本。它是一个 AnsiString,应该有中断,但是当从 AnsiString 转换为 unicode 时,它​​们会丢失,它变成一个字符串,在行尾和行首之间甚至没有空格。

单步调试调试器时,我注意到它的每一行都用单引号括起来,在行之间它有 #$A 我假设如果我签入十六进制是某种形式的控制字符。

comment=PunkBuster 截图 (ñ) BF3 Levels/MP_017/MP_017'#$A'1135998 31.204.131.11:25530 GoTBF3.nl #4 | 32p |仅 TDM 运河 | 500 张门票'#$A'geawtaw46y4w63a46a34643a BorislavFatsolka'#$A'尝试:w=320 X h=240 at (x=50%,y=50%)'#$A'结果:w =320 X h=200 样本=1'

示例图片 http://www.pbbans.com/pbss_evidence/bf3/31.204.131.11:25530/5d00a95d22fae4a287bd510c076db1bf-2e36c3b4.png 这是示例。我正在做的是从 punkbuster 图像中读取数据,以使它们可以在我们的社区数据库中搜索。但我也会在图像旁边显示信息,并且 id 喜欢换行或知道行何时结束。

当直接放入备忘录或字符串列表时,它会全部显示为一行:

comment=PunkBuster Screenshot (ñ) BF3 Levels/MP_017/MP_0171135998 31.204.131.11:25530 GoTBF3.nl #4 | 32p |仅 TDM 运河 | 500 张票*geawtaw46y4w63a46a34643a* BorislavFatsolka 尝试:w=320 X h=240 at (x=50%,y=50%) 结果:w=320 X h=200 sample=1

问题

处理这个 ansistring 的最佳方法是什么,它来自原始图像,或者 TPNGImage 在那里没有真正的选择。将其放入备忘录、丰富的编辑或字符串列表中,并保持完整的中断。

首先想到的可能是效率低下,那就是将其放入字节数组等中,并在行尾处切割每一行逐字节读取。

来自示例的更多数据 您应该能够通过下载示例图像来看到这一点,但是,这是它在十六进制编辑器中的外观(文件的第一部分完好无损,png 标头,tEXt 块标头关键字等。

‰PNG........IHDR...Ž...2.....ûŒÆ$....tEXtcomment.PunkBuster Screenshot (ñ) BF3  Levels/MP_017/MP_017.1135998 31.204.131.11:25530 GoTBF3.nl #4 | 32p | TDM Canals Only | 500 Tickets.*geawtaw46y4w63a46a34643a* BorislavFatsolka.Attempted: w=320 X h=240 at (x=50%,y=50%).Resulting: w=320 X h=200 sample=1.

89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 00 00 02 8E 00 00 01 32 08 02 00 00 00 FB 8C C6 24 00 00 01 03 74 45 58 74 63 6F 6D 6D 65 6E 74 00 50 75 6E 6B 42 75 73 74 65 72 20 53 63 72 65 65 6E 73 68 6F 74 20 28 F1 29 20 42 46 33 20 20 4C 65 76 65 6C 73 2F 4D 50 5F 30 31 37 2F 4D 50 5F 30 31 37 0A 31 31 33 35 39 39 38 20 33 31 2E 32 30 34 2E 31 33 31 2E 31 31 3A 32 35 35 33 30 20 47 6F 54 42 46 33 2E 6E 6C 20 23 34 20 7C 20 33 32 70 20 7C 20 54 44 4D 20 43 61 6E 61 6C 73 20 4F 6E 6C 79 20 7C 20 35 30 30 20 54 69 63 6B 65 74 73 0A 2A 67 65 61 77 74 61 77 34 36 79 34 77 36 33 61 34 36 61 33 34 36 34 33 61 2A 20 42 6F 72 69 73 6C 61 76 46 61 74 73 6F 6C 6B 61 0A 41 74 74 65 6D 70 74 65 64 3A 20 77 3D 33 32 30 20 58 20 68 3D 32 34 30 20 61 74 20 28 78 3D 35 30 25 2C 79 3D 35 30 25 29 0A 52 65 73 75 6C 74 69 6E 67 3A 20 77 3D 33 32 30 20 58 20 68 3D 32 30 30 20 73 61 6D 70 6C 65 3D 31 0A

其他发现 如果我转储块 (PngVar.Chunks.item[n].SaveToStream),它基本上给了我我们在十六进制编辑器中找到的内容。控制字符为 0A。我不确定#$A是转换前还是转换后的效果,甚至可能是由pngimage代码引起的。

【问题讨论】:

  • 什么是s,“返回数据”是什么意思?
  • 该代码来自作者的示例,该示例最初是从 embercardo 下载的 TPNGObject/TPNGImage。在该示例中,S 表示 TStringList。在我的测试代码中,我将其命名为 Memo1.Lines.Add。我失去了我要去的例子,因为它没有被保存。最后,这将使用 unicode 字符串。解释我所说的返回数据对你没有任何帮助。它返回我们请求的数据。数据是一个有换行符但丢失的 ansistring。
  • 如果有人想尝试一下,我将编辑添加更多代码,并在此处添加几分钟后公开的 pbbans 图像。
  • #$0A 与 #10、chr(10) 或 chr($A) 相同,也称为 CR(回车)。在半换行符的窗口中,因为换行符是 CR+LF 对(LF 是 #$0D 或 #13)。如果将其保存到文件中,记事本也将显示它而没有换行符。通常,Delphi 会以透明的方式为您管理它。您可能还会对 $ 表示法感到困惑,它等同于 c 0x,这意味着以下数字以十六进制表示。因此,$0A 与 0x0A 相同,或者简称为 10。
  • 其他的Delphi符号是#,用ASCII值表示一个字符,主要用于显示不可打印的字符。例如#65 是'A'。您可以结合使用 #$41 等两种表示法来表示相同的“A”字符。

标签: delphi png ansistring


【解决方案1】:

试试:

memo1.lines.add(KeyWord+'='+StringReplace(Text,#10,sLineBreak,[rfReplaceAll]));

【讨论】:

  • 那行得通。谢谢你。我知道必须有一种简单有效的方法来做到这一点。我不经常使用这类东西,虽然过去几年我变得更好了,但我仍然只是一个业余爱好者。正如我后来添加到我的帖子中读取块流和原始文件一样,控制字符看起来像一个标准字符,但调试器向我显示的内容很奇怪。
【解决方案2】:

另一种方法是 Jedi CodeLib

sl := TJclStringList.Create;
sl.Split(Text, #10);
sl[0] := 'Keyword=' +sl[0]
memo1.lines.AddStrings(sl);
sl.Free;

【讨论】:

  • 您可以使用标准的TStringList 来做同样的事情。 TStringList.Text 属性支持裸 LF 分隔线。在较新版本的 Delphi 中,TStrings 有一个 LineBreak 属性,因此您可以自定义换行符的值。
猜你喜欢
  • 2010-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-21
  • 2023-04-06
  • 1970-01-01
  • 2013-02-28
相关资源
最近更新 更多