2012-03-08 14 views
8

Nel Blocco note è possibile aprire qualsiasi file e visualizzerà i dati non elaborati all'interno.Apri un file in un memo?

Mi piacerebbe farlo in un TMemo ma ho faticato a scoprire come farlo.

sono riuscito a trovare questo code here.

ho modificato a una funzione e ha cambiato leggermente per i miei scopi:

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; 

Funziona, ma viene visualizzata solo in un importo fisso di caratteri per riga , in questo modo:

enter image description here

di cosa ho bisogno di cambiare in modo da riempire tutto il promemoria nella stessa wa Il blocco note sarebbe?

risposta

9

Bene, è il test if (i mod 16) = 0 che sta troncando le linee a 16 caratteri.

credo che Notepad fa lo stesso di questo codice:

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; 

Se si desidera sostituire i caratteri non stampabili con '.' allora si può facilmente farlo modificando il codice di cui sopra in questo modo:

if s[i]<#32 then 
    s[i] := '.'; 
+0

che è grande grazie David. Stavo leggendo alcuni commenti mentre cercavo varie soluzioni e alcuni citano l'uso di BlockRead. I file che sto aprendo sono relativamente piccoli, ma devo considerarlo comunque, o la tua risposta non lo richiede perché sembra che sia letto attraverso il flusso? –

+0

Userei sempre un flusso piuttosto che un vecchio pascal io –

+0

Beh, non ho mai usato Pascal vecchio stile, sto ancora imparando il Delphi moderno :) Gli articoli/frammenti che stavo leggendo erano probabilmente obsoleti che potrebbero spiegarlo. La tua soluzione è veramente ordinata ed efficiente, lo fai sembrare facile. Grazie mille :) –

3

TStrings diventato TEncoding -aware in D2009. Per impostazione predefinita, TStrings.LoadFrom...() utilizzerà TEncoding.Default a meno che non lo dici diversamente. Vorrei suggerire l'implementazione di una classe personalizzata TEncoding derivata che legge/scrive i dati a 8 bit prime, ad esempio:

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; 

Quindi è possibile utilizzare in questo modo:

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

Eccellente informazione ed esempio di codice grazie mille Remy. Mi stupisce che ci sia sempre più di un modo per fare qualcosa in programmazione e Delphi - eppure più spesso non riesco a capire un solo modo! La tua soluzione è completamente diversa da quella di David, ma entrambi mostrano approcci diversi che sono davvero utili :) –

Problemi correlati