Juntar 2 arquivos num só

31/01/2004

0

Gostária de saber se tem como juntar 2 arquivos em um só. Por exemplo, eu fiz um ´instalador´ usando um componente de zip, ... E neste .exe que eu fiz, gostária que ele armazenasse também o ZIP e virasse um arquivo só, tem como?


Doctor-x

Doctor-x

Responder

Posts

31/01/2004

Beppe

procedure MergeFiles(const Dest: String; const Sources: array of String);
var
  I, Len: Integer;
  Output, Src: TStream;
begin
  Output := TFileStream.Create(Dest, fmCreate);
  try
    for I := 0 to High(Sources) do
    begin
      // escreve o nome do arquivo, prefixado com o tamanho do nome
      Len := Length(Sources[I]);
      Output.Write(Len, SizeOf(Integer));
      Output.Write(Pointer(Sources[I])^, Len);

      // copia o arquivo, prefixado com o tamanho do mesmo
      Src := TFileStream.Create(Sources[I], fmOpenRead or fmShareDenyWrite);
      try
        Len := Src.Size;
        Output.Write(Len, SizeOf(Integer));
        Output.CopyFrom(Src, Len);
      finally
        Src.Free;
      end;
    end;
  finally
    Output.Free;
  end;
end;

procedure ExtractFiles(const Filename: String);
var
  I, Len: Integer;
  Output, Src: TStream;
  Name: String;
begin
  Src := TFileStream.Create(Filename, fmOpenRead or fmShareDenyWrite);
  try
    while Src.Size > Src.Position do
    begin
      Src.ReadBuffer(Len, SizeOf(Integer));
      SetLength(Name, Len);
      Output.ReadBuffer(Pointer(Name)^, Len);

      Output := TFileStream.Create(Name, fmCreate);
      try
        Src.ReadBuffer(Len, SizeOf(Integer));
        Output.CopyFrom(Src, Len);
      finally
        Output.Free;
      end;
    end;
  finally
    Src.Free;
  end;
end;


Eu acabei escrevendo isto(não testei), mas depois vi que sua duvida pode ser outra. O que você quer é fazer um auto-extract?

Se é juntar dois arquivos, o código é esse. Chama assim:

// juntando os arquivos
MergeFiles(´dest.dst´, [´source1.exe´, ´source2.zip´]);
// extrai os arquivos
ExtractFiles(´dest.dst´);



Responder

31/01/2004

Doctor-x

procedure MergeFiles(const Dest: String; const Sources: array of String);
var
  I, Len: Integer;
  Output, Src: TStream;
begin
  Output := TFileStream.Create(Dest, fmCreate);
  try
    for I := 0 to High(Sources) do

ExtractFiles(´dest.dst´);


Vou explicar, é mais ou menos assim: Eu criei um arquivo.zip e um executavel. No executavel eu uso um componente para descompactação de arquivos. Então eu queria um modo de este arquivo .zip e o .exe que eu criei ser um arquivo só .exe tipo um auto-extrator mesmo, mas eu não queria que ficasse o .exe e o .zip, e sim um jeito de ´colocar´ o .zip dentro do .exe para ter somente 1 arquivo


Responder

31/01/2004

Beppe

O seu componente de zipar já não faz isso? Tem alguns que fazem...

Mas tem sim como. Você cria um executável que extrai os dados compactados em um recurso. Aí tem duas opções de fazer isso: ou você gera o executável, seção por seção, coloca o recurso e o código de extração(x86), ou você cria no Delphi um executável(o auto-extract) que faça isso. Então no seu programa você coloca o .zip como recurso no executável auto-extract através da API do Windows.

Mas dá uma olhada que tem componentes que fazem isso.


Responder

01/02/2004

Doctor-x

O seu componente de zipar já não faz isso? Tem alguns que fazem... Mas tem sim como. Você cria um executável que extrai os dados compactados em um recurso. Aí tem duas opções de fazer isso: ou você gera o executável, seção por seção, coloca o recurso e o código de extração(x86), ou você cria no Delphi um executável(o auto-extract) que faça isso. Então no seu programa você coloca o .zip como recurso no executável auto-extract através da API do Windows. Mas dá uma olhada que tem componentes que fazem isso.



vocÊ poderia me dar um exemplo da segunda opção... de criar o auto-extrator usando o Delphi ... é pq o programa que eu fiz, precisa de umas configurações antes do programa rodar pela primeira vez... e eu to fazendo isso com o meu executavel. Só que no momento ele funciona com 2 arquivos, o executavel que eu fiz no Delphi e o .zip do que contém o programa... Eu gostária de ter somente o executavel do Delphi com o zip ´dentro´ dele


Responder

01/02/2004

Beppe

Eu posso te apontar como fazer, mas não posso te passar muito código, pois não tenho tempo(é um pouco demorado), e estou num sistema sem o SDK do Windows, e as funçãos não sei totalmente de cor.

Procedimentos:
1) Escreva e compile um programa no Delphi que faça isso:
- O seu componente de zip deve ter a opção de descompactar de uma stream para arquivo, certo? Você a usa pra pegar o recurso compactado.
Você acessa o recurso criando uma instância de TResourceStream, passando o nome do recurso. Passa entao essa stream pro zip descompactar.
2) Escreva e compile um programa no Delphi que faça isso:
Este programa gera o auto-extract. Ele pega o executável 1, abre com BeginUpdateResource, acrescenta o .zip como recurso passando um nome e tipo, depois chama EndUpdateResource.

Como disse não me lembro exato do nome das APIs, mas procura por resource na Windows.pas que tu acha algo.

Se tiver dúvidas é só falar.


Responder

01/02/2004

Paulocesar1301

Porque vc simplesmente não cria um .RES com o arquivo .ZIP dentro e joga dentro do seu projeto ? Usa o RCData. Qdopreciso de recursos externos uso assim e funciona blz.


Responder

02/02/2004

Doctor-x

Porque vc simplesmente não cria um .RES com o arquivo .ZIP dentro e joga dentro do seu projeto ? Usa o RCData. Qdopreciso de recursos externos uso assim e funciona blz.


você poderia me dar uma dica simples de como fazer isso?


Responder

13/02/2004

Beppe

Gente, conforme apontado pelo caninha51, tinha um erro numa rotina que postei, ExtractFiles. Era só um nome de parâmetro trocado. :oops:


Responder

16/02/2004

Caninha51

Na verdade, ainda continua com um errinho...

Em ExtractFile, e vez de...
Output.ReadBuffer(Pointer(Name)^, Len);

Eh...
Src.ReadBuffer(Pointer(Name)^, Len);

Só confundiu as Stream´s! :))

Valew Beppe!

Caninha51


Responder

17/02/2004

Beppe

procedure MergeFiles(const Dest: String; const Sources: array of String);
var
  I, Len: Integer;
  Output, Src: TStream;
begin
  Output := TFileStream.Create(Dest, fmCreate);
  try
    for I := 0 to High(Sources) do
    begin
      // escreve o nome do arquivo, prefixado com o tamanho do nome
      Len := Length(Sources[I]);
      Output.Write(Len, SizeOf(Integer));
      Output.Write(Pointer(Sources[I])^, Len);

      // copia o arquivo, prefixado com o tamanho do mesmo
      Src := TFileStream.Create(Sources[I], fmOpenRead or fmShareDenyWrite);
      try
        Len := Src.Size;
        Output.Write(Len, SizeOf(Integer));
        Output.CopyFrom(Src, Len);
      finally
        Src.Free;
      end;
    end;
  finally
    Output.Free;
  end;
end;

procedure ExtractFiles(const Filename: String);
var
  I, Len: Integer;
  Output, Src: TStream;
  Name: String;
begin
  Src := TFileStream.Create(Filename, fmOpenRead or fmShareDenyWrite);
  try
    while Src.Size > Src.Position do
    begin
      Src.ReadBuffer(Len, SizeOf(Integer));
      SetLength(Name, Len);
      Src.ReadBuffer(Pointer(Name)^, Len);

      Output := TFileStream.Create(Name, fmCreate);
      try
        Src.ReadBuffer(Len, SizeOf(Integer));
        Output.CopyFrom(Src, Len);
      finally
        Output.Free;
      end;
    end;
  finally
    Src.Free;
  end;
end;
Eu acabei escrevendo isto(não testei), mas depois vi que sua duvida pode ser outra. O que você quer é fazer um auto-extract? Se é juntar dois arquivos, o código é esse. Chama assim:
// juntando os arquivos
MergeFiles(´dest.dst´, [´source1.exe´, ´source2.zip´]);
// extrai os arquivos
ExtractFiles(´dest.dst´);



Responder

17/02/2004

Beppe

Na verdade, ainda continua com um errinho... Em ExtractFile, e vez de... Output.ReadBuffer(Pointer(Name)^, Len); Eh... Src.ReadBuffer(Pointer(Name)^, Len); Só confundiu as Stream´s! :)) Valew Beppe! Caninha51


Hehe, agora é um erro a menos. :wink:

PS: Continuo sem testar... :P


Responder

20/02/2004

Icheuk

Beppe tudo bem, espero que sim.

Voce colou uma dica muito interessante, a de juntar dois arquivos ou seja eu tenho o meu executavel e posso juntar a ele outro arquivo qualquer certo ?

Bom a pergunta é a seguinte, eu consigo alterar este segundo arquivo, via codigo sem tira-lo do arquivo principal.

Ex. Arq1.Exe, Arq2.Txt

Fiz o merge e ficou Arq1.Exe ( porem agora o exe tem o dois arquivos.

O conteudo do arq2.Txt:

este arquivo contem a letra A.

Agora eu quero colocar a letra B.

e o arquivo ficar assim:

este arquivo contem a letra AB.

teria como fazer isto sem extrair o arquivo Txt e depois fazer o merge novamente.

Agradeço antecipadamente a ajuda.


Responder

20/02/2004

Beppe

teria como fazer isto sem extrair o arquivo Txt e depois fazer o merge novamente.


Não é simples como append´er esse bytes, é necessário atualizar o tamanho do arquivo também.

procedure AppendStringToSecondFile(const Filename: String; const Text: String);
var 
  I, Len: Integer; 
  Output, Src: TStream; 
  Name: String; 
begin 
  Src := TFileStream.Create(Filename, fmOpenReadWrite or fmShareDenyWrite); 
  try
    // pula o primeiro arquivo
    Src.ReadBuffer(Len, SizeOf(Integer));
    Src.Seek(Len, soFromCurrent);

    // atualiza o tamanho do segundo arquivo
    Src.ReadBuffer(Len, SizeOf(Integer));
    Src.Seek(-SizeOf(Integer), soFromCurrent);
    Inc(Len, Length(Text));
    Src.WriteBuffer(Len, SizeOf(Integer));

    // acrescenta novos dados
    Src.Seek(0, soFromEnd);
    Src.WriteBuffer(Pointer(Text)^, Length(Text));
  finally 
    Src.Free; 
  end; 
end;


PS: não testei


Responder

12/09/2005

Guilherme

para juntar parece estar juntando certin mais para extrair nao estou achando para onde ele extrai os arquivos , tem como indicar um local para a extraçao ????


Responder

01/10/2005

Beppe

Oi.

Vou te ensinar como modificar a(s) rotina(s) para seus propósitos. Usei o caminho absoluto tanto para merge como extract. Na hora de extrair, o arquivo será criado dentro do diretório original, o que pode ou não ser o desejado. Chame ExtractFilename(Nome) para pegar apenas a porção que indica o nome relativo do arquivo, e ao criar o arquivo, ou sete o diretório corrente(SetCurrentDir) ou concatene um novo nome de diretório. Lembre-se de que o diretório já precisa estar criado, pode garantir isso com ForceDirectories(Nome).

Boa sorte.


Responder

Assista grátis a nossa aula inaugural

Assitir aula

Saiba por que programar é uma questão de
sobrevivência e como aprender sem riscos

Assistir agora

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar