J'ai besoin d'écrire des enregistrements dans un fichier où les données sont écrites à un emplacement de fichier (c.-à-d. Position de recherche) en fonction de la valeur d'une clé numérique . Par exemple, si la clé est 100, je pourrais écrire à la position 400.Java - comment écrire efficacement un fichier séquentiel avec des trous occasionnels
Les enregistrements sont constitués de la clé numérique et d'une donnée. L'enregistrement ne sera pas très grand (quelques octets). Cependant, il peut y avoir beaucoup d'enregistrements (millions).
Il existe deux scénarios possibles:
Les clés augmentent de façon monotone. Dans ce cas, la meilleure approche consiste à écrire en utilisant un
DataOutputStream
enveloppant unBufferedOutputStream
, en réglant la taille de la mémoire tampon sur un certain nombre (par exemple 64k) pour maximiser le débit d'E/S.Les clés sont en augmentation mais avec des écarts importants possibles. Dans ce cas, l'utilisation d'un OutputStream nécessite l'écriture de zéros dans les espaces du fichier. Pour éviter cela, un
RandomAccessFile
serait mieux car il pourrait chercher sur les lacunes, économiser de l'espace s'il est possible de chercher sur un bloc entier. L'inconvénient est que, pour autant que je sache,RandomAccessFile
ne tampon pas, donc cette méthode va être lente pour les touches séquentielles.
Cependant, la situation probable est que le fichier est un peu des deux. Il existe des séquences de clés monotones croissantes. Il y a quelques clés avec de petits espaces entre et d'autres avec de très grands espaces. Ce que je cherche est une solution qui offre le meilleur des deux mondes. Il se peut que je commute entre les deux modes d'E/S si un écart entre les clés est détecté. Cependant, il serait préférable qu'il existe une classe Java standard capable de faire ces deux choses. J'ai vu FileImageOutputStream
, mais je ne suis pas sûr comment cela fonctionne.
Notez que je ne cherche pas d'échantillons de code (bien que cela serait utile pour démontrer des solutions complexes), mais simplement une stratégie générale. Il serait bon de connaître les tailles optimales des tailles de tampon pour les données séquentielles et à quel point (taille de l'écart) vous devez passer d'une stratégie séquentielle à une stratégie d'accès aléatoire.
EDIT:
Pour une réponse soit acceptée, je voudrais une certaine assurance que tous les deux, ne gère solution proposée juste qu'il pourrait. Cela nécessiterait:
- Confirmation que le mode séquentiel est tamponné.
- Confirmation que le mode d'accès aléatoire laisse des trous dans le fichier.
De plus, la solution doit être efficace en mémoire car plusieurs de ces fichiers peuvent être ouverts simultanément.
EDIT 2
Les fichiers peuvent être sur un NAS. Ce n'est pas une question de conception, mais simplement une reconnaissance que dans un environnement d'entreprise, cette architecture est très utilisée et que la solution devrait probablement la gérer (peut-être pas de manière optimale) et ne pas empêcher son utilisation. AFAIK, cela ne devrait pas affecter une solution basée sur write()
et lseek()
, mais pourrait invalider certaines solutions plus ésotériques.
La taille du fichier est-elle fixe? Ou a-t-il besoin de se développer en fonction de la clé? Je voudrais simplement utiliser un 'MappedByteBuffer' pour les opérations d'écriture .. Si le fichier est trop grand ou a besoin de croître, je voudrais envelopper dans une classe qui mappe dans" blocs ", puis déplace le bloc le long que vous écrivez .. L'algorithme pour cela est assez simple .. Il suffit de choisir une taille de bloc qui a du sens pour les données que vous écrivez .. – Nim
La taille du fichier n'est pas connue à l'avance. Le fichier pourrait être sur un lecteur réseau - Je ne suis pas sûr si cela affecte votre solution – rghome
Jetez un oeil à 'java.nio.channels'. Vous pouvez faire un accès aléatoire avec un 'FileChannel', et écrire des données tamponnées. – teppic