สามารถใช้คลาส ByteArrayInputStream ใน แพ็คเกจ java.ioเพื่ออ่านอินพุตอาร์เรย์ (จำนวนไบต์)

ในการสร้างสตรีมอินพุตอาร์เรย์แบบไบต์ เราต้องนำเข้าแพ็คเกจjava.io.ByteArrayInputStream ก่อน หลังจากที่เรานำเข้าแพ็คเกจแล้ว เรามีตัวสร้างสองตัวสำหรับสร้างสตรีมอินพุต:


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

มี 4 ฟิลด์ภายในชั้นเรียน:


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

และนี่คือตัวสร้างของเรา:


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

วิธี การกระทำ
int อ่าน () อ่านข้อมูลไบต์ถัดไปจากสตรีมอินพุตนี้
int อ่าน (ไบต์ b [], int ปิด, int len) อ่านหลายไบต์จากสตรีมอินพุตและเก็บไว้ในอาร์เรย์บัฟเฟอร์b
offคือค่าชดเชยในอาร์เรย์เป้าหมายb
lenคือจำนวนไบต์สูงสุดที่จะอ่านได้
ข้ามยาว(ยาว n) ข้ามอินพุต n ไบต์จากสตรีมอินพุตนี้ ส่งกลับจำนวนไบต์ที่ข้ามไป (อาจน้อยกว่า n หากเราไปถึงจุดสิ้นสุดของสตรีมอินพุต)
int ใช้ได้ () ส่งกลับจำนวนไบต์ที่เหลือที่สามารถอ่าน (หรือข้าม) จากอินพุตสตรีมนี้
เป็นโมฆะรีเซ็ต () รีเซ็ตบัฟเฟอร์ไปยังตำแหน่งที่ทำเครื่องหมายไว้ ตำแหน่งที่ทำเครื่องหมายเป็น 0 เว้นแต่จะมีการทำเครื่องหมายตำแหน่งอื่นหรือระบุออฟเซ็ตอื่นในตัวสร้าง
เครื่องหมายบูลีนรองรับ () ตรวจสอบว่าInputStream นี้ รองรับการทำเครื่องหมาย/การรีเซ็ตหรือไม่ คืนค่าจริงสำหรับByteArrayInputStream
เป็นโมฆะปิด () ไม่ทำอะไรเลย
เครื่องหมายเป็นโมฆะ (int readAheadLimit) ตั้งค่าเครื่องหมายเขตเท่ากับตำแหน่งปัจจุบัน หาก มีการเรียกใช้วิธี การรีเซ็ตการอ่านครั้งต่อไปจะเริ่มจากตำแหน่งนั้น ไม่ได้ใช้ พารามิเตอร์readAheadLimitและไม่ส่งผลต่อลักษณะการทำงานของเมธอด

ลองมาดูวิธีการเหล่านี้ให้ละเอียดยิ่งขึ้นและดูว่าพวกเขาทำงานอย่างไร

อ่าน()

เมื่อคุณต้องการอ่านไบต์จากByteArrayInputStreamเช่นเดียวกับที่คุณอ่านจากInputStream ทั่วไป คุณสามารถใช้เมธอดread()


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

มีอยู่()

หากคุณต้องการตรวจสอบว่ามีบางอย่างอยู่ในบัฟเฟอร์ของคุณหรือไม่ คุณสามารถเรียกใช้เมธอดavailable()


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

เราจะเห็นว่าจำนวนไบต์ที่สามารถอ่านได้เปลี่ยนแปลงไปหลังจากอ่านแต่ละครั้งจากบัฟเฟอร์

เอาท์พุต:

ไบต์สำหรับการอ่าน: 4
ไบต์สำหรับการอ่าน: 3
ไบต์สำหรับการอ่าน: 2

ข้าม (ยาว n)

คุณสามารถใช้ เมธอด การข้าม ()เพื่อข้ามจำนวนไบต์ที่กำหนดและไม่อ่าน


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

เอาท์พุต:

3, 4,

รีเซ็ต ()

วิธีนี้จะรีเซ็ตตำแหน่งของสตรีมที่บัฟเฟอร์เป็นตำแหน่งที่ทำเครื่องหมายไว้ล่าสุด เป็นตำแหน่ง 0 เว้นแต่จะกำหนดเครื่องหมายอื่นไว้


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()จะนำเราไปยังจุดเริ่มต้นของสตรีมของเรา

เอาท์พุต:

อ่าน: 65
อ่าน: 66
อ่าน: 67
อ่าน: 68
วิธีรีเซ็ตการโทร ()
อ่าน: 65
อ่าน: 66

ทำเครื่องหมาย (int readAheadLimit)

วิธีการทำ เครื่องหมาย()ของ คลาส ByteArrayInputStreamตั้งค่าเครื่องหมายภายในที่ตำแหน่งไบต์ปัจจุบัน นั่นคือ ทันทีหลังจากไบต์ที่อ่านก่อนหน้านี้ เมธอดนี้ใช้พารามิเตอร์ที่ระบุจำนวนไบต์ที่สามารถอ่านได้หลังจากทำเครื่องหมายก่อนที่สตรีมจะไม่ถูกต้อง ตามค่าเริ่มต้น หากไม่ได้ตั้งค่าเครื่องหมายอย่างชัดเจนByteArrayInputStreamจะทำเครื่องหมายตำแหน่ง 0 หรือตำแหน่งของออฟเซ็ตที่ส่งผ่านไปยังตัวสร้าง โปรดทราบว่า เครื่องหมาย readAheadLimitไม่เกี่ยวข้องกับคลาสนี้


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

นี่คือตัวอย่างการตั้งค่าเครื่องหมายในByteArrayInputStreamโดยใช้วิธีmark()และreset() เราจะเพิ่มการเรียกใช้เมธอดmark()ให้กับตัวอย่างก่อนหน้านี้:


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

เราจะเห็นว่าตำแหน่งของกระแสเปลี่ยนไป

เอาท์พุต:

อ่าน: 65
อ่าน: 66
อ่าน: 67
อ่าน: 68
อ่าน: 69
วิธีรีเซ็ตการโทร ()
อ่าน: 68
อ่าน: 69

เครื่องหมายรองรับ ()

วิธี การ markSupported()ช่วยให้คุณตรวจสอบว่าสามารถตั้งค่าเครื่องหมายได้หรือไม่ เพื่อให้เข้าใจว่าค่าส่งคืนมาจากไหน ให้ไปที่โค้ดของเมธอด:


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

เมธอดจะคืนค่าtrue เสมอ ลองทดสอบกันในทางปฏิบัติ


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()และreset()สตรีมของเราก็พร้อมเสมอและรองรับการทำเครื่องหมาย:

เอาท์พุต:

isMarkSupported: true
อ่าน: 65
Read: 66
Read: 67
isMarkSupported: true
isMarkSupported: true

ปิด()

และเพื่อให้เข้าใจถึง วิธี การปิดลองมาดูข้างในกัน:


/**
* 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 {
}
    

เอกสารประกอบสำหรับวิธีการปิดบอกเราว่าการปิดByteArrayInputStreamไม่มีผลใดๆ เมธอด คลาสByteArrayInputStream สามารถเรียกได้หลังจากปิดสตรีมโดยไม่ต้องโยนIOException

เราสามารถสรุปอะไรได้บ้าง?

เราต้องการByteArrayInputStreamเมื่อเราต้องการอ่านข้อมูลจากอาร์เรย์แบบไบต์ โดยปกติแล้ว การใช้คลาสนี้ร่วมกับโค้ดอื่นๆ ที่รู้วิธีทำงานกับInputStreamsนั้นสมเหตุสมผลกว่าปกติ