Delphi 打开备忘录中的任何文件?

Delphi 打开备忘录中的任何文件?,delphi,delphi-xe,Delphi,Delphi Xe,在记事本中,您可以打开任何文件,它将显示其中的原始数据 我想在TMemo中这样做,但一直在努力寻找如何做到这一点 我设法找到了这个 我将其修改为函数,并出于我的目的对其进行了轻微更改: function OpenBinaryFile(var Data; Count: Cardinal): string; var Line: string[80]; i: Cardinal; P: PAnsiChar; nStr: string[4]; SL: TStringList; cons

在记事本中,您可以打开任何文件,它将显示其中的原始数据

我想在TMemo中这样做,但一直在努力寻找如何做到这一点

我设法找到了这个

我将其修改为函数,并出于我的目的对其进行了轻微更改:

function OpenBinaryFile(var Data; Count: Cardinal): string;
var
  Line: string[80];
  i: Cardinal;
  P: PAnsiChar;
  nStr: string[4];
  SL: TStringList;
const
  posStart = 1;
  binStart = 7;
  ascStart = 57;
begin
  P := @Data;
  Line := '';

  SL := TStringList.Create;
  try
    for i := 0 to Count - 1 do
    begin
      if (i mod 16) = 0 then
      begin
        if Length(Line) > 0 then
          SL.Add(Trim(Line));

        FillChar(Line, SizeOf(Line), ' ');
        Line[0] := Chr(72);
      end;

    if P[i] >= ' ' then
      Line[i mod 16 + ascStart] := P[i]
    else
      Line[i mod 16 + ascStart] := '.';
    end;

    SL.Add(Trim(Line));

    Result := SL.Text;
 finally
    SL.Free;
  end;
end;
它可以工作,但每行只显示固定数量的字符,如下所示:

if s[i]<#32 then
  s[i] := '.';
var
  Enc: TEncoding;
begin
  Enc := TRawEncoding.Create;
  try
    Memo1.Lines.LoadFromFile('filename', Enc);
  finally
    Enc.Free;
  end;
end;

我需要更改什么,以便它以记事本的相同方式填充所有备忘录?

好吧,如果(I mod 16)=0,则是
测试将行截断为16个字符

我相信记事本的功能与此代码相同:

var
  i: Integer;
  s: AnsiString;
  Stream: TFileStream;
begin
  Stream := TFileStream.Create(FileName, fmOpenRead);
  try
    SetLength(s, Stream.Size);
    if Stream.Size>0 then
      Stream.ReadBuffer(s[1], Stream.Size);
  finally
    Stream.Free;
  end;
  for i := 1 to Length(s) do
    if s[i]=#0 then
      s[i] := ' ';
  Memo1.Text := s;
end;
如果要将不可打印字符替换为“
”。
则可以通过如下方式修改上述代码来轻松完成此操作:

if s[i]<#32 then
  s[i] := '.';
var
  Enc: TEncoding;
begin
  Enc := TRawEncoding.Create;
  try
    Memo1.Lines.LoadFromFile('filename', Enc);
  finally
    Enc.Free;
  end;
end;

如果s[i]
t字符串在D2009中变得
TEncoding
-可识别。默认情况下,
TStrings.LoadFrom…()
将使用
TEncoding.default
,除非您另有说明。我建议实现一个定制的
TEncoding
派生类,用于读取/写入原始8位数据,例如:

type
  TRawEncoding = class(TEncoding)
  protected
    function GetByteCount(Chars: PChar; CharCount: Integer): Integer; override;
    function GetBytes(Chars: PChar; CharCount: Integer; Bytes: PByte; ByteCount: Integer): Integer; override;
    function GetCharCount(Bytes: PByte; ByteCount: Integer): Integer; override;
    function GetChars(Bytes: PByte; ByteCount: Integer; Chars: PChar; CharCount: Integer): Integer; override;
  public
    constructor Create;
    function GetMaxByteCount(CharCount: Integer): Integer; override;
    function GetMaxCharCount(ByteCount: Integer): Integer; override;
    function GetPreamble: TBytes; override;
  end;

然后你可以这样使用它:

if s[i]<#32 then
  s[i] := '.';
var
  Enc: TEncoding;
begin
  Enc := TRawEncoding.Create;
  try
    Memo1.Lines.LoadFromFile('filename', Enc);
  finally
    Enc.Free;
  end;
end;

太好了,谢谢你,大卫。我在寻找各种解决方案的同时阅读了一些评论,其中一些提到了BlockRead的使用。我打开的文件比较小,但是我是否需要考虑它,或者你的答案不需要这个,因为它看起来是通过流读取的?我总是使用流而不是旧的Pascal IOWELL,我从来没有使用过旧的Pascal,还在学习现代德尔菲:)我读的文章/片段可能已经过时了,这也许可以解释这一点。你的解决方案非常整洁高效,你让它看起来很简单。非常感谢:)非常好的信息和代码示例非常感谢雷米。在编程和Delphi中,总是有不止一种方法可以做一些事情,这让我感到惊讶——但更多的时候,我无法找到一种方法!您的解决方案与David的完全不同,但两者都显示了不同的方法,这非常有用:)