2012-03-08 11 views
8

En el Bloc de notas puede abrir cualquier archivo y se mostrarán los datos sin procesar dentro.¿Abrir cualquier archivo en una nota?

Me gustaría hacer esto en un TMemo pero he tenido problemas para descubrir cómo hacerlo.

he conseguido encontrar este code here.

he modificado a una función y cambió ligeramente para mis propósitos:

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; 

Funciona, pero sólo se muestra en una cantidad fija de caracteres por línea , de esta manera:

enter image description here

¿Qué necesito para cambiar de modo que llene toda la nota en la misma wa y el Bloc de notas lo haría?

Respuesta

9

Bueno, es la prueba if (i mod 16) = 0 que está truncando las líneas con 16 caracteres.

creo que el Bloc de notas hace lo mismo que este código:

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; 

Si desea reemplazar los caracteres no imprimibles con '.' a continuación, puede hacerlo fácilmente mediante la modificación del código anterior como esto:

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

Eso es grande gracias David. Estaba leyendo algunos comentarios mientras buscaba varias soluciones y algunos mencionaron el uso de BlockRead. Los archivos que estoy abriendo son relativamente pequeños, pero ¿debo considerarlos de todos modos, o su respuesta no lo requiere porque parece que se lee a través de Stream? –

+0

Siempre usaría una secuencia en lugar de pascal viejo estilo –

+0

Bueno, nunca he usado Pascal de estilo antiguo, todavía estoy aprendiendo Delphi moderno :) Los artículos/fragmentos que estaba leyendo probablemente fueron obsoletos y podrían explicar eso. Su solución es realmente ordenada y eficiente, la hace parecer fácil. Muchas gracias :) –

3

TStrings se convirtió en TEncoding -aware en D2009. De forma predeterminada, TStrings.LoadFrom...() usará TEncoding.Default a menos que le indique lo contrario. Yo sugeriría la implementación de una clase personalizada TEncoding derivada que lee/escribe datos de 8 bits primas, por ejemplo:

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; 

A continuación, puede utilizar de esta manera:

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

Excelente información y ejemplo de código muchas gracias Remy. Me sorprende que siempre haya más de una forma de hacer algo en la programación y en Delphi, ¡pero aún más a menudo que no puedo entender de una sola manera! Su solución es completamente diferente a la de David, pero ambas muestran diferentes enfoques, lo cual es realmente útil :) –

Cuestiones relacionadas