Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

StringIO ใน Ruby:มันทำงานอย่างไร &วิธีใช้งาน

คุณกำลังมองหาวัตถุที่มีลักษณะเหมือน 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 . ที่น่าสนใจ แจ้งให้เราทราบในความคิดเห็นและอย่าลืม แชร์สิ่งนี้ บทความเพื่อให้ผู้คนได้เพลิดเพลินมากขึ้น!