2010-01-09 12 views
1

J'ai créé un java.nio.MappedByteBuffer autour d'un java.io.RandomAccessFile (un fichier de seulement 54 Ko). Le résultat MappedByteBuffer a une «capacité» et une «limite» d'environ 12 Ko, alors quand j'essaie d'invoquer mybytebuffer.get(i > 13044) ou mybytebuffer.put(i > 13044, value), il lance un InvalidIndexException.Java.NIO InvalidIndexException - comment lire et écrire avec un accès aléatoire aux fichiers volumineux

Tout ce comportement est documenté dans les javadocs officiels de Sun. Ma question est comment je peux utiliser java.nio ByteBuffers pour lire ou écrire n'importe où dans le fichier (j'ai besoin d'un accès aléatoire). Je n'arrive pas à trouver un exemple ou une documentation de Java NIO qui illustre l'accès non-séquentiel.

+0

avez-vous essayé d'appeler la limite (la taille réelle)? – bmargulies

+0

Oui, mais je ne peux pas définir limite> capacité. La capacité est une limite dure qui ne peut pas être augmentée. J'espérais que je pourrais cacher le fait qu'un ByteBuffer était enroulé autour d'un fichier pour le code qui l'utilise, mais cela me semble impossible maintenant: il n'y a pas de solutions natives et vous ne pouvez pas étendre ByteBuffer pour faire votre propre abstraction. Laid. –

+1

Pourquoi s'embêter avec un fichier mappé en mémoire pour un fichier de 54 Ko? Le mappage de la mémoire a ses avantages pour les fichiers volumineux. Pour les petits fichiers, il est souvent plus lent car l'initialisation du mappage prend un certain temps. – dmeister

Répondre

1

MappedByteBuffer peut accéder aux fichiers de manière aléatoire ... il s'agit d'un 'buffer d'octets direct'. (Plus précisément, il utilise le sous-système de mémoire virtuelle pour cartographier le fichier dans la mémoire du système d'exploitation.)

Vous pouvez accéder à des octets au hasard comme dans l'extrait de code ici:

public void doIt() throws FileNotFoundException, IOException { 
    File file = new File("myfile"); 
    RandomAccessFile raf = new RandomAccessFile(file, "rw"); 
    FileChannel fc = raf.getChannel();  
    MappedByteBuffer mbb = fc.map(MapMode.READ_WRITE, 0, file.length()); 

    //get a random byte 
    byte b1 = mbb.get(SOME_RANDOM_BYTE); 

    //get another random byte 
    mbb.position(SOME_OTHER_BYTE_POSITION); 
    byte b2 = mbb.get(); 
} 

Vous pouvez déplacer le MBB et octets d'accès (à la fois lire et écrire) comme vous devez.

+0

+1. fonctionne tant que file.length() est inférieur à Integer.MAX_INT. – dmeister

+0

Je semble recevoir une exception NonWriteableChannelException en utilisant ceci; Je vais regarder dedans. –

+0

Si vous utilisez un FileInputStream, le canal n'est pas accessible en écriture. Si vous utilisez un FileOutputStream, le canal n'est pas lisible. Utilisez un RandomAccessFile pour produire un canal lisible et inscriptible. –

0

MappedByteBuffers n'offre pas lui-même un accès aléatoire. C'est un malentendu. Utilisez un SeekableByteChannel pour un accès aléatoire.