Kelas ByteArrayOutputStream ngetrapake aliran output sing nulis data menyang array byte. Buffer tuwuh kanthi otomatis nalika data ditulis.

Kelas ByteArrayOutputStream nggawe buffer ing memori, lan kabeh data sing dikirim menyang stream disimpen ing buffer.

ByteArrayOutputStream konstruktor

Kelas ByteArrayOutputStream nduweni konstruktor ing ngisor iki :

Konstruktor
ByteArrayOutputStream() Konstruktor iki nggawe buffer ing memori sing dawane 32 bita.
ByteArrayOutputStream(int a) Konstruktor iki nggawe buffer ing memori kanthi ukuran tartamtu.

Lan iki katon ing kelas kasebut:


// The buffer itself, where the data is stored.
protected byte buf[];

// Current number of bytes written to the buffer.
protected int count;

public ByteArrayOutputStream() {
    this(32);
}

public ByteArrayOutputStream(int size) {
    if (size < 0) {
        throw new IllegalArgumentException("Negative initial size: "
                                           + size);
    }
    buf = new byte[size];
}
    

Metode saka kelas ByteArrayOutputStream

Ayo kita ngomong babagan cara sing bisa digunakake ing kelas.

Ayo dadi nyoba kanggo nyelehake soko ing stream kita. Kanggo nindakake iki, kita bakal nggunakake cara nulis () - bisa nampa siji bait utawa set bait kanggo nulis.

Metode
void nulis (int b) Nulis siji bait.
void write(byte b[], int off, int len) Nulis array saka bita saka ukuran tartamtu.
void writeBytes(byte b[]) Nulis array saka bita.
void writeTo(OutputStream out) Nulis kabeh data saka stream output saiki kanggo stream output liwati.

Implementasi metode:


public static void main(String[] args) throws IOException {
   ByteArrayOutputStream outputByte = new ByteArrayOutputStream();
   // Write one byte
   while(outputByte.size()!= 7) {
      outputByte.write("codegym".getBytes());
   }

   // Write array of bytes
   String value = "\nWelcome to Java\n";
   byte[] arrBytes = value.getBytes();
   outputByte.write(arrBytes);

   // Write part of an array
   String codeGym = "CodeGym";
   byte[] b = codeGym.getBytes();
   outputByte.write(b, 4, 3);

   // Write to a file
   FileOutputStream fileOutputStream = new FileOutputStream("output.txt");
   outputByte.write(80);
   outputByte.writeTo(fileOutputStream);
}
    

Asil punika file output.txt anyar sing katon kaya iki:

Cara toByteArray () ngasilake isi saiki stream output iki minangka Uploaded byte. Lan sampeyan bisa nggunakake cara toString () kanggo njaluk buf byte array minangka teks:


public static void main(String[] args) throws IOException {
    ByteArrayOutputStream outputByte = new ByteArrayOutputStream();

    String value = "CodeGym";
    outputByte.write(value.getBytes());

    byte[] result = outputByte.toByteArray();
    System.out.println("Result: ");

    for(int i = 0 ; i < result.length; i++) {
        // Display the characters
        System.out.print((char)result[i]);
    }
}
    

Buffer kita ngemot array byte sing diwenehake.

Cara reset () ngreset jumlah bait sing bener ing stream output array byte menyang nol (supaya kabeh sing dikumpulake ing output direset).


public static void main(String[] args) throws IOException {
   ByteArrayOutputStream outputByte = new ByteArrayOutputStream(120);

   String value = "CodeGym";
   outputByte.write(value.getBytes());
   byte[] result = outputByte.toByteArray();
   System.out.println("Output before reset: ");

   for (byte b : result) {
      // Display the characters
      System.out.print((char) b);
   }

   outputByte.reset();

   byte[] resultAfterReset = outputByte.toByteArray();
   System.out.println("\nOutput after reset: ");

   for (byte b : resultAfterReset) {
      // Display the characters
      System.out.print((char) b);
   }
}
    

Nalika kita nampilake buffer sawise nelpon cara reset () , kita njaluk apa-apa.

Fitur khusus saka metode close ().

Cara iki kudu diwenehi perhatian khusus. Kanggo mangerteni apa sing ditindakake, ayo ndelok ing jero:


/**
 * Closing a {@code ByteArrayOutputStream} has no effect. The methods in
 * this class can be called after the stream has been closed without
 * generating an {@code IOException}.
 */
public void close() throws IOException {
}
    

Elinga yen metode close () kelas ByteArrayOutputStream ora nindakake apa-apa.

Kok ngono? A ByteArrayOutputStream minangka aliran basis memori (yaiku, dikelola lan diisi dening pangguna ing kode), saengga nelpon cedhak () ora ana pengaruhe.

Laku

Saiki ayo nyoba ngleksanakake sistem file nggunakake ByteArrayOutputStream lan ByteArrayInputStream .

Ayo nulis kelas FileSystem nggunakake pola desain singleton lan nggunakake HashMap statis<String, byte[]> , ngendi:

  • String minangka path menyang file
  • byte [] yaiku data ing file sing disimpen

import java.io.*;
import java.util.HashMap;
import java.util.Map;

class FileSystem {
   private static final FileSystem fileSystem = new FileSystem();
   private static final Map<String, byte[]> files = new HashMap<>();

   private FileSystem() {
   }

   public static FileSystem getFileSystem() {
       return fileSystem;
   }

   public void create(String path) {
       validateNotExists(path);
       files.put(path, new byte[0]);
   }

   public void delete(String path) {
       validateExists(path);
       files.remove(path);
   }

   public boolean isExists(String path) {
       return files.containsKey(path);
   }

   public InputStream newInputStream(String path) {
       validateExists(path);
       return new ByteArrayInputStream(files.get(path));
   }

   public OutputStream newOutputStream(String path) {
       validateExists(path);
       return new ByteArrayOutputStream() {
           @Override
           public void flush() throws IOException {
               final byte[] bytes = toByteArray();
               files.put(path, bytes);
               super.flush();
           }

           @Override
           public void close() throws IOException {
               final byte[] bytes = toByteArray();
               files.put(path, bytes);
               super.close();
           }
       };
   }

   private void validateExists(String path) {
       if (!files.containsKey(path)) {
           throw new RuntimeException("File not found");
       }
   }

   private void validateNotExists(String path) {
       if (files.containsKey(path)) {
           throw new RuntimeException("File exists");
       }
   }
}
    

Ing kelas iki, kita nggawe metode umum ing ngisor iki:

  • metode CRUD standar (gawe, maca, nganyari, mbusak),
  • cara kanggo mriksa yen file ana,
  • cara kanggo njaluk Kayata saka sistem file.

Kanggo maca saka file, kita ngasilake InputStream . Ing hood punika implementasine ByteArrayInputStream . Buffer minangka array byte sing disimpen ing peta file .

Cara liyane sing menarik yaiku newOutputStream . Nalika cara iki disebut, kita bali obyek ByteArrayOutputStream anyar sing overrides rong cara: flush lan nutup . Nelpon salah siji saka cara iki kudu nimbulaké nulis kanggo njupuk Panggonan.

Lan persis apa sing kita lakoni: kita entuk array byte sing wis ditulis pangguna, lan nyimpen salinan minangkanilaiing peta file kanthi kunci sing cocog.

Kita nggunakake kode ing ngisor iki kanggo nyoba sistem file (FS):


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import static java.nio.charset.StandardCharsets.UTF_8;

public class MyFileSystemTest {
   public static void main(String[] args) throws IOException {
       FileSystem fileSystem = FileSystem.getFileSystem();
       final String path = "/user/bin/data.txt";

       // Create a file
       fileSystem.create(path);
       System.out.println("File created successfully");

       // Make sure it's empty
       try (InputStream inputStream = fileSystem.newInputStream(path)) {
           System.out.print("File contents:\t");
           System.out.println(read(inputStream));
       }

       // Write data to it
       try (final OutputStream outputStream = fileSystem.newOutputStream(path)) {
           outputStream.write("CodeGym".getBytes(UTF_8));
           System.out.println("Data written to file");
       }

       // Read data
       try (InputStream inputStream = fileSystem.newInputStream(path)) {
           System.out.print("File contents:\t");
           System.out.println(read(inputStream));
       }

       // Delete the file
       fileSystem.delete(path);

       // Verify that the file does not exist in the FS
       System.out.print("File exists:\t");
       System.out.println(fileSystem.isExists(path));

   }

   private static String read(InputStream inputStream) throws IOException {
       return new String(inputStream.readAllBytes(), UTF_8);
   }
}
    

Sajrone tes, kita verifikasi tumindak ing ngisor iki:

  1. Kita nggawe file anyar.
  2. Kita priksa manawa file sing digawe kosong.
  3. Kita nulis sawetara data menyang file.
  4. Kita maca maneh data lan verifikasi manawa cocog karo sing ditulis.
  5. Kita mbusak file kasebut.
  6. Kita verifikasi manawa file kasebut wis dibusak.

Mlaku kode iki menehi output iki:

File digawe kasil
Isi file:
Data ditulis kanggo file
Isi file: CodeGym
File ana: palsu

Yagene conto iki perlu?

Cukup, data tansah sakumpulan bita. Yen sampeyan kudu maca / nulis akeh data saka / menyang disk, kode bakal mlaku alon amarga masalah I / O. Ing kasus iki, iku ndadekake pangertèn kanggo njaga sistem file virtual ing RAM, bisa karo ing cara sing padha karo disk tradisional. Lan apa sing luwih gampang tinimbang InputStream lan OutputStream ?

Mesthi, iki minangka conto kanggo instruksi, dudu kode sing siap produksi. Ora ana akun (dhaptar ing ngisor iki ora lengkap):

  • multithreading
  • watesan ukuran file (jumlah RAM sing kasedhiya kanggo JVM sing mlaku)
  • verifikasi saka struktur path
  • verifikasi argumen metode

Informasi njero sing menarik:
Server verifikasi tugas CodeGym nggunakake pendekatan sing padha. Kita muter FS virtual, nemtokake tes sing kudu ditindakake kanggo verifikasi tugas, nglakokake tes, lan maca asile.

Kesimpulan lan pitakonan gedhe

Pitakonan gedhe sawise maca pawulangan iki yaiku "Yagene aku ora bisa nggunakake byte [] , amarga luwih trep lan ora ngetrapake watesan?"

Kauntungan saka ByteArrayInputStream iku kuwat nuduhake yen sampeyan bakal nggunakake bait mung diwaca (amarga stream ora menehi antarmuka kanggo ngganti isi). Yen ngandika, iku penting kanggo Wigati sing programmer isih bisa ngakses bita langsung.

Nanging yen kadhangkala sampeyan duwe byte [] , kadhangkala sampeyan duwe file, kadhangkala sampeyan duwe sambungan jaringan, lan liya-liyane, sampeyan bakal mbutuhake sawetara jenis abstraksi kanggo "stream of byte, lan aku ora peduli ngendi padha teka saka". Lan kuwi InputStream . Nalika sumber dadi array byte, ByteArrayInputStream minangka InputStream sing apik kanggo digunakake.

Iki migunani ing pirang-pirang kahanan, nanging ana rong conto khusus:

  1. Sampeyan lagi nulis perpustakaan sing nampa bita lan ngolah mau piye wae (contone, umpamane perpustakaan utilitas pangolahan gambar). Pangguna perpustakaan sampeyan bisa nyedhiyakake bait saka file, saka bait ing memori [] , utawa saka sawetara sumber liyane. Supaya sampeyan nyedhiyani antarmuka sing nampa InputStream , kang tegese yen padha duwe byte[] , padha kudu mbungkus ing ByteArrayInputStream .

  2. Sampeyan lagi nulis kode sing maca sambungan jaringan. Nanging kanggo nindakake tes unit ing kode iki, sampeyan ora pengin mbukak sambungan - sampeyan mung pengin feed sawetara bita menyang kode. Dadi kode njupuk InputStream lan tes sampeyan lulus ing ByteArrayInputStream .