Java - Écrire dans un fichier

Java - Écrire dans un fichier

1. Vue d'ensemble

Dans ce didacticiel, nous allons explorer différentes manières dewrite to a file using Java. Nous utiliseronsBufferedWriter,PrintWriter,FileOutputStream,DataOutputStream,RandomAccessFile,FileChannel et les Java 7Files classe d'utilité.

Nous examinerons également le verrouillage du fichier lors de l'écriture et discuterons de quelques conseils finaux sur l'écriture dans un fichier.

Cet article fait partie dethe “Java – Back to Basic” series ici par exemple.

Lectures complémentaires:

Java - Ajouter des données à un fichier

Un guide rapide et pratique pour ajouter des données aux fichiers.

Read more

FileNotFoundException en Java

Un guide rapide et pratique sur FileNotFoundException en Java.

Read more

Comment copier un fichier avec Java

Jetez un coup d'œil aux méthodes courantes de copie de fichiers en Java.

Read more

2. Ecrire avecBufferedWriter

Commençons simplement - et utilisonsBufferedWriter pour écrire unStringto a new file:

public void whenWriteStringUsingBufferedWritter_thenCorrect()
  throws IOException {
    String str = "Hello";
    BufferedWriter writer = new BufferedWriter(new FileWriter(fileName));
    writer.write(str);

    writer.close();
}

La sortie dans le fichier sera:

Hello

On peut alorsappend a String to the existing file:

@Test
public void whenAppendStringUsingBufferedWritter_thenOldContentShouldExistToo()
  throws IOException {
    String str = "World";
    BufferedWriter writer = new BufferedWriter(new FileWriter(fileName, true));
    writer.append(' ');
    writer.append(str);

    writer.close();
}

Le fichier sera alors:

Hello World

3. Ecrire avecPrintWriter

Ensuite, voyons comment nous pouvons utiliser unPrintWriter pour écrire du texte formaté dans un fichier:

@Test
public void givenWritingStringToFile_whenUsingPrintWriter_thenCorrect()
  throws IOException {
    FileWriter fileWriter = new FileWriter(fileName);
    PrintWriter printWriter = new PrintWriter(fileWriter);
    printWriter.print("Some String");
    printWriter.printf("Product name is %s and its price is %d $", "iPhone", 1000);
    printWriter.close();
}

Le fichier résultant contiendra:

Some String
Product name is iPhone and its price is 1000$

Notez que nous n'écrivons pas seulement une chaîne brute dans un fichier, mais également du texte formaté avec la méthodeprintf.

Nous pouvons créer le graveur en utilisantFileWriter,BufferedWriter ou mêmeSystem.out.

4. Ecrire avecFileOutputStream

Voyons maintenant comment nous pouvons utiliserFileOutputStream enwrite binary data to a file. Le code suivant convertit unString int octets et écrit les octets dans le fichier à l'aide d'unFileOutputStream:

@Test
public void givenWritingStringToFile_whenUsingFileOutputStream_thenCorrect()
  throws IOException {
    String str = "Hello";
    FileOutputStream outputStream = new FileOutputStream(fileName);
    byte[] strToBytes = str.getBytes();
    outputStream.write(strToBytes);

    outputStream.close();
}

La sortie dans le fichier sera bien sûr:

Hello

5. Ecrire avecDataOutputStream

Ensuite, voyons comment nous pouvons utiliser unDataOutputStream pour écrire une chaîne dans un fichier:

@Test
public void givenWritingToFile_whenUsingDataOutputStream_thenCorrect()
  throws IOException {
    String value = "Hello";
    FileOutputStream fos = new FileOutputStream(fileName);
    DataOutputStream outStream = new DataOutputStream(new BufferedOutputStream(fos));
    outStream.writeUTF(value);
    outStream.close();

    // verify the results
    String result;
    FileInputStream fis = new FileInputStream(fileName);
    DataInputStream reader = new DataInputStream(fis);
    result = reader.readUTF();
    reader.close();

    assertEquals(value, result);
}

6. Ecrire avecRandomAccessFile

Voyons maintenant comment écrire et modifier à l'intérieur d'un fichier existant - plutôt que de simplement écrire dans un fichier complètement nouveau ou de l'ajouter à un fichier existant. En termes simples, nous avons besoin d’un accès aléatoire.

RandomAccessFile nous permet d'écrire à une position spécifique dans le fichier étant donné le décalage - depuis le début du fichier - en octets. Le code suivant écrit une valeur entière avec offset donnée depuis le début du fichier:

private void writeToPosition(String filename, int data, long position)
  throws IOException {
    RandomAccessFile writer = new RandomAccessFile(filename, "rw");
    writer.seek(position);
    writer.writeInt(data);
    writer.close();
}

Si nous voulons lire le int stocké à un emplacement spécifique, nous pouvons utiliser la méthode suivante:

private int readFromPosition(String filename, long position)
  throws IOException {
    int result = 0;
    RandomAccessFile reader = new RandomAccessFile(filename, "r");
    reader.seek(position);
    result = reader.readInt();
    reader.close();
    return result;
}

Pour tester nos fonctions, écrivons un entier - éditons-le - et, enfin, relisons-le:

@Test
public void whenWritingToSpecificPositionInFile_thenCorrect()
  throws IOException {
    int data1 = 2014;
    int data2 = 1500;

    writeToPosition(fileName, data1, 4);
    assertEquals(data1, readFromPosition(fileName, 4));

    writeToPosition(fileName2, data2, 4);
    assertEquals(data2, readFromPosition(fileName, 4));
}

7. Ecrire avecFileChannel

Si vous avez affaire à des fichiers volumineux,FileChannel peut être plus rapide que les E / S standard. Le code suivant écritString dans un fichier à l'aide deFileChannel:

@Test
public void givenWritingToFile_whenUsingFileChannel_thenCorrect()
  throws IOException {
    RandomAccessFile stream = new RandomAccessFile(fileName, "rw");
    FileChannel channel = stream.getChannel();
    String value = "Hello";
    byte[] strBytes = value.getBytes();
    ByteBuffer buffer = ByteBuffer.allocate(strBytes.length);
    buffer.put(strBytes);
    buffer.flip();
    channel.write(buffer);
    stream.close();
    channel.close();

    // verify
    RandomAccessFile reader = new RandomAccessFile(fileName, "r");
    assertEquals(value, reader.readLine());
    reader.close();
}

8. Écrire avec la classeFiles

Java 7 introduit une nouvelle façon de travailler avec le système de fichiers, ainsi qu'une nouvelle classe d'utilitaires -Files. En utilisant la classeFiles, nous pouvons également créer, déplacer, copier, supprimer des fichiers et des répertoires; il peut également être utilisé pour lire et écrire dans un fichier:

@Test
public void givenUsingJava7_whenWritingToFile_thenCorrect()
  throws IOException {
    String str = "Hello";

    Path path = Paths.get(fileName);
    byte[] strToBytes = str.getBytes();

    Files.write(path, strToBytes);

    String read = Files.readAllLines(path).get(0);
    assertEquals(str, read);
}

9. Écrire dans un fichier temporaire

Maintenant, essayons d'écrire dans un fichier temporaire. Le code suivant crée un fichier temporaire et y écrit une chaîne:

@Test
public void whenWriteToTmpFile_thenCorrect() throws IOException {
    String toWrite = "Hello";
    File tmpFile = File.createTempFile("test", ".tmp");
    FileWriter writer = new FileWriter(tmpFile);
    writer.write(toWrite);
    writer.close();

    BufferedReader reader = new BufferedReader(new FileReader(tmpFile));
    assertEquals(toWrite, reader.readLine());
    reader.close();
}

Donc, comme vous pouvez le voir - c'est juste la création du fichier temporaire qui est intéressante et différente - après ce point, l'écriture dans le fichier est la même.

10. Verrouiller le fichier avant d'écrire

Enfin, lors de l'écriture dans un fichier, vous devez parfois vous assurer que personne d'autre n'écrit dans ce fichier en même temps. Fondamentalement, vous devez pouvoir verrouiller ce fichier lors de l'écriture.

Utilisons lesFileChannel pour essayer de verrouiller le fichier avant d’y écrire:

@Test
public void whenTryToLockFile_thenItShouldBeLocked()
  throws IOException {
    RandomAccessFile stream = new RandomAccessFile(fileName, "rw");
    FileChannel channel = stream.getChannel();

    FileLock lock = null;
    try {
        lock = channel.tryLock();
    } catch (final OverlappingFileLockException e) {
        stream.close();
        channel.close();
    }
    stream.writeChars("test lock");
    lock.release();

    stream.close();
    channel.close();
}

Notez que si le fichier est déjà verrouillé lorsque nous essayons d'acquérir le verrou, unOverlappingFileLockException sera levé.

11. Remarques

Après avoir exploré tant de méthodes d'écriture dans un fichier, discutons de quelques remarques importantes:

  • Si nous essayons de lire à partir d'un fichier qui n'existe pas, unFileNotFoundException sera renvoyé

  • Si nous essayons d'écrire dans un fichier qui n'existe pas, le fichier sera créé en premier et aucune exception ne sera levée

  • Il est très important de fermer le flux après l'avoir utilisé, car il n'est pas fermé implicitement, pour libérer les ressources qui lui sont associées.

  • Dans le flux de sortie, la méthodeclose() appelleflush() avant de libérer les ressources, ce qui force l'écriture des octets mis en mémoire tampon dans le flux

En regardant les pratiques d'utilisation courantes, nous pouvons voir - par exemple - quePrintWriter est utilisé pour écrire du texte formaté; FileOutputStream pour écrire des données binaires; DataOutputStream pour écrire des types de données primitifs; RandomAccessFile pour écrire à une position spécifique; FileChannel pour écrire plus rapidement dans des fichiers plus volumineux. Certaines des API de ces classes en autorisent davantage, mais c'est un bon point de départ.

12. Conclusion

Cet article illustre les nombreuses options d’écriture de données dans un fichier à l’aide de Java.

L'implémentation de tous ces exemples et extraits de codecan be found over on GitHub project - il s'agit d'un projet basé sur Maven, il devrait donc être facile à importer et à exécuter tel quel.