2015-08-05 2 views
2

Если я запускаю следующий код:Использование Рубин StringIO получает метод

require 'stringio' 
chunked_data = StringIO.new("7\r\nHello, \r\n6\r\nworld!\r\n0\r\n") 
data = "" 
until chunked_data.eof? 
    if chunk_head = chunked_data.gets("\r\n") 
    print chunk_head 
    if chunk = chunked_data.read(chunk_head.to_i) 
     print chunk 
     data << chunk 
    end 
    end 
end 

я получаю этот выход:

7 
Hello, 
6 
world! 
0 

According to the docs, метод gets принимает разделитель и возвращает следующую строку, основываясь на том, что разделитель. Если я заменю \r\n в строке и сепаратором с ., то функциональные возможности сепаратора, кажется, больше не работает, и я получаю это:

7.Hello, .6.world!.0. 

Что происходит?

+4

Протестируйте свой код, и я получаю тот же результат для '\ r \ n' и' .'. Метод не удаляет разделитель из строки, если это вас смущает. – konart

ответ

2

Чтобы увидеть, что происходит на самом деле, давайте заменим print с более явным выходом:

require 'stringio' 

def parse(chunked_data, separator) 
    data = "" 
    until chunked_data.eof? 
    if chunk_head = chunked_data.gets(separator) 
     puts "chunk_head: #{chunk_head.inspect}" 
     if chunk = chunked_data.read(chunk_head.to_i) 
     puts "  chunk: #{chunk.inspect}" 
     data << chunk 
     end 
    end 
    end 
    data 
end 

result = parse(StringIO.new("7\r\nHello, \r\n6\r\nworld!\r\n0\r\n"), "\r\n") 
puts " result: #{result.inspect}" 

Выход:

chunk_head: "7\r\n" 
    chunk: "Hello, " 
chunk_head: "\r\n" 
    chunk: "" 
chunk_head: "6\r\n" 
    chunk: "world!" 
chunk_head: "\r\n" 
    chunk: "" 
chunk_head: "0\r\n" 
    chunk: "" 

Теперь с .:

result = parse(StringIO.new("7.Hello, .6.world!.0."), ".") 
puts " result: #{result.inspect}" 

Выход:

chunk_head: "7." 
    chunk: "Hello, " 
chunk_head: "." 
    chunk: "" 
chunk_head: "6." 
    chunk: "world!" 
chunk_head: "." 
    chunk: "" 
chunk_head: "0." 
    chunk: "" 
    result: "Hello, world!" 

Как вы можете видеть, он работает в любом случае, и результат идентичен.

Хотя результат верен, в вашем коде есть ошибка: вы не читаете разделитель после chunk. Это может быть исправлено путем добавления chunked_data.gets(separator) или chunked_data.read(separator.bytesize) после if/end блока:

def parse(chunked_data, separator) 
    data = "" 
    until chunked_data.eof? 
    if chunk_head = chunked_data.gets(separator) 
     puts "chunk_head: #{chunk_head.inspect}" 
     if chunk = chunked_data.read(chunk_head.to_i) 
     puts "  chunk: #{chunk.inspect}" 
     data << chunk 
     end 
     chunked_data.read(separator.bytesize) 
    end 
    end 
    data 
end 

result = parse(StringIO.new("7.Hello, .6.world!.0."), ".") 
puts " result: #{result.inspect}" 

Выход:

chunk_head: "7." 
    chunk: "Hello, " 
chunk_head: "6." 
    chunk: "world!" 
chunk_head: "0." 
    chunk: "" 
    result: "Hello, world!" 

Это выглядит лучше.

Смежные вопросы