2012-03-21 20 views
7

Tôi đang cố gắng đọc một dòng từ một io theo cách không chặn.đường không bị chặn của ruby ​​đọc

Thật không may là readline khối. Tôi nghĩ rằng tôi có thể giải quyết điều này với read_nonblock với một bộ đệm bổ sung mà tôi lưu trữ một phần kết quả, kiểm tra xem có nhiều dòng trong bộ đệm, vv .. nhưng có vẻ như một chút phức tạp cho một nhiệm vụ đơn giản như thế này. Có cách nào tốt hơn để làm điều này?

Lưu ý: Tôi đang sử dụng sự kiện giải mã kênh (select) và tôi khá hài lòng với nó, tôi không muốn tạo chủ đề, sử dụng EventMachine, vv ...

Trả lời

5

Tôi nghĩ rằng giải pháp read_nonblock là có lẽ là con đường để đi. Đơn giản, không tối đa hiệu quả phiên bản khỉ vá:

class IO 
    def readline_nonblock 
    rlnb_buffer = "" 
    while ch = self.read_nonblock(1) 
     rlnb_buffer << ch 
     if ch == "\n" then 
     result = rlnb_buffer 
     return result 
     end 
    end  
    end 
end  

Đó ném một ngoại lệ nếu không có dữ liệu sẵn sàng, giống như read_nonblock, vì vậy bạn phải giải cứu mà chỉ có được một con số không trở lại vv

+0

Yeah, đó là ý tưởng ban đầu của tôi, và đó là những gì cuối cùng tôi đã làm, nhưng tôi đọc càng nhiều càng tốt tôi có thể (không chỉ là một char duy nhất), tôi nghĩ rằng đó là tốt hơn cho hiệu suất. Cảm ơn cho tip monke-patch;) –

3

thực hiện điều này cải thiện về câu trả lời Đánh dấu Reed bằng cách không vứt bỏ dữ liệu đọc mà không kết thúc trong một dòng mới:

class IO 
    def readline_nonblock 
    buffer = "" 
    buffer << read_nonblock(1) while buffer[-1] != "\n" 

    buffer 
    rescue IO::WaitReadable => blocking 
    raise blocking if buffer.empty? 

    buffer 
    end 
end 
+1

"không bảo đảm" - đó là kinda đáng sợ. không dựa vào 'tính năng' không có giấy tờ. "Tôi đã thử nghiệm điều này" - thorougly? với các phương thức nhập khác nhau? Nó có thể chỉ làm việc vì đầu vào của bạn là dòng đệm ... –

+0

Tôi đã không đủ can đảm để dựa vào nó hoặc là, đó là lý do tại sao tôi bao gồm phần thứ hai. :-) –

+0

Tôi đã xác minh rằng 'read_nonblock (4096)' không trả lại một dòng trên ruby ​​1.9.3, 2.0.0 và 2.1.3. Tốt hơn đưa đề xuất này ra ngoài. Dễ đủ để xác minh với 'ruby19 -e 'x = IO.popen (" cat/etc/fstab "); ngủ 0,2; p x.read_nonblock (4096) ''. – chutz

Các vấn đề liên quan