Java - Tulis ke File

1. Ikhtisar

Dalam tutorial ini, kita akan menjelajahi berbagai cara untuk menulis ke file menggunakan Java. Kami akan menggunakan BufferedWriter , PrintWriter , FileOutputStream , DataOutputStream , RandomAccessFile , FileChannel, dan kelas utilitas Java 7 Files .

Kami juga akan melihat penguncian file saat menulis dan membahas beberapa kesimpulan terakhir tentang menulis ke file.

Tutorial ini adalah bagian dari seri “Kembali ke Dasar” Java di Baeldung.

2. Menulis Dengan BufferedWriter

Mari mulai dengan sederhana dan gunakan BufferedWriter untuk menulis String ke file baru :

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

Output dalam file tersebut adalah:

Hello

Kami kemudian dapat menambahkan String ke file yang ada :

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

File tersebut kemudian akan menjadi:

Hello World

3. Menulis Dengan PrintWriter

Selanjutnya, mari kita lihat bagaimana kita dapat menggunakan PrintWriter untuk menulis teks yang diformat ke file :

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

File yang dihasilkan akan berisi:

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

Perhatikan bagaimana kami tidak hanya menulis String mentah ke sebuah file, tetapi juga beberapa teks yang diformat dengan metode printf .

Kita dapat membuat penulis menggunakan FileWriter , BufferedWriter , atau bahkan System.out .

4. Menulis Dengan FileOutputStream

Sekarang mari kita lihat bagaimana kita dapat menggunakan FileOutputStream untuk menulis data biner ke sebuah file.

Kode berikut mengubah String menjadi byte dan menulis byte ke file menggunakan 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(); }

Output dalam file tersebut tentu saja akan menjadi:

Hello

5. Menulis Dengan DataOutputStream

Selanjutnya, mari kita lihat bagaimana kita dapat menggunakan DataOutputStream untuk menulis String ke file:

@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. Menulis Dengan RandomAccessFile

Sekarang mari kita ilustrasikan cara menulis dan mengedit di dalam file yang sudah ada daripada hanya menulis ke file yang benar-benar baru atau menambahkan ke file yang sudah ada. Sederhananya: Kami membutuhkan akses acak.

RandomAccessFile memungkinkan kita untuk menulis pada posisi tertentu dalam file yang diberi offset - dari awal file - dalam byte.

Kode ini menulis nilai integer dengan offset yang diberikan dari awal file:

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

Jika kita ingin membaca int yang disimpan di lokasi tertentu , kita dapat menggunakan metode ini:

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

Untuk menguji fungsi kita, mari tulis bilangan bulat, edit, dan terakhir baca kembali:

@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. Menulis Dengan FileChannel

Jika kita berurusan dengan file besar, FileChannel bisa lebih cepat daripada IO standar. Kode berikut menulis String ke file menggunakan 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. Menulis Dengan Kelas File

Java 7 memperkenalkan cara baru untuk bekerja dengan sistem berkas, bersama dengan kelas utilitas baru: Files .

Dengan menggunakan kelas Files , kita dapat membuat, memindahkan, menyalin, dan menghapus file dan direktori. Ini juga dapat digunakan untuk membaca dan menulis ke file:

@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. Menulis ke File Sementara

Sekarang mari kita coba menulis ke file sementara. Kode berikut membuat file sementara dan menulis String padanya:

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

Seperti yang bisa kita lihat, hanya pembuatan file sementara yang menarik dan berbeda. Setelah itu, penulisan ke file tersebut sama.

10. Kunci File Sebelum Menulis

Terakhir, saat menulis ke file, terkadang kita perlu memastikan bahwa tidak ada orang lain yang menulis ke file itu pada saat yang bersamaan. Pada dasarnya, kita harus bisa mengunci file itu saat sedang menulis.

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.

Penerapan semua contoh dan cuplikan kode ini dapat ditemukan di GitHub.