Java.io paketindeki ByteArrayInputStream sınıfı, bir girdi dizisini (baytlardan oluşan) okumak için kullanılabilir.

Bir bayt dizisi giriş akışı oluşturmak için önce java.io.ByteArrayInputStream paketini içe aktarmalıyız . Paketi içe aktardıktan sonra, bir giriş akışı oluşturmak için kullanılabilecek iki oluşturucumuz var:

ByteArrayInputStream input = new ByteArrayInputStream(arr);
ByteArrayInputStream input = new ByteArrayInputStream(arr, 2, 2);

Sınıfın içinde 4 alan vardır:

// Byte array provided by the creator of the stream
protected byte buf[];

// Index of the next character to read from the input stream's buffer
protected int pos;

// Current marked position in the stream
protected int mark = 0;

// Index is one greater than the last valid character in the input stream's buffer
protected int count;

Ve işte yapıcılarımız:

public ByteArrayInputStream(byte buf[]) {
    this.buf = buf;
    this.pos = 0;
    this.count = buf.length;
}

public ByteArrayInputStream(byte buf[], int offset, int length) {
    this.buf = buf;
    this.pos = offset;
    this.count = Math.min(offset + length, buf.length);
    this.mark = offset;
}

ByteArrayInputStream sınıfının yöntemleri

Yöntem Aksiyon
int oku() Bu giriş akışından bir sonraki veri baytını okur.
int okuma(bayt b[], int kapalı, int len) Giriş akışından birkaç bayt okur ve bunları b arabellek dizisinde saklar .
off , hedef diziye göre bir sapmadır b .
len, okunacak maksimum bayt sayısıdır.
uzun atlama (uzun n) Bu giriş akışından n baytlık girişi atlar. Atlanan bayt sayısını döndürür (giriş akışının sonuna ulaşırsak n'den az olabilir).
int mevcut() Bu giriş akışından okunabilen (veya atlanabilen) kalan bayt sayısını döndürür.
geçersiz sıfırlama() Tamponu işaretli konuma sıfırlar. Yapıcıda başka bir konum işaretlenmedikçe veya farklı bir ofset belirtilmedikçe işaretli konum 0'dır.
Boole işaretiDesteklenen() Bu InputStream'in işaretlemeyi/sıfırlamayı destekleyip desteklemediğini kontrol eder. ByteArrayInputStream için true değerini döndürür .
geçersiz kapatma() Hiçbir şey yapmaz.
boşluk işareti(int readAheadLimit) ayarlarişaretgeçerli konuma eşit alan. Sıfırlama yöntemi çağrılırsa, sonraki okuma bu konumdan başlayacaktır. readAheadLimit parametresi kullanılmaz ve yöntemin davranışını etkilemez .

Bu yöntemlere daha yakından bakalım ve pratikte nasıl çalıştıklarını görelim.

Okumak()

Bir ByteArrayInputStream'den tıpkı sıradan bir InputStream'den yaptığınız gibi bayt okumak istediğinizde read() yöntemini kullanabilirsiniz .

public static void main(String[] args) {
   byte[] array = {1, 2, 3, 4};

   try (ByteArrayInputStream input = new ByteArrayInputStream(array)) {
       for (int i = 0; i < array.length; i++) {
           int data = input.read();
           System.out.print(data + ", ");
       }
   } catch (IOException e) {
       e.printStackTrace();
   }
}

mevcut()

Tamponunuzda bir şey olup olmadığını kontrol etmek istiyorsanız, available() yöntemini çağırabilirsiniz .

public static void main(String[] args) {
   byte[] array = {1, 2, 3, 4};

   try (ByteArrayInputStream input = new ByteArrayInputStream(array)) {
       System.out.println("Bytes available for reading: " + input.available());

       input.read();
       System.out.println("Bytes available for reading " + input.available());

       input.read();
       System.out.println("Bytes available for reading " + input.available());
   } catch (IOException e) {
       e.printStackTrace();
   }
}

Tampondan her okumadan sonra okunabilecek bayt sayısının değiştiğini göreceğiz.

Çıktı:

Okunabilir bayt: 4
Okunabilir bayt: 3
Okunabilir bayt: 2

atla(uzun n)

Belirli sayıda baytı atlamak ve okumamak için jump() yöntemini kullanabilirsiniz .

public static void main(String[] args) {
   byte[] array = {1, 2, 3, 4};

   try (ByteArrayInputStream input = new ByteArrayInputStream(array)) {
       input.skip(2);

       while (input.available() != 0) {
           int data = input.read();
           System.out.print(data + ", ");
       }
   } catch (IOException e) {
       e.printStackTrace();
   }
}

Çıktı:

3, 4,

Sıfırla()

Bu yöntem, tamponlanmış akışın konumunu son işaretlenen konuma sıfırlar. Farklı bir işaret ayarlanmadıkça konum 0'dır.

public static void main(String[] args) {
   byte[] buf = {65, 66, 67, 68, 69};
   try (ByteArrayInputStream input = new ByteArrayInputStream(buf)) {
       System.out.println("Read: " + input.read());
       System.out.println("Read: " + input.read());
       System.out.println("Read: " + input.read());
       System.out.println("Read: " + input.read());

       System.out.println("Calling reset() method");
       input.reset();
       System.out.println("Read: " + input.read());
       System.out.println("Read: " + input.read());
   } catch (IOException e) {
       e.printStackTrace();
   }
}

reset() yöntemini çağırmanın bizi akışımızın başlangıç ​​noktasına götürdüğünü göreceğiz .

Çıktı:

Okuma: 65
Okuma: 66
Okuma: 67
Okuma: 68
reset() yöntemini çağırma
Okuma: 65
Okuma: 66

mark(int readAheadLimit)

ByteArrayInputStream sınıfının mark () yöntemi, dahili işareti geçerli bayt konumunda, yani daha önce okunan bayttan hemen sonra ayarlar. Bu yöntem, akış geçersiz hale gelmeden önce işaretlemeden sonra kaç bayt okunabileceğini gösteren bir parametre alır. Varsayılan olarak, işaret açıkça ayarlanmamışsa, bir ByteArrayInputStream 0 konumunu veya yapıcısına iletilen ofsetin konumunu işaretler. ReadAheadLimit işaretinin bu sınıf için alakasız olduğuna dikkat etmek önemlidir .

/* Note: For this class, {@code readAheadLimit}
*  has no meaning.
*
* @since   1.1
*/
public void mark(int readAheadLimit) {
   mark = pos;
}

Burada , mark() ve reset() yöntemleri kullanılarak bir ByteArrayInputStream'de bir işaret belirleme örneği verilmiştir . Önceki örneğe mark() yöntemine bir çağrı ekleyeceğiz :

public static void main(String[] args) {
   byte[] buf = {65, 66, 67, 68, 69};
   try (ByteArrayInputStream input = new ByteArrayInputStream(buf)) {
       System.out.println("Read: " + input.read());
       System.out.println("Read: " + input.read());
       System.out.println("Read: " + input.read());
       input.mark(5);

       System.out.println("Read: " + input.read());
       System.out.println("Read: " + input.read());

       System.out.println("Calling reset() method");
       input.reset();

       System.out.println("Read: " + input.read());
       System.out.println("Read: " + input.read());

   } catch (IOException e) {
       e.printStackTrace();
   }
}

Mevcut akışın konumunun değiştiğini görebiliriz.

Çıktı:

Okuma: 65
Okuma: 66
Okuma: 67
Okuma: 68
Okuma: 69
reset() yöntemini çağırma
Okuma: 68
Okuma: 69

markSupported()

markSupported () yöntemi, bir işaretin ayarlanıp ayarlanamayacağını kontrol etmenizi sağlar. Dönen değerin nereden geldiğini anlamak için yöntemin koduna geçelim:

/**
* Tests if this {@code InputStream} supports mark/reset. The
* {@code markSupported} method of {@code ByteArrayInputStream}
* always returns {@code true}.
*
* @since   1.1
*/
public boolean markSupported() {
   return true;
}

Yöntem her zaman true değerini döndürür . Bunu pratikte test edelim.

public static void main(String[] args) {
   byte[] buf = {65, 66, 67, 68, 69};
   try (ByteArrayInputStream bais = new ByteArrayInputStream(buf)) {
       boolean isMarkSupported = bais.markSupported();

       System.out.println("isMarkSupported: " + isMarkSupported);
       System.out.println("Read: " + bais.read());
       System.out.println("Read: " + bais.read());

       bais.mark(1);
       System.out.println("Read: " + bais.read());
       isMarkSupported = bais.markSupported();
       System.out.println("isMarkSupported: " + isMarkSupported);

       bais.reset();
       isMarkSupported = bais.markSupported();
       System.out.println("isMarkSupported: " + isMarkSupported);
   } catch (IOException e) {
       e.printStackTrace();
   }
}

mark() ve reset() yöntemlerini çalıştırdıktan sonra , akışımız her zaman hazırdır ve işaretleri destekler:

Çıktı:

isMarkSupported: true
Okuma: 65
Okuma: 66
Okuma: 67
isMarkSupported: true
isMarkSupported: true

kapalı()

Kapatma yöntemini anlamak için içine de bir göz atalım:

/**
* Closing a {@code ByteArrayInputStream} 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 {
}

Close yönteminin belgeleri bize bir ByteArrayInputStream'i kapatmanın hiçbir etkisinin olmadığını söyler. ByteArrayInputStream sınıfı yöntemleri , akış kapatıldıktan sonra bir IOException atmadan çağrılabilir .

Ne sonuca varabiliriz?

Bir bayt dizisinden veri okumak istediğimizde bir ByteArrayInputStream'e ihtiyacımız var . Bu sınıfı , kendi başına kullanmak yerine, InputStreams ile nasıl çalışılacağını bilen diğer kodlarla birlikte kullanmak genellikle mantıklıdır .