2012-06-26 7 views
3

J'essaie d'écrire mes données spatiales d'une table dans un fichier. Mais j'ai besoin de connaître la taille exacte des données sur le disque avant d'écrire sur le disque. À titre d'exemple, disons que je suis en train d'écrire sur le disque en utilisant le code suivant:estimation de la taille du fichier sur le disque lors de l'utilisation de ObjectOutputStream

FileOutputStream fos = new FileOutputStream("t.tmp",false); 
    ObjectOutputStream oos = new ObjectOutputStream(fos); 
    oos.writeInt(gid); 
    oos.writeUTF(fullname); 
    oos.writeInt(d.shape.length); 
    oos.write(d.shape); 

    oos.close(); 
    fos.close(); 

Je pensais que la taille du fichier sur le disque est égal à:

size= 4B {for gid, int} + fullname.getBytes.length() {string} + 4B {d.shape.length, int} + d.shape.length 

mais en fait, ce qui est très différent de la taille réelle du fichier sur le disque.

J'ai également remarqué que même créer un fichier vide en utilisant ObjectOutputstream conduit à l'espace 4B sur le disque.

Une aide sur la façon de calculer la taille du fichier sur le disque?

(je ne peux pas écrire les données sur le disque, puis lire la taille réelle. Cela permettra de diminuer les performances. Au lieu de cela, je dois calculer la taille des données sur le disque en fonction des valeurs de données stockées dans la mémoire.)

+0

Avez-vous vraiment besoin d'un objet * OutputStream? Utilisez-vous 'writeObject()'? Ou votre code d'exemple est-il aussi sophistiqué que vous l'obtenez? Il semble que vous feriez mieux d'utiliser un [DataOutputStream] (http://docs.oracle.com/javase/6/docs/api/java/io/DataOutputStream.html). (Un objet 'ObjectOutputStream' écrit des informations d'en-tête de flux et garde la trace des références aux objets déjà écrits afin qu'il puisse simplement écrire une référence etc. - tout cela entraverait vos efforts pour pré-calculer la taille. –

+0

Également - pouvez-vous développer le problème de performances que vous percevez en utilisant le système de fichiers après l'écriture des octets? –

+0

en termes de problème de performance. J'ai 40 Go de données dans ma table et beaucoup d'entre elles sont des données spatiales. Je partitionne ma table de manière à ce que la taille totale des données stockées dans chaque fichier soit inférieure à une certaine valeur (max_file_size). Au premier tour, je calcule la taille sur le disque de chaque rangée de ma table et dans les tours suivants, je résume tant d'entre eux qui peuvent tenir dans un fichier avec une taille de fichier totale inférieure à max_file_size. Ainsi, écrire chaque fichier et ensuite mesurer la taille réelle du fichier sur le disque n'est pas une option. – reza

Répondre

1

En supposant que cela ne vous dérange pas de gaspiller de la mémoire, vous pouvez tout d'abord l'écrire dans un ByteArrayOutputStream, puis obtenir la taille.

ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
ObjectOutputStream oos = new ObjectOutputStream(boas); 
oos.writeInt(gid); 
oos.writeUTF(fullname); 
oos.writeInt(d.shape.length); 
oos.write(d.shape); 

oos.close(); 
boas.close(); 
int size = boas.size(); 
+0

génial. Cela fonctionne très bien si je veux calculer la taille d'une ligne de données. Je calcule ceci pour chaque ligne de données et je la stocke dans ma table sous la colonne block_size. Je sélectionne alors tant de lignes que leur taille_bloc cumulée est inférieure à une certaine valeur. Le problème est que la somme des valeurs block_size de deux lignes est supérieure à la taille de fichier des deux lignes écrites sur le disque. Une idée sur la façon de résoudre cette partie? – reza

+0

@reza Si vous avez besoin d'être précis, vous devez d'abord sérialiser l'ensemble de la structure de données en mémoire (ou dans un fichier temporaire). La sérialisation Java supprimera les objets dupliqués et les chaînes de sorte que vous ne supportiez pas deux fois plus d'espace. –

+0

merci, j'ai fini par utiliser DataOutputStream. De cette façon, ma taille calculée correspond exactement à la taille du fichier sur le disque. merci pour les suggestions. – reza

2

Je suis en train d'écrire mes données spatiales à partir d'une table dans un fichier. Mais j'ai besoin de connaître la taille exacte des données sur le disque avant d'écrire sur le disque.

Vous ne devriez pas utiliser un ObjectOutputStream. Un ObjectOutputStream peut sérialiser automatiquement un graphique complexe d'objets pour vous - mais cela ne semble pas être l'une de vos exigences. Dans le cadre de cette sérialisation, le ObjectOutputStream écrit certaines informations d'en-tête de flux (les 4 octets que vous avez découverts au début) et conserve les objets écrits précédemment afin de pouvoir écrire des valeurs de marqueur spéciales plutôt que d'écrire tout l'objet . En revanche, utilisez simplement un DataOutputStream. Il fournit la même fonctionnalité que vous le souhaitez:

Un flux de sortie de données permet à une application d'écrire des types de données Java primitifs dans un flux de sortie de manière portable. Une application peut alors utiliser un flux d'entrée de données pour lire les données avant.

FileOutputStream fos = new FileOutputStream("t.tmp",false); 
DataOutputStream dos = new DataOutputStream(fos); 
dos.writeInt(gid);     // write 4 bytes 
dos.writeUTF(fullname);   // write 2 bytes of length, then variable length string (UTF encoded) 
dos.writeInt(d.shape.length);  // write 4 bytes 
dos.write(d.shape);    // write a variable length byte array 

dos.close(); 
fos.close(); 

Il n'y aura pas de surprises ici (à condition que vous savez combien d'octets votre chaîne UTF codé finira), et vous pouvez faire l'arithmétique pour calculer quelle sera la taille exacte du fichier.

(Si vous utilisiez des chaînes qui ne se limitaient pas à un caractère d'un octet, vous pouvez d'abord convertir la chaîne en un tableau d'octets à l'aide d'un encodeur charset).

+0

merci beaucoup. Cela a résolu le problème. Il semble que j'ai besoin de rafraîchir ma mémoire sur les flux Java. Recommandez-vous un tutoriel sur les flux Java? – reza

+0

@reza: non, désolé - je voudrais juste google pour ça ... –

Questions connexes