Java - Ecrire dans un fichier

1. Vue d'ensemble

Dans ce didacticiel, nous explorerons différentes manières d'écrire dans un fichier à l'aide de Java. Nous utiliserons BufferedWriter , PrintWriter , FileOutputStream , DataOutputStream , RandomAccessFile , FileChannel et la classe utilitaire Java 7 Files .

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

Ce tutoriel fait partie de la série Java «Back to Basics» ici sur Baeldung.

2. Ecrire avec BufferedWriter

Commençons simplement et utilisons BufferedWriter pour écrire une chaîne dans un nouveau fichier :

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

Nous pouvons ensuite ajouter une chaîne au fichier existant :

@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. Écrivez avec PrintWriter

Ensuite, voyons comment nous pouvons utiliser PrintWriter 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 écrivons non seulement une chaîne brute dans un fichier, mais aussi du texte formaté avec la méthode printf .

Nous pouvons créer le graveur en utilisant FileWriter , BufferedWriter ou même System.out .

4. Ecrire avec FileOutputStream

Voyons maintenant comment nous pouvons utiliser FileOutputStream pour écrire des données binaires dans un fichier.

Le code suivant convertit une chaîne en octets et écrit les octets dans un fichier à l'aide de FileOutputStream :

@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. Écrire avec DataOutputStream

Ensuite, voyons comment nous pouvons utiliser DataOutputStream 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. Écrire avec RandomAccessFile

Illustrons maintenant comment écrire et modifier dans 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.

Ce code écrit une valeur entière avec un décalage donné 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 les int stockés à un emplacement spécifique , nous pouvons utiliser cette méthode:

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. Écrire avec FileChannel

Si nous traitons de gros fichiers, FileChannel peut être plus rapide que les E / S standard. Le code suivant écrit String dans un fichier à l'aide de FileChannel :

@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. Classe d' écriture avec des fichiers

Java 7 introduit une nouvelle façon de travailler avec le système de fichiers, ainsi qu'une nouvelle classe utilitaire: Files .

En utilisant la classe Files , nous pouvons créer, déplacer, copier et 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

Essayons maintenant 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(); }

Comme on peut 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, nous devons parfois nous assurer que personne d'autre n'écrit dans ce fichier en même temps. En gros, nous devons pouvoir verrouiller ce fichier lors de l'écriture.

Let's make use of FileChannel to try locking the file before writing to it:

@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(); }

Note that if the file is already locked when we try to acquire the lock, an OverlappingFileLockException will be thrown.

11. Notes

After exploring so many methods of writing to a file, let's discuss some important notes:

  • If we try to read from a file that doesn't exist, a FileNotFoundException will be thrown.
  • If we try to write to a file that doesn't exist, the file will be created first and no exception will be thrown.
  • It is very important to close the stream after using it, as it is not closed implicitly, to release any resources associated with it.
  • In output stream, the close() method calls flush() before releasing the resources, which forces any buffered bytes to be written to the stream.

Looking at the common usage practices, we can see, for example, that PrintWriter is used to write formatted text, FileOutputStream to write binary data, DataOutputStream to write primitive data types, RandomAccessFile to write to a specific position, and FileChannel to write faster in larger files. Some of the APIs of these classes do allow more, but this is a good place to start.

12. Conclusion

This article illustrated the many options of writing data to a file using Java.

L'implémentation de tous ces exemples et extraits de code peut être trouvée sur GitHub.