Como ler e gravar um arquivo binário ?
Amigos, estou num projeto de geração de Patch... este sistema deverá ler qualquer tipo de arquivo binário (por exemplo: arquivos fonte do FORMS *.fmb ), percorrê-lo para encontrar uma sequência "$Header" (em binário), alterá-lo e depois gravar novamente em binário.
Com o código abaixo, já consigo percorrer o arquivo byte a byte e criar o novo arquivo sem danificá-lo... mas ainda não sei como encontrar o que eu quero!
Alguém pode me ajudar?
****************
[b]editado pelo moderador. Não esqueçam de postar códigos entre as tags code[/b]
****************
public static void lerArquivoBin(String origem, String destino){
try{
File fileOrigin = new File(origem);
File fileDestiny = new File(destino);
FileInputStream i = new FileInputStream(fileOrigin);
FileOutputStream o = new FileOutputStream(fileDestiny);
BufferedInputStream in = new BufferedInputStream(i);
BufferedOutputStream out = new BufferedOutputStream(o);
int x;
while((x = in.read()) != -1){
out.write(x);
System.out.println("byte = "+x);
}
in.close();
out.close();
}catch(Exception e){
System.out.println("Erro = "+e);
}
}Mauricio Hiroshi
Curtidas 0
Respostas
Bruno Ghisi
09/04/2009
Um jeito de fazer é ler o arquivo em bytes e transformar em String para poderes manipular melhor e depois criar o novo arquivo. Exemplo abaixo acrescido do teu código fazendo isso:
[b]editado pelo moderador. Não esqueçam de postar códigos entre as tags code[/b]
public static void lerArquivoBin(String origem, String destino){
try{
File fileOrigin = new File(origem);
File fileDestiny = new File(destino);
BufferedInputStream in = new BufferedInputStream(new FileInputStream(fileOrigin));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int x = 0;
while((x = in.read()) != -1){
baos.write(x);
}
in.close();
String fileContent = new String(baos.toByteArray());
//manipular o fileContent de acordo com desejado para modificar os $Header, exemplo bobo concantenado um "testado" abaixo para notares a modificação sobre o original
fileContent += "testando";
FileOutputStream o = new FileOutputStream(fileDestiny);
o.write(fileContent.getBytes());
o.flush();
o.close();
}catch(Exception e){
System.out.println("Erro = "+e);
}
}GOSTEI 0
Mauricio Hiroshi
09/04/2009
Olá Bruno, obrigado pelo código. Bem, mas tenho um grande problema ao tentar fazer desta maneira:
Se faço a leitura byte a byte e escrevo o novo arquivo byte a byte, o arquivo não é corrompido, porém desta maneira apresentada, quando transformo cada byte em String, depois volto para byte, o arquivo é corrompido.
Se o arquivo for somente texto, não há problemas, mas no tipo de arquivo que estou tratando, existem bytes que, quando transformados em String, viram caracteres desconhecidos (um monte de quadrados), e estes ao voltarem para bytes é que se perdem, acredito.
Encontramos uma forma que deu certo, lendo de byte a byte e escrevendo byte a byte, mas quando encontro o byte 36 (referente ao $) fazemos uma lógica para verificar se é um trecho String e o qual procuramos para aí sim manipularmos esse trecho onde sabemos que não há problemas em se substituir para String e retornar para byte.
De qualquer forma, fiz um teste utilizando o seu código (segue abaixo), e se tiver alguma idéia melhor, ou encontrar algum erro, por favor me diga, eu o agradeço desde já.
**************************
[b]editado pelo moderador. Não esqueçam de postar códigos entre as tags code[/b]
**************************
public static void generatePatch(String fileOrigin, String fileName, String version, String versionDate, String user){
try{
BufferedInputStream in = new BufferedInputStream(new FileInputStream(new File(fileOrigin)));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int x;
while((x = in.read()) != -1) baos.write(x);
in.close();
String fileContent = new String(baos.toByteArray());
if (fileContent.indexOf("$Header: %f% %v% %d% %u% ship $") == -1)
System.out.println("Arquivo fora de padrão.");
else{
fileContent = fileContent.replace("%f%",fileName);
fileContent = fileContent.replace("%v%",version);
fileContent = fileContent.replace("%d%",versionDate);
fileContent = fileContent.replace("%u%",user);
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File(fileOrigin)));
out.write(fileContent.getBytes());
out.flush();
out.close();
System.out.println("Patch "+fileOrigin+" gerado com sucesso.");
}
}catch(FileNotFoundException fnfe){
System.out.println("Erro: O arquivo "+fileOrigin+" não foi localizado.");
}catch(IOException ioe){
System.out.println("Erro: Falhou ao ler/gravar arquivo.");
}catch(Exception e){
System.out.println("Erro desconhecido: "+e);
}
}
GOSTEI 0
Bruno Ghisi
09/04/2009
Agora que li que era binário e não texto puro, mas que bom que arrumasse e deu certo!
Valeu!
GOSTEI 0
Bruno Ghisi
09/04/2009
Olá Mauricio!
Estive lendo e achei muito interessante o que vc fez. Eu estou querendo resolver um problema muito parecido com o seu.
Eu quero ler um arquivo binário que não sei o que tem escrito nele e nem como está formatado e converte-lo para texto para armazenar em um arquivo onde eu possa abrir em um editor de texto normal e assim vê o que contem nele.
Agradeço
GOSTEI 0
Mauricio Hiroshi
09/04/2009
Fala cara,
Então, se quer apenas transformar um binário em String basta seguir o código acima aí do nosso amigo Bruno onde ele instancia new String(baos.toByteArray()), porém dependendo de que tipo de arquivo você queira fazer isso, o resultado pode ser um monte de caracter desconhecido.
flw
GOSTEI 0
Carlos Heuberger
09/04/2009
[quote="mauriciohiroshi"]Fala cara,
Então, se quer apenas transformar um binário em String basta seguir o código acima aí do nosso amigo Bruno onde ele instancia new String(baos.toByteArray()), porém dependendo de que tipo de arquivo você queira fazer isso, o resultado pode ser um monte de caracter desconhecido.
flw
desconfio queuma representação hexadecimal possa ajudar.
int x;
...
String hex = String.format("%02x", x); // ou semelhante
GOSTEI 0