Java - Scrieți în fișier

1. Prezentare generală

În acest tutorial, vom explora diferite moduri de a scrie într-un fișier folosind Java. Vom folosi BufferedWriter , PrintWriter , FileOutputStream , DataOutputStream , RandomAccessFile , FileChannel și clasa utilitară Java 7 Files .

De asemenea, ne vom uita la blocarea fișierului în timp ce scriem și vom discuta despre câteva plăți finale despre scrierea în fișier.

Acest tutorial face parte din seria Java „Înapoi la elementele de bază” aici de pe Baeldung.

2. Scrieți cu BufferedWriter

Să începem simplu și să folosim BufferedWriter pentru a scrie un șir într-un fișier nou :

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

Ieșirea din fișier va fi:

Hello

Apoi putem adăuga un șir la fișierul existent :

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

Fișierul va fi apoi:

Hello World

3. Scrieți cu PrintWriter

În continuare, să vedem cum putem folosi PrintWriter pentru a scrie text formatat într-un fișier :

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

Fișierul rezultat va conține:

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

Rețineți că nu numai că scriem un șir brut într-un fișier, ci și un text formatat cu metoda printf .

Putem crea scriitorul folosind FileWriter , BufferedWriter sau chiar System.out .

4. Scrieți cu FileOutputStream

Să vedem acum cum putem folosi FileOutputStream pentru a scrie date binare într-un fișier.

Următorul cod convertește un șir în octeți și scrie octeții într-un fișier folosind 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(); }

Ieșirea din fișier va fi desigur:

Hello

5. Scrieți cu DataOutputStream

În continuare, să aruncăm o privire la modul în care putem folosi DataOutputStream pentru a scrie un șir într-un fișier:

@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. Scrieți cu RandomAccessFile

Să ilustrăm acum cum să scrieți și să editați într-un fișier existent, mai degrabă decât să scrieți într-un fișier complet nou sau să îl atașați la unul existent. Simplu spus: avem nevoie de acces aleatoriu.

RandomAccessFile ne permite să scriem la o anumită poziție în fișierul dat de offset - de la începutul fișierului - în octeți.

Acest cod scrie o valoare întreagă cu offset dat de la începutul fișierului:

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

Dacă dorim să citim int stocate la o anumită locație , putem folosi această metodă:

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; }

Pentru a testa funcțiile noastre, să scriem un număr întreg, să-l edităm și să-l citim în cele din urmă:

@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. Scrieți cu FileChannel

Dacă avem de-a face cu fișiere mari, FileChannel poate fi mai rapid decât IO standard. Următorul cod scrie String într-un fișier folosind 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. Clasa Scrieți cu fișiere

Java 7 introduce un nou mod de lucru cu sistemul de fișiere, împreună cu o nouă clasă de utilități: Fișiere .

Folosind clasa Fișiere , putem crea, muta, copia și șterge fișiere și directoare. Poate fi folosit și pentru citirea și scrierea într-un fișier:

@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. Scrieți într-un fișier temporar

Acum să încercăm să scriem într-un fișier temporar. Următorul cod creează un fișier temporar și îi scrie un șir :

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

După cum putem vedea, este doar crearea fișierului temporar care este interesant și diferit. După acel moment, scrierea în fișier este aceeași.

10. Blocați fișierul înainte de a scrie

În cele din urmă, atunci când scriem într-un fișier, uneori trebuie să ne asigurăm că nimeni altcineva nu scrie în acel fișier în același timp. Practic, trebuie să putem bloca acel fișier în timp ce scriem.

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.

Implementarea tuturor acestor exemple și fragmente de cod poate fi găsită pe GitHub.