คุณกำลังมองหาวัตถุที่มีลักษณะเหมือน IO
วัตถุ (ไฟล์ ซ็อกเก็ต ฯลฯ) แต่คุณสามารถควบคุมได้เหมือนสตริงหรือไม่
แล้วก็ StringIO
สำหรับคุณ
ผมขอแสดงตัวอย่างและสิ่งที่ควรระวัง!
ตัวอย่างพื้นฐาน
การสร้าง StringIO
วัตถุที่คุณสามารถทำได้:
io = StringIO.new("abc")
จากนั้นคุณสามารถอ่านจากวัตถุนี้โดยใช้วิธีการเช่น gets
, read
&each_line
.
ฉันทำตารางที่มีประโยชน์สำหรับคุณด้วยวิธีที่มีประโยชน์ที่สุด:
วิธีการ | คำอธิบาย |
---|---|
ได้รับ | อ่านอินพุตหนึ่งบรรทัด |
อ่าน | อ่านจำนวนไบต์ที่ระบุ (ทั้งหมดเป็นค่าเริ่มต้น) |
each_line | กำหนดบล็อก วนซ้ำในแต่ละบรรทัด |
each_char | กำหนดบล็อก วนซ้ำอักขระแต่ละตัว |
<< | ผนวกข้อมูล |
กรอกลับ | รีเซ็ตตัวชี้ตำแหน่งภายใน |
สตริง | คืนค่าสตริงจริงจากออบเจ็กต์ stringio |
ขอให้สังเกตว่า StringIO
มีตัวชี้ตำแหน่ง
ตัวชี้นี้จะติดตามจำนวนไบต์ที่คุณอ่าน เช่นเดียวกับวัตถุไฟล์
ดังนั้นทุกครั้งที่คุณเรียกใช้เมธอดอย่าง gets
หรือ read
มันจะให้ข้อมูลจำนวนนั้นแก่คุณ &เลื่อนตัวชี้
แม้แต่วิธีการนับได้เช่น map
หรือ each_line
จะเลื่อนตัวชี้ตำแหน่ง ดังนั้นโปรดระลึกไว้เสมอว่า
io.each_line { |line| puts line }
คุณสามารถรีเซ็ตตัวชี้ตำแหน่งไปที่จุดเริ่มต้นโดยใช้ rewind
วิธีการ:
io.pos # 45 io.rewind io.pos # 0
เท่านั้นสำหรับพื้นฐาน
ฉันจะแสดงให้คุณเห็นการใช้งานจริงบางประการสำหรับ StringIO
แต่ก่อนอื่น ให้ฉันแสดงอย่างอื่นให้คุณดูก่อน
แล้วอะไรเกี่ยวกับ StringScanner
ตอนนี้คุณได้เห็นแล้วว่า StringIO
ทำได้ แต่ Ruby Standard Library มีคลาสอื่นที่เกี่ยวข้องกับสตริง
คลาสนั้นคือ StringScanner
อาจทำให้สับสนได้เนื่องจากมีชื่อและวิธีการคล้ายกัน แต่ให้ฉันช่วยคุณเห็นความแตกต่าง
สิ่งสำคัญคือสิ่งนี้ :
StringIO
วัตถุสามารถแทนที่ IO
. อื่นได้ วัตถุ (เช่น File
หรือ Socket
) แต่ StringScanner
มีไว้สำหรับทำสิ่งต่าง ๆ เช่นการแยกวิเคราะห์ (ทำให้ข้อความบางส่วนมีความหมายโดยแบ่งเป็นชุดโทเค็น)
คลาสทั้งสองนี้ยังคงแบ่งปันบางสิ่ง นอกเหนือจากการมี “สตริง” ในชื่อ พวกเขาทั้งคู่ใช้ตัวชี้ตำแหน่งภายใน .
การแทนที่อินพุตและเอาต์พุตมาตรฐาน
สมมติว่าคุณกำลังเขียนแอปพลิเคชันบรรทัดคำสั่งที่ขอผลลัพธ์จากผู้ใช้โดยใช้วิธี Kernel#gets…
…ถ้าคุณต้องการทดสอบโค้ดนี้ คุณจะต้องป้อนข้อมูลบางอย่างด้วยมือทุกครั้ง
เป็นการทดสอบอัตโนมัติจากภาพหรือไม่
ไม่ มันไม่ใช่!
นี่คือที่ที่ StringIO
มาเพื่อช่วยชีวิต คุณสามารถเริ่มต้น StringIO
วัตถุด้วยอินพุตทดสอบของคุณแล้วแทนที่วัตถุอินพุตมาตรฐานที่ชี้ด้วย $stdin
(นี่คือที่ที่ Ruby ค้นหาอินพุตของผู้ใช้เมื่อคุณเรียก gets
)
ตัวอย่าง :
io = StringIO.new("input") $stdin = io gets # input
เทคนิคนี้ยังสามารถใช้เพื่อจับภาพผลลัพธ์จากวิธีการต่างๆ เช่น puts
.
วิธีการแสดงผลจะพิมพ์ไปยังอุปกรณ์ส่งออกเริ่มต้นที่เรียกว่า 'เอาต์พุตมาตรฐาน' ใน Ruby แสดงด้วย IO
วัตถุที่คุณสามารถแทนที่ด้วย StringIO
. ของคุณ วัตถุ
ตัวอย่าง :
io = StringIO.new("") $stdout = io # Print to $stdout puts "Jesus Castello is from Spain & likes to help people learn Ruby." # Restore original value $stdout = STDOUT io.rewind io.read # "Jesus Castello is from Spain & likes to help people learn Ruby."
สิ่งนี้มีความเกี่ยวข้องมากกว่าเวอร์ชันอินพุต เนื่องจากเราต้องการให้แน่ใจว่าได้กู้คืน STDOUT
ดั้งเดิม วัตถุ &เพื่อย้อนกลับ StringIO
. ของเรา เพื่อให้เราสามารถอ่านผลลัพธ์ได้
สังเกตว่าเฟรมเวิร์กการทดสอบส่วนใหญ่มีวิธีการทำเช่นนี้ให้คุณ (asssert_output สำหรับ Minitest &ตัวจับคู่เอาต์พุตใน RSpec) แต่การรู้ว่าเกิดอะไรขึ้นเบื้องหลังนั้นเป็นเรื่องที่ดีเสมอ 🙂
สรุป
คุณได้เรียนรู้เกี่ยวกับ StringIO
คลาสซึ่งเลียนแบบ IO
. ของจริง วัตถุจึงทำหน้าที่แทนวัตถุชนิดนั้นได้
ซึ่งจะเป็นประโยชน์สำหรับการทดสอบคลาสที่เขียนเอาต์พุตไปยังหน้าจอหรือกำหนดให้ผู้ใช้ป้อนข้อมูลผ่านเทอร์มินัล
หากคุณรู้จักการใช้ StringIO
. ที่น่าสนใจ แจ้งให้เราทราบในความคิดเห็นและอย่าลืม แชร์สิ่งนี้ บทความเพื่อให้ผู้คนได้เพลิดเพลินมากขึ้น!