Fórum Unit OK! - Conversão de Tipos p/ Binário: Leitura e Escrita #265338
14/01/2005
0
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:574d92b430]MASSUDA[/b:574d92b430], 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:574d92b430]UNIT[/b:574d92b430]: 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
Curtir tópico
+ 0Posts
14/01/2005
Emerson Nascimento
Gostei + 0
14/01/2005
Nildo
Mode: Integer; // 0 para C e 1 para Delphi
Poderia ser diferente! Poderia ser assim:
type
TMode = ( mC, mDELPHI );
TBinaryFile = class(TObject)
private
{ Private declarations }
Mode: TMode;
E nas verificações, usar assim, por exemplo:
case Mode of mC : Result := WriteCString(str); mDELPHI : Result := WriteDelphiString(str);
E poderia substituir o Create para ficar da seguinte maneira:
constructor TBinaryFile.Create(Language: TMode; FileName: String; Read: Boolean);
Dai na hora de criar não tem perigo de digitar uma linguagem errada:
arq := TBinaryFile.Create( mDELPHI, ´C:\Temp\NomeArquivoBin.ext´, True );
ou
arq := TBinaryFile.Create( mC, ´C:\Temp\NomeArquivoBin.ext´, True );
Caso contrário o compilador não deixa compilar.
Dai pode tirar todas as verificações do [b:7a5d92aae9]if MODE = -1 then GeraErro[/b:7a5d92aae9]
São apenas opiniões! :D
Gostei + 0
14/01/2005
Wbb
Acho que fica melhor mesmo.
Vlw!
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)