Pipino ObjectOsDoisStream urgente!

7 respostas
C

E ai galera to com um probleminha aqui e preciso da ajuda de vcs.
Tenho um um arquivo cheio de objetos (Blocos), suponha que seja 10.Como q faco para acessar este aquivo RANDOMINACAMENTE mas lidando com read e/ou write de objetos(Blocos).Por exemplo, em deteminado instante eu queira acessar DIRETAMENTE o bloco 7 neste arquivo e, em outro instante, o bloco 10 _ como o RandoAccessFile faz com byte[]_ para escrita e/ou leitura.
Obs: nao tenho a necessidade de read e write em um mesmo metodo pode ser separados.

Faleu Carlos Martins.

7 Respostas

T

Se você já olhou no formato do arquivo gerado por ObjectOutputStream, vai ver que ele não é adequado para acesso aleatório. O pior caso é quando um objeto é composto de outros objetos, que já foram gravados no arquivo anteriormente. Nesse caso o ObjectOutputStream simplesmente grava uma referência para esses outros objetos que já foram gravados, em vez de gravá-los novamente. Isso é legal porque um objeto deve existir apenas uma vez em um ObjectOutputStream, mas é terrível para poder efetuar o acesso aleatório.
Por exemplo, você precisaria ter dois arquivos: um com um índice, e outro com registros contendo um objeto somente (mas não um ObjectOutputStream, que tem essa característica que comentei). Você teria de fazer um “banco de dados orientado a objetos”.

danieldestro

Talvez serializar com XStream seja uma solução.

C

thingol deixa eu ver se entendi!!!

Vc dize que o objeto nao pode ser regravavel.Mas entao como que o objetoOutputStream trataria caso o objeto fosse
alterado na execuçao do programa, ou seja, ele tever algum de seus dados mudado? Estou implementando um banco de dados mesmo como vc citou (para projeto de Facu) nao como um mysql eh claro; mas simples.O que vc me aconselharia a fazer para resolver este problema tendo em vista esta implementaçao de objetos?

Valeu
Carlos Martins

T

Na verdade não sei exatamente como seria adequado um acesso aleatório em bancos de dados de objetos.
Precisaria estudar mais para saber o que é necessário num banco desses, e como isso é implementado (por exemplo, no Jasmine).
Para serializar um objeto sozinho, você pode usar o próprio ObjectOutputStream, só que gravando um objeto de cada vez, ou então o XStream, como o Destro sugeriu (o XStream é uma generalização da classe java.beans.XMLEncoder/XMLDecoder). Mas para representar as relações entre objetos já é mais difícil.
Dê uma olhada no Ozone, por exemplo (http://www.ozone-db.org ).
Dica: para achar no Google as palavras-chave são “OODBMS” e “Java”.

C

Eu queria uma coisa mais ou menos assim:

//class típo

public class Tipo implements Serializable

{

private char[] nomeTipo;

private char tamanho[];

//construtor utilizado para varchar
public Tipo(String nome, int tam)

{

this.nomeTipo = nome.toCharArray() ;

this.tamanho = new char[tam];
}

//metodos

}

//class registro

public class Registro implements Serializable

{

private char[] sNome;

private Tipo tipo;

private char[] sPrimaria;

private char[] sEstrangeira;

private String[] vetValor;

private static int iValor = 10; // maximo de valores suportados

private int numValor = 0; //numero de valores existentes

public Registro(String nomeReg,Tipo tipo,String chave)

{

this.sNome = nomeReg.toCharArray() ;

this.tipo = tipo;

this.vetValor = new String[iValor];

if(chave.equals(primaria))

this.sPrimaria = chave.toCharArray() ;

else if(chave.equals(estrangeira))

this.sEstrangeira = chave.toCharArray() ;

}

//metodos

}

//class bloco

public class Bloco implements Serializable

{

private Registro[] bloco;

private int qtdeRegistro;

private int numReg=0;

private int numBloco;

public Bloco(int tamBloco,int numBloco)

{

this.bloco = new Registro[tamBloco];

this.qtdeRegistro = tamBloco;

this.numBloco = numBloco;

}

//metodos

}

//METODP SIZEOF ACOXAMBRADO

public static int sizeof(Object o)

{

try

{

ByteArrayOutputStream ba = new ByteArrayOutputStream();

ObjectOutputStream oos = new ObjectOutputStream(ba);

oos.writeObject(o);

return ba.toByteArray().length;

}

catch (IOException ex)

{

throw new RuntimeException(ex.toString());

}

}

PRECISARIA UMA COISA DESTE TIPO SO QUE FIZ ALGUNS TESTES MAIS NAO FUNCIAONA

public Bloco  leBloco(Banco banco,int posicao) //throws FileNotFoundException

{

String sArqBanco = banco.getNomeArquivo();

Bloco bloco=null;

//int iLocalizacao=0;

//Vector vetIdent = banco.getVetIdentificador();

//IdentificaBloco idBloco = (IdentificaBloco)vetIdent.elementAt(posicao);

//int tamBloco = idBloco.getSizeOf();

if(posicao ==-1)

{

return null;

}

else

{

try

{

FileInputStream f = new FileInputStream(sArqBanco);

ObjectInputStream input = new ObjectInputStream( f );

for(int i=0;i < posicao;i++)

{

input.readObject();

//idBloco = (IdentificaBloco)vetIdent.elementAt(i);

//iLocalizacao = iLocalizacao + idBloco.getSizeOf();

}

bloco = (Bloco)input.readObject();

input.close();

return bloco;

/*

RandomAccessFile random = new RandomAccessFile(sArqBanco,“r”);

random.seek(iLocalizacao);

byte[] buf = new byte[tamBloco];

random.read(buf);

Object obj =(Object)buf; //DA PALA DE EXEC.

bloco = (Bloco)obj;

return bloco;

*/
}
         catch(IOException e) 
         {
            JOptionPane.showMessageDialog(null,"Problemas em desalocar blocos");
            
         }
         
    }
    return bloco;
 }
 public void  gravaBloco(Banco banco,int posicao,Bloco bloco) //throws FileNotFoundException
 {
    String sArqBanco = banco.getNomeArquivo();
    int iLocalizacao=0;
    Vector vetIdent = banco.getVetIdentificador();
    IdentificaBloco idBloco = (IdentificaBloco)vetIdent.elementAt(posicao);
    int tamBloco = idBloco.getSizeOf();
    if(posicao ==-1)
    {
        JOptionPane.showMessageDialog(null,"ERRO: posicao -1");
    }  
    else  
    {
         
         try
         {
            RandomAccessFile random = new RandomAccessFile(sArqBanco,"w");
            for(int i=0;i < posicao;i++)
            {
               idBloco = (IdentificaBloco)vetIdent.elementAt(i);
               iLocalizacao = iLocalizacao + idBloco.getSizeOf();
            }
            random.seek(posicao);
            FileOutputStream f = new FileOutputStream(random.getFilePointer()); 
            ObjectOutputStream output = new ObjectOutputStream(f);
            output.writeObject(Output);
            output.close();
            
            /*
              RandomAccessFile random = new RandomAccessFile(sArqBanco,"w");
              random.seek(iLocalizacao);
              Object obj =(Object)bloco;
              byte[] buf = (byte[])obj; //DA PALA DE EXEC.
              random.write(buf);
              JOptionPane.showMessageDialog(null,"bloco gravado teste");
            */  
              
         }
         catch(IOException e) 
         {
            JOptionPane.showMessageDialog(null,"ERRO:"+e.toString());
            
         }
         
    }
 }

}
O objeto IdentificaBloco identifica onde o bloco de determinada tabela se encontra no disco.Possui tambem um campo tamanho = IdentificaBloco.sizeof()

Desculpe ai cara mas to precisando de ajuda nesta pala ai.Se mudar o esquema como vc me disse terei de fazer tudo de novo e nao tenho mais tempo.

Valeu
Carlos Martins

T

Se você quer gravar apenas um objeto serializável em um campo, tal como faz o HSQLDB (que tem um tipo OBJECT que é realmente uma forma de guardar objetos serializados em bancos de dados), você está no caminho certo (não li seu código inteiro, mas deve ser só alguma coisa boba que está errada aí).
Pegue o seu objeto, grave-o com writeObject em um ObjectOutputStream que está ‘wrapped’ em um ByteArrayOutputStream, pegue os bytes do ByteArrayOutputStream e guarde-os em um campo de sua tabela.
Ao recuperar o objeto, pegue os bytes do campo da sua tabela, monte um ByteArrayInputStream com o byte array que você, e ‘wrap’ isso em um ObjectInputStream. O seu objeto será corretamente deserializado com readObject.

C

Cara brigadao vc quebrou nao um galho mais a arvore inteira; acho q agora dah para resolver o problema.Acho q a pala era nesse lance de empacotamento (wrapped) e deserializaçao , pois tinha a necessidade de escrever/ler em byte[] devido ao RandomAccessFile e lidar em nivel de execuçao com objetos(Blocos).Na leitura ate q tudo bem _deslocava o ponteiro do ObjectInputStream com readObject() _ mas, na escrita, a coisa conplicava um pouco pois devia percorrer, no pior caso, o arquivo quase inteiro a procura do Bloco desejado e isso sobreescrivia todos os objetos do banco que se encontrava localizado antes do Bloco q estava sendo gravado.
Nao testei ainda mais creio q ira funcionar

Valeu
Carlos Martins

Criado 16 de março de 2005
Ultima resposta 19 de mar. de 2005
Respostas 7
Participantes 3