Unit OK! - Conversão de Tipos p/ Binário: Leitura e Escrita

Delphi

14/01/2005

Olá pessoal!

Gostaria de compartilhar um pequeno trabalho que terminei e que me auxiliou muito num outro trabalho. Graças a ajuda aqui do pessoal, em especial o colega [b:03eb6c1580]MASSUDA[/b:03eb6c1580], consegui concluir o que precisava.

É uma coisa relativamente simples, mas que pode ser util a outras pessoas tanto quanto foi para mim. Trata-se de uma Unit pronta, que tem como função a leitura e a escrita de tipos como Byte, SmallInt, Integer, LongInt e Data convertidos em Bytes, salvando em arquivo Stream. Esta Unit pode ser melhorada ainda. Eu fiz uma pequena utilização desnecessária de TMemoryStream, no lugar de usar apenas TFileStream, mas como é transparente ao ser utilizada e eu estou com pouco tempo, então deixei assim mesmo (funciona!).

Bom, para utilizar faça o seguinte:

1º) Inclua a Unit uBinaryFile em seu projeto;
2º) Declare a unit uBinaryFile, na seção Uses do form onde for fazer a leitura e/ou escrita;

3º) Exemplo de leitura de bytes num arquivo do tipo binário, cujo formato de string foi gerado para PascalString:

try
    // Lê o arquivo binário especificado
    arq := TBinaryFile.Create(´DELPHI´,´C:\Temp\NomeArquivoBin.ext´, True);
    // Onde os parâmetros são: ´DELPHI´ = Informa o formato que a string foi gravada no arquivo
    //                         ´C:\Temp\NomeArquivoBin.ext´ = Path do arquivo + nome
    //                         True = Abre o construtor para leitura. Se fosse FALSE, abriria para Escrita.

    showmessage(arq.ReadString(13)); // 13 = Posição de início da string

    arq.Destroy;

except on e: exception do
  WriteLog(´Erro lendo arquivo ´ + e.message,0);
end;


4º) Exemplo de escrita:

var
  arq: TBinaryFile;
  Num: LongInt;
begin
Num := 327;

// Cria o arquivo binário no nome e local especificados
arq := TBinaryFile.Create(´C´, ´C:\Temp\NomeArquivoBin.ext´, False);
// Onde mudou apenas o 1º parâmetro: ´C´ = Formato em que são gravados, neste caso é ANSI

arq.WriteLong(Valor); // Escreve o valor de "Num" no arquivo stream, em bytes

arq.WriteDate(Now); // Escreve a data e hora atual no arquivo stream, em bytes

arq.Flush; // Grava dados no arquivo Stream

arq.Destroy;


5º) [b:03eb6c1580]UNIT[/b:03eb6c1580]: Abra um formulário do tipo Unit em seu Delphi, apague tudo e cole o código que segue abaixo

unit uBinaryFile;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls;

type
  TBinaryFile = class(TObject)
  private
    { Private declarations }
    
    Mode: Integer; // 0 para C e 1 para Delphi
    File_Name: String;
    Memory: TMemoryStream;
    File_Stream: TFileStream;
    function WriteCString(str: String):Boolean;
    function WriteDelphiString(str: String):Boolean;
    function DateToLongDelphi(Data : TDateTime) : LongWord;

    function ReadDelphiString(Pos: LongInt): String;
    function ReadCString(Pos: LongInt): String;
  public
    { Public declarations }

    // Read = TRUE: Construtor definido para LEITURA de bytes; FALSE = Escrita
    constructor Create(Language, FileName: String; Read: Boolean);
    destructor Destroy(); override;

    function WriteString(Str: String): Boolean;
    function WriteInteger(Number: SmallInt): Boolean;
    function WriteLong(Number: LongInt): Boolean;
    function WriteByte(Number: Byte): Boolean;
    function Flush(): Boolean;
    function WriteDate(Date: TDateTime): Boolean;
    function GetFileName(): String;
    function GetPath(): String;

    function ReadByte(Pos: LongInt): Byte;
    function ReadInteger(Pos: LongInt): SmallInt;
    function ReadLong(Pos: LongInt): LongInt;
    function ReadString(Pos: LongInt): String;
  end;

implementation

function TBinaryFile.DateToLongDelphi(Data : TDateTime) : longword;
var H, M, S, mS : Word;
begin
   Data := Data - StrToDateTime(´01/01/1970 00:00:00´);
   DecodeTime(Data, H, M, S, mS);
   Result := (trunc(Data) * 86400) + ((H*60+M)*60) + S;
end;

function TBinaryFile.GetFileName(): String;
begin
  Result := File_Name;
end;

function TBinaryFile.GetPath(): String;
begin
  Result := ExtractFilePath(File_Name);
end;

function TBinaryFile.WriteDate(date: TDateTime): Boolean;
var
  temp: LongWord;
begin
   if (Mode = -1) then
   begin
     raise exception.create(´BinaryFile: Linguagem não reconhecida.´);
     Exit;
   end;
   
   temp := DateToLongDelphi(date);

   try
     Memory.Write(temp, 4);
     Result := True;
   except
     Result :=  False;
   end;
end;

function TBinaryFile.Flush(): boolean;
begin
   if (Mode = -1) then
   begin
     raise exception.create(´BinaryFile: Linguagem não reconhecida.´);
     Exit;
   end;

   try
     Memory.SaveToFile(File_Name);
     Result := True;
   except
     Result := False;
   end;
end;


function TBinaryFile.WriteByte(number: byte): Boolean;
begin
   if (Mode = -1) then
   begin
     raise Exception.Create(´BinaryFile: Linguagem não reconhecida.´);
     Exit;
   end;

   try
     Memory.Write(number, SizeOf(number));
     Result := True;
   except
     Result :=  False;
   end;
end;


function TBinaryFile.WriteInteger(number: smallint): Boolean;
begin
   if (Mode = -1) then
   begin
     raise Exception.Create(´BinaryFile: Linguagem não reconhecida.´);
     Exit;
   end;

   try
     Memory.Write(number, SizeOf(number));
     Result := True;
   except
     Result :=  False;
   end;
end;

function TBinaryFile.WriteLong(number: longint): Boolean;
begin
   if (Mode = -1) then
   begin
     raise Exception.Create(´BinaryFile: Linguagem não reconhecida.´);
     Exit;
   end;

   try
     Memory.Write(number, SizeOf(number));
     Result := True;
   except
     Result :=  False;
   end;
end;

destructor TBinaryFile.Destroy();
begin
  if File_Stream <> nil then
    File_Stream.Destroy;

  if Memory <> nil then
    Memory.Destroy;

  inherited Destroy;
end;

function TBinaryFile.WriteCString(str: String):Boolean;
var
  N: Integer;
  c: Char;
begin
  // Escrita de string no padrão AnsiStrting
  try
    N := Length(str);
    if N > 0 then Memory.Write(str[1], N);
    c := chr(0);
    Memory.Write(c,1);
    Result := True;
  except
    Result := False;
  end;
end;

function TBinaryFile.WriteDelphiString(str: String):Boolean;
var
  N: Integer;
begin
  // Escrita de string no padrão PascalStrting
  try
    N := Length(str);
    Memory.Write(N, SizeOf(N));
    if N > 0 then Memory.Write(str[1], N);
    Result := True;
  except
    Result := False;
  end;
end;

function TBinaryFile.WriteString(str: String): Boolean;
begin
  Result := false;

  // Identifica o método de conversão e escrita da string em bytes
  case Mode of
    0 : Result := WriteCString(str);
    1 : Result := WriteDelphiString(str);
    -1: begin
           raise Exception.Create(´TBinaryFile: Linguagem não reconhecida.´);
           Exit;
        end;
  end;
end;


constructor TBinaryFile.Create(Language, FileName: String; Read: Boolean);
begin
  inherited Create;

  if (UpperCase(Language) = ´DELPHI´) then
    Mode := 1
  else
  if (UpperCase(Language) = ´C´) then
    Mode := 0
  else
  begin
    Mode := -1;

    if Read then // Modo Leitura
      raise Exception.Create(´Erro ao ler BinaryFile. Parâmetro ´ + ´´´´ + ´language´ + ´´´´ + ´ não reconhecido: ´ + Language + ´.´)
    else
      raise Exception.Create(´Erro ao criar BinaryFile. Parâmetro ´ + ´´´´ + ´language´ + ´´´´ + ´ não reconhecido: ´ + Language + ´.´);
    Exit;
  end;

  if (FileExists(FileName)) then
  begin
    if Read then // Modo Leitura
    begin
      File_Name := FileName;

      File_Stream := TFileStream.Create(File_Name, fmOpenRead);
      File_Stream.Seek(0, soFromBeginning);
    end
    else
    begin
      raise Exception.Create(´Erro ao criar BinaryFile: Arquivo ´ + ´´´´ + FileName + ´´´´ + ´ já existe!´ );
      Exit;
    end;
  end
  else
  begin
    if Read then // Modo Leitura
    begin
      raise Exception.Create(´Erro ao ler BinaryFile: Arquivo ´ + ´´´´ + FileName + ´´´´ + ´ não existe!´ );
      Exit;
    end
    else
    begin
      File_Name := FileName;

      Memory := TMemoryStream.Create;
      Memory.Seek(0, soFromBeginning);
    end;
  end;
end;

function TBinaryFile.ReadByte(Pos: LongInt): Byte;
begin
   if (Mode = -1) then
   begin
     raise Exception.Create(´BinaryFile: Linguagem não reconhecida.´);
     Exit;
   end;

   try
     File_Stream.Seek(Pos, soFromBeginning);
     File_Stream.Read(Result, 1); // 1 = 1 byte para ler o tipo Byte
   except
     Result := 0;
   end;
end;

function TBinaryFile.ReadInteger(Pos: LongInt): SmallInt;
begin
   if (Mode = -1) then
   begin
     raise Exception.Create(´BinaryFile: Linguagem não reconhecida.´);
     Exit;
   end;

   try
     File_Stream.Seek(Pos, soFromBeginning);
     File_Stream.Read(Result, 2); // 2 = Dois bytes para ler o tipo SmallInt (SmallInt = Integer em liguagem C)
   except
     Result := -32767;
   end;
end;

function TBinaryFile.ReadLong(Pos: LongInt): LongInt;
begin
   if (Mode = -1) then
   begin
     raise Exception.Create(´BinaryFile: Linguagem não reconhecida.´);
     Exit;
   end;

   try
     File_Stream.Seek(Pos, soFromBeginning);
     File_Stream.Read(Result, 4); // 4 = Quatro bytes para ler o tipo LongInt
   except
     Result := -32767;
   end;
end;

function TBinaryFile.ReadDelphiString(Pos: LongInt): String;
var
  N: Integer;
  StringLida: String;
begin
  // Leitura de string no padrão PascalStrting
  if (Mode = -1) then
  begin
    raise Exception.Create(´BinaryFile: Linguagem não reconhecida.´);
    Exit;
  end;

  try
    File_Stream.Seek(Pos, soFromBeginning);
    File_Stream.Read(N, SizeOf(N));

    if N > 0 then begin
      SetLength(StringLida, N);
      File_Stream.Seek(Pos + 4, soFromBeginning); // A soma de 4 unidades à posição, se deve ao tamanho de N, que indica o comprimento da string e é um Integer
      File_Stream.Read(StringLida[1], N);
    end else
      StringLida := ´´;

    Result := StringLida;
  except
    StringLida := ´´;
  end;
end;

function TBinaryFile.ReadCString(Pos: LongInt): String;
var
  ReadChar: Char;
  StringLida: String;
begin
  // Leitura de String no padrão AnsiString
  if (Mode = -1) then
  begin
    raise Exception.Create(´BinaryFile: Linguagem não reconhecida.´);
    Exit;
  end;

  try
    repeat
      File_Stream.Seek(Pos, soFromBeginning);
      File_Stream.Read(ReadChar, 1);
      StringLida := StringLida + ReadChar;
      Inc(Pos);
    until ReadChar = #0;

    Result := StringLida;
  except
    StringLida := ´´;
  end;
end;

function TBinaryFile.ReadString(Pos: LongInt): String;
begin
  Result := ´´;

  // Identifica o método de Leitura dos bytes e conversão para strring
  case Mode of
    0 : Result := ReadCString(Pos);
    1 : Result := ReadDelphiString(Pos);
    -1: begin
           Result := ´´;
           raise Exception.Create(´TBinaryFile: Linguagem não reconhecida.´);
           Exit;
        end;
  end;
end;

end.


Bom, é isso. Espero que seja útil a alguém. :wink:

T+
wbb


Wbb

Wbb

Curtidas 0
POSTAR