Panduan untuk Java OutputStream

1. Ikhtisar

Dalam tutorial ini, kita akan menjelajahi detail tentang kelas Java OutputStream . O utputStream adalah kelas abstrak. Ini berfungsi sebagai superclass untuk semua kelas yang mewakili aliran keluaran byte.

Kami akan memeriksa apa arti kata-kata seperti "keluaran" dan "aliran" ini secara lebih rinci saat kita melanjutkan.

2. Pengantar Singkat Java IO

OutputStream adalah bagian dari Java IO API yang mendefinisikan kelas yang diperlukan untuk melakukan operasi I / O di Java. Ini semua dikemas dalam namespace java.io. Ini adalah salah satu paket inti yang tersedia di Java sejak versi 1.0.

Mulai Java 1.4, kami juga memiliki Java NIO yang dikemas dalam namespace java.nio yang memungkinkan operasi input dan output non-pemblokiran. Area fokus kami untuk artikel ini, bagaimanapun, adalah ObjectStream sebagai bagian dari Java IO.

Detail terkait Java IO dan Java NIO dapat ditemukan di sini.

2.1. Masukan dan keluaran

Java IO pada dasarnya menyediakan mekanisme untuk membaca data dari sumber dan menulis data ke tujuan . Input mewakili sumber sedangkan output mewakili tujuan di sini.

Sumber dan tujuan ini dapat berupa apa saja dari File, Pipa hingga Koneksi Jaringan.

2.2. Aliran

Java IO menyediakan konsep aliran yang pada dasarnya mewakili aliran data yang berkelanjutan . Aliran dapat mendukung berbagai jenis data seperti byte, karakter, objek, dll.

Selain itu, koneksi ke sumber atau tujuan adalah apa yang diwakili oleh aliran. Oleh karena itu, keduanya datang sebagai InputStream atau OutputStream masing-masing.

3. Antarmuka OutputStream

OutputStream mengimplementasikan banyak antarmuka yang menyediakan beberapa karakter berbeda untuk subkelasnya. Mari kita bahas dengan cepat.

3.1. Bisa ditutup

Antarmuka Closeable menyediakan metode yang disebut close () yang menangani penutupan sumber atau tujuan data. Setiap implementasi OutputStream harus menyediakan implementasi metode ini. Di sini mereka dapat melakukan tindakan untuk melepaskan sumber daya.

3.2. AutoCloseable

Antarmuka AutoCloseable juga menyediakan metode yang disebut close () dengan perilaku yang mirip dengan yang ada di Closeable . Namun, dalam kasus ini, metode close () secara otomatis dipanggil saat keluar dari blok coba-dengan-sumber daya.

Rincian lebih lanjut tentang coba-dengan-sumber daya dapat ditemukan di sini.

3.3. Flushable

Antarmuka Flushable menyediakan metode yang disebut flush () yang menangani pembilasan data ke tujuan.

Implementasi tertentu dari OutputStream dapat memilih untuk menyangga byte yang ditulis sebelumnya untuk dioptimalkan, tetapi panggilan ke flush () membuatnya langsung menulis ke tujuan .

4. Metode dalam OutputStream

OutputStream memiliki beberapa metode yang harus diimplementasikan oleh setiap kelas pelaksana untuk tipe datanya masing-masing.

Ini adalah terpisah dari dekat () dan flush () metode yang mewarisi dari dapat ditutup dan Flushable interface.

4.1. tulis (int b)

Kita dapat menggunakan metode ini untuk menulis satu byte tertentu ke OutputStream . Karena argumen "int" terdiri dari empat byte, sebagai par kontrak hanya byte orde rendah pertama yang ditulis dan tiga byte orde tinggi lainnya diabaikan dan diabaikan:

public static void fileOutputStreamByteSingle(String file, String data) throws IOException { byte[] bytes = data.getBytes(); try (OutputStream out = new FileOutputStream(file)) { out.write(bytes[6]); } }

Jika kita memanggil metode ini dengan data sebagai "Hello World!", Yang kita dapatkan sebagai hasil adalah file dengan teks berikut:

W

Ini, seperti yang bisa kita lihat, adalah karakter ketujuh dari string keenam yang diindeks.

4.2. tulis (byte [] b, int off, int length)

Versi metode write () yang kelebihan beban ini ada untuk menulis sub-urutan dari array byte ke OutputStream .

It can write “length” number of bytes from the byte array as specified by the argument starting at an offset determined by “off” to the OutputStream:

public static void fileOutputStreamByteSubSequence( String file, String data) throws IOException { byte[] bytes = data.getBytes(); try (OutputStream out = new FileOutputStream(file)) { out.write(bytes, 6, 5); } }

If we now call this method with the same data as before, we get the following text in our output file:

World

This is the substring of our data starting at index five and comprising five characters.

4.3. write(byte[] b)

This is yet another overloaded version of the write() method which can write an entire byte array as specified by the argument to the OutputStream.

This has the same effect as a call to write(b, 0, b.lengh):

public static void fileOutputStreamByteSequence(String file, String data) throws IOException { byte[] bytes = data.getBytes(); try (OutputStream out = new FileOutputStream(file)) { out.write(bytes); } }

When we call this method now with the same data, we have the entire String in our output file:

Hello World!

5. Direct Subclasses of OutputStream

Now we'll discuss some of the direct known subclasses of OutputStream which individually represent a specific data type of which the OutputStream they define.

They define their own methods apart from implementing those inherited from OutputStream.

We won't go into the details of these subclasses.

5.1. FileOutputStream

As the name suggests, a FileOutputStream is an OutputStream to write data to a File. FileOutputStream, like any other OutputStream, can write a stream of raw bytes.

We have already examined different methods in FileOutputStream as part of the last section.

5.2. ByteArrayOutputStream

ByteArrayOutputStream is an implementation of OutputStream that can write data into a byte array. The buffer keeps growing as ByteArrayOutputStream writes data to it.

We can keep the default initial size of the buffer as 32 bytes or set a specific size using one of the constructors available.

The important thing to note here is that the method close() has practically no effect. The other methods in ByteArrayOutputStream can be safely called even after close() has been called.

5.3. FilterOutputStream

OutputStream primarily writes a byte stream to a destination, but it can as well transform the data before doing so. FilterOutputStream represents superclass of all such classes which perform a specific data transformation. FilterOutputStream is always constructed with an existing OutputStream.

Some of the examples of FilterOutputStream are BufferedOutputStream, CheckedOutputStream, CipherOutputStream, DataOutputStream, DeflaterOutputStream, DigestOutputStream, InflaterOutputStream, PrintStream.

5.4. ObjectOutputStream

ObjectOutputStream can write primitive data types and graphs of Java objects to a destination. We can construct an ObjectOutputStream using an existing OutputStream to write to a specific destination like File.

Please note that it is necessary for objects to implement Serializable for ObjectOutputStream to write them to a destination. You can find more details on Java Serialization here.

5.5. PipedOutputStream

A PipedOutputStream is useful to create a communication pipe. PipedOutputStream can write data which a connected PipedInputStream can read.

PipedOutputStream features a constructor to connect it with a PipedInputStream. Alternatively, we can do this later by using a method provided in PipedOutputStream called connect().

6. OutputStream Buffering

Input and output operations typically involve relatively expensive operations like disk access, network activity, etc. Performing this often can make a program less efficient.

We have “buffered streams” of data in Java to handle these scenarios. BufferedOutputStreamwrites data to a buffer instead which is flushed to the destination less often, when the buffer gets full, or the method flush() is called.

BufferedOutputStream extends FilterOutputStream discussed earlier and wraps an existing OutputStream to write to a destination:

public static void bufferedOutputStream( String file, String ...data) throws IOException { try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file))) { for(String s : data) { out.write(s.getBytes()); out.write(" ".getBytes()); } } }

The critical point to note is that every call to write() for each data argument only writes to the buffer and does not result in a potentially expensive call to the File.

In the case above, if we call this method with data as “Hello”, “World!”, this will only result in data being written to the File when the code exits from the try-with-resources block which calls the method close() on the BufferedOutputStream.

This results in an output file with the following text:

Hello World!

7. Writing Text with OutputStreamWriter

A byte stream, as discussed earlier, represents raw data which may be a bunch of text characters. Now we can get the character array and perform the conversion to the byte array ourselves:

byte[] bytes = data.getBytes();

Java provides convenient classes to bridge this gap. For the case of OutputStream, this class is OutputStreamWriter. OutputStreamWriter wraps an OutputStream and can directly write characters to the desired destination.

We can also optionally provide the OutputStreamWriter with a character set for encoding:

public static void outputStreamWriter(String file, String data) throws IOException { try (OutputStream out = new FileOutputStream(file); Writer writer = new OutputStreamWriter(out,"UTF-8")) { writer.write(data); } }

Sekarang seperti yang bisa kita lihat, kita tidak perlu melakukan transformasi larik karakter menjadi larik byte sebelum menggunakan FileOutputStream. OutputStreamWriter melakukan ini dengan nyaman untuk kita .

Tidak mengherankan bila kita memanggil metode di atas dengan data seperti "Hello World!", Ini menghasilkan file dengan teks sebagai:

Hello World!

8. Kesimpulan

Pada artikel ini, kita membahas kelas abstrak Java OutputStream . Kami pergi melalui antarmuka yang diimplementasikannya dan metode yang disediakannya.

Kemudian kami membahas beberapa sub-kelas OutputStream yang tersedia di Java. Kami akhirnya berbicara tentang buffering dan aliran karakter.

Seperti biasa, kode untuk contoh tersedia di GitHub.