Juntar 2 arquivos num só
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
Curtidas 0
Respostas
Beppe
31/01/2004
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´);
GOSTEI 0
Doctor-x
31/01/2004
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
GOSTEI 0
Beppe
31/01/2004
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.
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.
GOSTEI 0
Doctor-x
31/01/2004
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
GOSTEI 0
Beppe
31/01/2004
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.
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.
GOSTEI 0
Paulocesar1301
31/01/2004
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.
GOSTEI 0
Doctor-x
31/01/2004
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?
GOSTEI 0
Beppe
31/01/2004
Gente, conforme apontado pelo caninha51, tinha um erro numa rotina que postei, ExtractFiles. Era só um nome de parâmetro trocado. :oops:
GOSTEI 0
Caninha51
31/01/2004
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
Em ExtractFile, e vez de...
Output.ReadBuffer(Pointer(Name)^, Len);
Eh...
Src.ReadBuffer(Pointer(Name)^, Len);
Só confundiu as Stream´s! :))
Valew Beppe!
Caninha51
GOSTEI 0
Beppe
31/01/2004
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´);
GOSTEI 0
Beppe
31/01/2004
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
GOSTEI 0
Icheuk
31/01/2004
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.
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.
GOSTEI 0
Beppe
31/01/2004
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
GOSTEI 0
Guilherme
31/01/2004
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 ????
GOSTEI 0
Beppe
31/01/2004
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.
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.
GOSTEI 0
Andrew Vargas
31/01/2004
Beleza Doctor-x? Você conseguiu resolver o problema? Eu tenho uma dúvida parecida, se puder dá uma olhada nesse link https://www.devmedia.com.br/forum/executar-programa-carregado-em-um-memorystream/486076
Valeu.
Valeu.
GOSTEI 0
Anderson Jesus
31/01/2004
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
Olá, precisei fazer um merge dos xml originados do ClientDataSet e acabei apanhando bastante da rotina (Deve ser por conta do Windows 10), pois o nome do arquivo nunca era salvo corretamente dentro do arquivo de destino. (Geralmente gravava lixo de memória ou metade do nome). Depois de muito estudar e ter que aprender ponteiros (Principalmente na parte que ensina como as Strings são controladas em https://www.devmedia.com.br/ponteiros-clube-delphi-118/17178) consegui entender o problema e fiz algumas alterações na rotina para salvar sem o diretório do arquivo e com a alteração de String para AnsiString .
Caso alguém precise:
procedure TfrmPediEsto.MergeFiles(const Dest: String; const Sources: array of String); var I, Len: Integer; Output, Src: TStream; ls_Arq : AnsiString; 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 ls_Arq := ExtractFileName(Sources[I]); Len := Length(ls_Arq); Output.Write(Len, SizeOf(Integer)); Output.Write(PAnsiString(ls_Arq)^, 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 TfrmPediEsto.ExtractFiles(const Filename: String; Diretorio: String); var I, Len: Integer; Output, Src: TStream; Name: AnsiString; 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(PAnsiString(Name)^, Len); Output := TFileStream.Create(Diretorio + Name, fmCreate); try Src.ReadBuffer(Len, SizeOf(Integer)); Output.CopyFrom(Src, Len); finally Output.Free; end; end; finally Src.Free; end; end;
GOSTEI 0