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

时间:2012-03-08 18:57:16

标签: delphi delphi-xe

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

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

我设法找到了这个code here.

我将它修改为一个函数并为了我的目的稍微改了一下:

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;

它可以工作,但它每行只显示固定数量的字符,如下所示:

enter image description here

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

2 个答案:

答案 0 :(得分:9)

嗯,这是if (i mod 16) = 0测试,它将行截断为16个字符。

我相信Notepad与此代码的作用相同:

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] := '.';

答案 1 :(得分:3)

TStrings成为TEncoding - 在D2009中意识到了。默认情况下,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;

constructor TRawEncoding.Create;
begin
  FIsSingleByte := True;
  FMaxCharSize := 1;
end;

function TRawEncoding.GetByteCount(Chars: PChar; CharCount: Integer): Integer;
begin
  Result := CharCount;
end;

function TRawEncoding.GetBytes(Chars: PChar; CharCount: Integer; Bytes: PByte; ByteCount: Integer): Integer;
var
  i : Integer;
begin
  Result := Math.Min(CharCount, ByteCount);
  for i := 1 to Result do begin
    // replace illegal characters > $FF
    if Word(Chars^) > $00FF then begin
      Bytes^ := Byte(Ord('?'));
    end else begin
      Bytes^ := Byte(Chars^);
    end;
    //advance to next char
    Inc(Chars);
    Inc(Bytes);
  end;
end;

function TRawEncoding.GetCharCount(Bytes: PByte; ByteCount: Integer): Integer;
begin
  Result := ByteCount;
end;

function TRawEncoding.GetChars(Bytes: PByte; ByteCount: Integer; Chars: PChar; CharCount: Integer): Integer;
var
  i : Integer;
begin
  Result := Math.Min(CharCount, ByteCount);
  for i := 1 to Result do begin
    Word(Chars^) := Bytes^;
    //advance to next char
    Inc(Chars);
    Inc(Bytes);
  end;
end;

function TRawEncoding.GetMaxByteCount(CharCount: Integer): Integer;
begin
  Result := CharCount;
end;

function TRawEncoding.GetMaxCharCount(ByteCount: Integer): Integer;
begin
  Result := ByteCount;
end;

function TRawEncoding.GetPreamble: TBytes;
begin
  SetLength(Result, 0);
end;

然后你可以像这样使用它:

var
  Enc: TEncoding;
begin
  Enc := TRawEncoding.Create;
  try
    Memo1.Lines.LoadFromFile('filename', Enc);
  finally
    Enc.Free;
  end;
end;