web-dev-qa-db-fra.com

Insérer du texte dans un fichier existant via Java

Je voudrais créer un programme simple (en Java) qui édite des fichiers texte - en particulier un qui effectue l'insertion de morceaux de texte arbitraires à des positions aléatoires dans un fichier texte. Cette fonctionnalité fait partie d'un programme plus vaste que j'écris actuellement.

En lisant la description de Java.util.RandomAccessFile, il apparaît que toutes les opérations d'écriture effectuées au milieu d'un fichier remplaceraient en fait le contenu existant. C'est un effet secondaire que j'aimerais éviter (si possible).

Existe-t-il un moyen simple d'y parvenir?

Merci d'avance.

24
Dinuk

D'accord, cette question est assez ancienne, mais FileChannels existe depuis Java 1.4 et je ne sais pas pourquoi ils ne sont mentionnés nulle part quand il s'agit de remplacer ou d'insérer du contenu dans des fichiers. - FileChannels sont rapides, utilisez-les.

Voici un exemple (en ignorant les exceptions et d'autres choses):

public void insert(String filename, long offset, byte[] content) {
  RandomAccessFile r = new RandomAccessFile(new File(filename), "rw");
  RandomAccessFile rtemp = new RandomAccessFile(new File(filename + "~"), "rw");
  long fileSize = r.length();
  FileChannel sourceChannel = r.getChannel();
  FileChannel targetChannel = rtemp.getChannel();
  sourceChannel.transferTo(offset, (fileSize - offset), targetChannel);
  sourceChannel.truncate(offset);
  r.seek(offset);
  r.write(content);
  long newOffset = r.getFilePointer();
  targetChannel.position(0L);
  sourceChannel.transferFrom(targetChannel, newOffset, (fileSize - offset));
  sourceChannel.close();
  targetChannel.close();
}
16
xor_eq

Eh bien, non, je ne pense pas qu'il existe un moyen d'éviter d'écraser le contenu existant avec un seul appel standard Java IO API).

Si les fichiers ne sont pas trop volumineux, lisez tout le fichier dans une liste de tableaux (une entrée par ligne) et réécrivez les entrées ou insérez de nouvelles entrées pour les nouvelles lignes.

Remplacez ensuite le fichier existant par un nouveau contenu ou déplacez le fichier existant vers une sauvegarde et écrivez un nouveau fichier.

Selon le degré de sophistication des modifications, votre structure de données peut devoir changer.

Une autre méthode consisterait à lire les caractères du fichier existant lors de l'écriture dans le fichier modifié et à modifier le flux au fur et à mesure de sa lecture.

11
Ken Gentle

Si Java a un moyen de mapper les fichiers en mémoire, alors ce que vous pouvez faire est d'étendre le fichier à sa nouvelle longueur, de mapper le fichier, de déplacer tous les octets jusqu'à la fin pour faire un trou et écrire les nouvelles données dans le trou.

Cela fonctionne en C. Jamais essayé en Java.

Une autre façon, je viens de penser à faire de même, mais avec un accès aléatoire aux fichiers.

  • Chercher jusqu'au bout - 1 Mo
  • Lire 1 Mo
  • Écrivez cela à la position d'origine + la taille de l'écart.
  • Répétez l'opération pour chaque 1 Mo précédent en travaillant vers le début du fichier.
  • Arrêtez-vous lorsque vous atteignez la position d'écart souhaitée.

Utilisez une taille de tampon plus grande pour des performances plus rapides.

4
Zan Lynx

Vous pouvez utiliser le code suivant:

BufferedReader reader = null;
BufferedWriter writer = null;
ArrayList list = new ArrayList();

try {
    reader = new BufferedReader(new FileReader(fileName));
    String tmp;
    while ((tmp = reader.readLine()) != null)
        list.add(tmp);
    OUtil.closeReader(reader);

    list.add(0, "Start Text");
    list.add("End Text");

    writer = new BufferedWriter(new FileWriter(fileName));
    for (int i = 0; i < list.size(); i++)
        writer.write(list.get(i) + "\r\n");
} catch (Exception e) {
    e.printStackTrace();
} finally {
    OUtil.closeReader(reader);
    OUtil.closeWriter(writer);
}
4
S.Yavari

Je crois que la seule façon d'insérer du texte dans un fichier texte existant est de lire le fichier d'origine et d'écrire le contenu dans un fichier temporaire avec le nouveau texte inséré. Effacez ensuite le fichier d'origine et renommez le fichier temporaire en son nom d'origine.

Cette exemple se concentre sur l'insertion d'une seule ligne dans un fichier existant, mais peut-être encore utile pour vous.

2
Brendan Cashman

Je ne sais pas s'il y a un moyen pratique de le faire autrement que

  • lire le début du fichier et l'écrire sur la cible
  • écrivez votre nouveau texte à cibler
  • lire le reste du fichier et l'écrire sur la cible.

À propos de la cible: vous pouvez créer le nouveau contenu du fichier en mémoire, puis écraser l'ancien contenu du fichier si les fichiers traités ne sont pas si volumineux. Ou vous pouvez écrire le résultat dans un fichier temporaire.

La chose serait probablement plus facile à faire avec les flux, RandomAccessFile ne semble pas être destiné à être inséré au milieu (afaik). Vérifiez le tutoriel si vous en avez besoin.

2
Touko

S'il s'agit d'un fichier texte , Lisez le fichier existant dans StringBuffer et ajoutez le nouveau contenu dans le même StringBuffer maintenant vous pouvez écrire le SrtingBuffer sur le fichier. maintenant le fichier contient à la fois le texte existant et le nouveau.

0
saravana kumar