在记事本中,您可以打开任何文件,它将显示其中的原始数据。
我想在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;
它可以工作,但它每行只显示固定数量的字符,如下所示:
我需要更改什么才能以与记事本相同的方式填充所有备忘录?
答案 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;