ถัดจากบทความก่อนหน้านี้เราจะเรียนรู้การดำเนินการสตรีมไบต์ใน Java ต่อไป
มัณฑนากรบุตร
สตรีมมัณฑนากรจริง ๆ แล้วเป็นไฟล์สตรีม IO ตามรูปแบบการออกแบบ "โหมดมัณฑนากร" และสตรีมบัฟเฟอร์ของเราเป็นเพียงหนึ่งในนั้น มาดูกันเถอะ
ก่อนหน้านี้เราใช้การอ่านไฟล์และเขียนสตรีม FileInputStream และ FileOutputStream ทั้งการอ่านและเขียนจากดิสก์ไบต์หรือไบต์ซึ่งใช้เวลานานมาก
สตรีมบัฟเฟอร์ของเราสามารถอ่านจำนวนไบต์ของความสามารถที่ระบุจากดิสก์ล่วงหน้าในครั้งเดียวในหน่วยความจำและการดำเนินการอ่านที่ตามมาจะถูกอ่านโดยตรงจากหน่วยความจำเพื่อปรับปรุงประสิทธิภาพ มาดูการใช้งานเฉพาะของกระแสบัฟเฟอร์:
ลองใช้ BufferedInputStream เป็นตัวอย่างก่อนขอพูดถึงคุณสมบัติหลักสั้น ๆ :
BUF เป็นอาร์เรย์ไบต์ที่ใช้สำหรับการอ่านบัฟเฟอร์ ค่าของมันจะถูกเติมอย่างต่อเนื่องเมื่อสตรีมอ่านและการดำเนินการอ่านที่ตามมาสามารถขึ้นอยู่กับอาร์เรย์บัฟเฟอร์นี้โดยตรง
default_buffer_size ระบุขนาดของบัฟเฟอร์เริ่มต้นนั่นคือความยาวอาร์เรย์ของ BUF max_buffer_size ระบุขีด จำกัด บนของบัฟเฟอร์
นับชี้ไปที่ดัชนีไบต์ที่ถูกต้องสุดท้ายในอาร์เรย์บัฟเฟอร์ POS ชี้ไปที่ตำแหน่งดัชนีไบต์ถัดไปที่จะอ่าน
Markpos และ MarkLimit ใช้เพื่อทำซ้ำการดำเนินการอ่าน
ถัดไปลองดูที่ตัวอย่างหลายตัวสร้างของ BufferedInputStream:
Public BufferedInputStream (InputStream In) {this (in, default_buffer_size);} Public BufferedInputStream (inputStream ในขนาด int) {super (in); if (size <= 0) {โยน unleglArgumentException ใหม่ ("ขนาดบัฟเฟอร์ <= 0"); } buf = ไบต์ใหม่ [ขนาด];}โดยรวมแล้วในอดีตจำเป็นต้องผ่านในอินสแตนซ์อินพุตที่ "ตกแต่ง" และใช้บัฟเฟอร์ขนาดเริ่มต้น หลังสามารถระบุขนาดของบัฟเฟอร์ได้อย่างชัดเจน
นอกจากนี้ Super (IN) จะบันทึกอินสแตนซ์อินพุตนี้ลงในฟิลด์แอตทริบิวต์ในของคลาสหลัก FilterInputStream และการดำเนินการอ่านดิสก์จริงทั้งหมดจะออกโดยอินสแตนซ์อินพุตนี้
ลองมาดูการดำเนินการอ่านที่สำคัญที่สุดและวิธีการเติมเต็มบัฟเฟอร์
public synchronized int read () พ่น ioexception {ถ้า (pos> = count) {fill (); if (pos> = นับ) return -1; } return getBufifopen () [pos ++] & 0xff;}ฉันเชื่อว่าทุกคนคุ้นเคยกับวิธีนี้แล้ว มันอ่านไบต์ถัดไปจากสตรีมและส่งคืน แต่การใช้งานในรายละเอียดยังแตกต่างกันเล็กน้อย
นับชี้ไปที่ตำแหน่งถัดไปของดัชนีไบต์ที่ถูกต้องในอาร์เรย์บัฟเฟอร์และ POS ชี้ไปที่ตำแหน่งถัดไปของดัชนีไบต์ที่จะอ่าน ในทางทฤษฎี POS ไม่สามารถมากกว่าการนับเท่าที่เท่ากับ
หาก POS เท่ากับการนับนั่นหมายความว่าไบต์ที่ถูกต้องทั้งหมดในอาร์เรย์บัฟเฟอร์ได้รับการอ่าน ในเวลานี้ข้อมูล "ไร้ประโยชน์" ในบัฟเฟอร์จะต้องถูกยกเลิกและชุดข้อมูลใหม่จะถูกโหลดใหม่จากดิสก์เพื่อเติมบัฟเฟอร์
ในความเป็นจริงวิธีการเติมคือสิ่งที่มันทำ มันมีรหัสมากมายดังนั้นฉันจะไม่พาคุณไปแยกวิเคราะห์ หากคุณเข้าใจฟังก์ชั่นของมันอาจเป็นเรื่องง่ายที่จะวิเคราะห์การใช้งาน
หาก POS ยังคงมีค่าเท่ากับการนับหลังจากวิธีการเติมนั้นเรียกว่าอินสแตนซ์อินพุตไม่ได้อ่านข้อมูลใด ๆ จากสตรีมนั่นคือไม่มีข้อมูลในสตรีมไฟล์ที่จะอ่าน สำหรับสิ่งนี้ดูบรรทัด 246 ของวิธีการเติม
โดยทั่วไปหากบัฟเฟอร์เสร็จสมบูรณ์วิธีการอ่านของเราจะใช้ไบต์โดยตรงจากบัฟเฟอร์และส่งคืนไปยังผู้โทร
การอ่าน int ที่ซิงโครไนซ์สาธารณะ (byte b [], int ปิด, int len) {// ..... }วิธีนี้ยังเป็น "คนรู้จัก" ซึ่งไม่มีคำอธิบายที่ไม่จำเป็นอีกต่อไปการใช้งานจะคล้ายกัน
วิธีการข้ามใช้เพื่อข้ามจำนวนไบต์ของความยาวที่ระบุสำหรับการอ่านต่อเนื่องของสตรีมไฟล์:
การข้ามแบบสาธารณะแบบ synchronized (ยาว n) {// ...... }สิ่งหนึ่งที่ควรทราบคือวิธีการข้ามพยายามข้ามไบต์ N แต่ไม่รับประกันว่าจะข้ามไบต์ วิธีการส่งคืนจำนวนไบต์ที่ข้ามจริง หากจำนวนไบต์ที่เหลืออยู่ในอาร์เรย์บัฟเฟอร์น้อยกว่า N จำนวนไบต์จริงที่สามารถข้ามในอาร์เรย์บัฟเฟอร์จะถูกข้ามในที่สุด
สุดท้ายเรามาพูดถึงวิธีการปิดนี้:
โมฆะสาธารณะปิด () โยน ioexception {byte [] บัฟเฟอร์; ในขณะที่ ((buffer = buf)! = null) {if (bufupdater.Compareandset (นี่, บัฟเฟอร์, null)) {inputStream input = in; ใน = null; if (input! = null) input.close (); กลับ; } // else retry ในกรณีที่ buf ใหม่ถูก cased ใน fill ()}}วิธีการปิดจะล้างกระแส "ตกแต่ง" และเรียกวิธีการปิดเพื่อปล่อยทรัพยากรที่เกี่ยวข้องซึ่งในที่สุดจะล้างพื้นที่หน่วยความจำที่ครอบครองโดยอาร์เรย์บัฟเฟอร์
BufferedInputStream ให้ความสามารถในการอ่านบัฟเฟอร์ในขณะที่ BufferedOutputStream มีความสามารถในการเขียนบัฟเฟอร์การเขียนนั่นคือการดำเนินการเขียนหน่วยความจำจะไม่ได้รับการอัปเดตเป็นดิสก์ทันทีและจะถูกบันทึกชั่วคราวในบัฟเฟอร์และจะถูกเขียนเข้าด้วยกันเมื่อบัฟเฟอร์เต็ม
ได้รับการปกป้องไบต์ buf []; จำนวน int ที่ได้รับการป้องกัน
BUF แสดงถึงบัฟเฟอร์ภายในและการนับแสดงถึงความสามารถของข้อมูลจริงในบัฟเฟอร์นั่นคือจำนวนไบต์ที่มีประสิทธิภาพใน BUF มากกว่าความยาวของอาร์เรย์ BUF
Public BufferedOutputStream (OutputStream) {this (out, 8192);} public BufferedOutputStream (OutputStream, ขนาด int) {super (out); if (size <= 0) {โยน unleglArgumentException ใหม่ ("ขนาดบัฟเฟอร์ <= 0"); } buf = ไบต์ใหม่ [ขนาด];}ด้วยแนวคิดการใช้งานที่เหมือนกันจำเป็นต้องจัดทำอินสแตนซ์ของกระแสเอาต์พุตเอาท์พุทสตรีมและขนาดบัฟเฟอร์ยังสามารถระบุได้
การเขียนโมฆะแบบซิงโครไนซ์สาธารณะ (int b) โยน ioexception {ถ้า (count> = buf.length) {flushbuffer (); } buf [count ++] = (ไบต์) b;}วิธีการเขียนจะตรวจสอบก่อนว่าบัฟเฟอร์ยังสามารถรองรับการดำเนินการเขียนนี้ได้หรือไม่ หากการดำเนินการเขียนดิสก์ไม่สามารถเริ่มต้นข้อมูลบัฟเฟอร์ทั้งหมดจะถูกเขียนลงในไฟล์ดิสก์มิฉะนั้นบัฟเฟอร์จะถูกเขียนไปยังบัฟเฟอร์ก่อน
แน่นอน BufferedOutputStream ยังมีวิธีการล้างเพื่อให้อินเทอร์เฟซกับภายนอกนั่นคือคุณไม่ต้องรอจนกว่าบัฟเฟอร์จะเต็มก่อนที่จะเขียนข้อมูลลงในดิสก์ นอกจากนี้คุณยังสามารถเรียกใช้วิธีนี้อย่างชัดเจนเพื่อล้างบัฟเฟอร์และอัปเดตไฟล์ดิสก์
โมฆะที่ซิงโครไนซ์สาธารณะฟลัช () โยน ioexception {flushbuffer (); out.flush ();}เกี่ยวกับสตรีมบัฟเฟอร์เนื้อหาหลักจะถูกนำมาใช้ดังกล่าวข้างต้น นี่คือสตรีมที่สามารถปรับปรุงประสิทธิภาพได้อย่างมีนัยสำคัญ จำนวนการเข้าถึงดิสก์สามารถลดลงและประสิทธิภาพการดำเนินการของโปรแกรมสามารถปรับปรุงได้
เราจะไม่หารือเกี่ยวกับการจัดเรียง ObjectIalization ObjectInput/OutputStream และ Datainput/OutputStream ตามประเภทพื้นฐาน เมื่อเราเรียนรู้การทำให้เป็นอนุกรมเราจะหารือเกี่ยวกับลำธารสองไบต์นี้อีกครั้ง
รหัสรูปภาพและไฟล์ทั้งหมดในบทความจะถูกเก็บไว้ในคลาวด์บน GitHub ของฉัน:
(https://github.com/singleyam/overview_java)
คุณยังสามารถเลือกที่จะดาวน์โหลดในพื้นที่
สรุป
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่าเนื้อหาของบทความนี้จะมีค่าอ้างอิงบางอย่างสำหรับการศึกษาหรือที่ทำงานของทุกคน หากคุณมีคำถามใด ๆ คุณสามารถฝากข้อความไว้เพื่อสื่อสาร ขอบคุณสำหรับการสนับสนุน Wulin.com