Juntar 2 arquivos num só
31/01/2004
0
Doctor-x
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´);
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
31/01/2004
Beppe
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.
01/02/2004
Doctor-x
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
01/02/2004
Beppe
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.
01/02/2004
Paulocesar1301
02/02/2004
Doctor-x
você poderia me dar uma dica simples de como fazer isso?
13/02/2004
Beppe
16/02/2004
Caninha51
Em ExtractFile, e vez de...
Output.ReadBuffer(Pointer(Name)^, Len);
Eh...
Src.ReadBuffer(Pointer(Name)^, Len);
Só confundiu as Stream´s! :))
Valew Beppe!
Caninha51
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;
// juntando os arquivos MergeFiles(´dest.dst´, [´source1.exe´, ´source2.zip´]); // extrai os arquivos ExtractFiles(´dest.dst´);
17/02/2004
Beppe
Hehe, agora é um erro a menos. :wink:
PS: Continuo sem testar... :P
20/02/2004
Icheuk
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.
20/02/2004
Beppe
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
12/09/2005
Guilherme
01/10/2005
Beppe
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.
Clique aqui para fazer login e interagir na Comunidade :)