7
votes

écrire un bitset à un fichier en Java

J'ai un bitset et je veux l'écrire dans un fichier - je suis tombé sur une solution pour utiliser une optionOutputStream à l'aide de la méthode WriteObject.

J'ai regardé l'objetOutPutStream dans l'API Java et j'ai vu que vous pouvez écrire d'autres choses (octet, int, court etc.)

J'ai essayé de vérifier la classe afin que j'ai essayé d'écrire un octet à un fichier à l'aide du code suivant, mais le résultat me donne un fichier avec 7 octets au lieu de 1 octet

Ma question est quels sont les 6 premiers octets du fichier? Pourquoi sont-ils là-bas?

Ma question est pertinente pour un bitset car je ne veux pas commencer à écrire beaucoup de données dans un fichier et réalisez que j'ai des octets aléatoires insérés dans le fichier sans savoir ce qu'ils sont.

Voici le code: xxx

merci pour toute aide

AVNER


0 commentaires

4 Réponses :


1
votes

Vous pouvez écrire des objets sur un ObjectOutPutStream , de sorte que le flux contient des informations sur les types écrits ainsi que les données nécessaires pour reconstituer l'objet.

Si vous savez que le flux contiendra toujours un bitset, n'utilisez pas un ObjectOutPutStream - et si l'espace est une prime, puis convertissez le bitset à un ensemble d'octets où chaque bit correspond à un peu dans le bitset , puis écrivez-en directement sur le flux sous-jacent (par exemple, un FileOutOutStream comme dans votre exemple).


3 commentaires

Malheureusement, Bitset n'a pas de méthode intégrée pour la convertir en une gamme d'octets.


Il y a la méthode: TobyeArray ()


@ clankill3r: Oui, avec Tolongarray () , mais seulement depuis Java 7.



2
votes

Les autres octets seront des informations de type.

Fondamentalement ObjectOutPutStream est une classe utilisée pour écrire des objets sérialisables à une destination (généralement un fichier). Cela a plus de sens si vous pensez à InputObjectstream. Il a une méthode LisaObject () dessus. Comment Java sait-elle quel objet instancier? Facile: il y a des informations de type là-bas.


3 commentaires

Donc, si je vous comprends correctement - chaque fois que j'écris quelque chose en utilisant ObjectOutputStream, je reçois des frais généraux sérieux pour chaque écriture. Par exemple, si j'écris un int, un court, un octet et une chaîne, je reçois 4 séries de données supplémentaires pour chaque article que j'écris?


Non. Seule la méthode WriteObject () ajoute l'en-tête de type. La méthode ERITUTF () ajoute un préfixe de lenght de 2 octets. Les méthodes primitive extritexx () n'ajoutent aucun aérien. Lisez l'API DOC pour plus de détails.


Notez également que les informations de type sont par objet. Pour un objet qui consiste essentiellement d'une matrice primitive (telle que Bitset), la surcharge est constante, quelle que soit la taille de la matrice.



0
votes

Le format de sérialisation, comme beaucoup d'autres, comprend un en-tête avec des informations de numéro magique et de version. Lorsque vous utilisez dataOutputtput / sortiestream méthodes sur ObjectOutPutStream sont placés au milieu des données sérialisées ( sans aucun type d'information ). Ceci est typiquement uniquement dans WriteObject implémentations après un appel sur defaultwriteObject ou d'utilisation de Putfields .


0 commentaires

0
votes

Si vous utilisez uniquement le bitset enregistré en Java, la sérialisation fonctionne bien. Cependant, c'est un peu ennuyeux si vous voulez partager le bitset sur plusieurs plates-formes multiples. Outre les frais généraux de la sérialisation Java, le bitset est stocké en unités de 8 octets. Cela peut générer trop de frais généraux si votre bitset est petit.

Nous avons écrit cette petite classe afin que nous puissions exagérer des tableaux d'octets de Bitset. En fonction de votre usecase, cela pourrait fonctionner mieux que la sérialisation Java pour vous. P>

public class ExportableBitSet extends BitSet {

    private static final long serialVersionUID = 1L;

    public ExportableBitSet() {
        super();
    }

    public ExportableBitSet(int nbits) {
        super(nbits);
    }

    public ExportableBitSet(byte[] bytes) {
        this(bytes == null? 0 : bytes.length*8);        
        for (int i = 0; i < size(); i++) {
            if (isBitOn(i, bytes))
                set(i);
        }
    }

    public byte[] toByteArray()  {

        if (size() == 0)
            return new byte[0];

        // Find highest bit
        int hiBit = -1;
        for (int i = 0; i < size(); i++)  {
            if (get(i))
                hiBit = i;
        }

        int n = (hiBit + 8) / 8;
        byte[] bytes = new byte[n];
        if (n == 0)
            return bytes;

        Arrays.fill(bytes, (byte)0);
        for (int i=0; i<n*8; i++) {
            if (get(i)) 
                setBit(i, bytes);
        }

        return bytes;
    }

    protected static int BIT_MASK[] = 
        {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};

    protected static boolean isBitOn(int bit, byte[] bytes) {
        int size = bytes == null ? 0 : bytes.length*8;

        if (bit >= size) 
            return false;

        return (bytes[bit/8] & BIT_MASK[bit%8]) != 0;
    }

    protected static void setBit(int bit, byte[] bytes) {
        int size = bytes == null ? 0 : bytes.length*8;

        if (bit >= size) 
            throw new ArrayIndexOutOfBoundsException("Byte array too small");

        bytes[bit/8] |= BIT_MASK[bit%8];
    }
}


0 commentaires