如何在Crystal中读取一定数量的字符(而不是字节)



在Crystal中,如果我有一个字符串(或文件(,如何一次读取一定数量的字符使用IO#readIO#getsIO#read_stringIO#read_utf8等函数,可以指定要读取的字节数,但不能指定UTF-8字符数(或其他编码的字符数(。

例如,在Python中,可以这样做:

from io import StringIO
s = StringIO("abcdefgh")
while True:
chunk = s.read(4)
if not chunk: break

或者,在文件的情况下,这是:

with open("example.txt", 'r') as f:
while True:
chunk = f.read(4)
if not chunk: break

通常,我希望IO::Memory是用于字符串大小写的类,但据我所知,它的方法不允许这样做在Crystal中,如何以高效且惯用的方式(对于字符串和文件,可能每个答案都不同(

目前在Crystal中没有这方面的捷径实现。

您可以用IO#read_char读取单个字符,也可以用IO#each_char读取连续字符。

因此,一个基本的实现是:

io = IO::Memory.new("€abcdefgh") 
string = String.build(4) do |builder|
4.times do
builder << io.read_char
end
end
puts string

无论你使用内存IO、文件还是任何其他IO都无关紧要,行为都是一样的。

io = IO::Memory.new("€€€abc€€€")   #UTF-8 string from memory
or
io = File.open("test.txt","r")     #UTF-8 string from file 
iter = io.each_char.each_slice(4)  #read max 4 chars at once
iter.each { |slice|                #into a slice
puts slice
puts slice.join                  #join to a string
} 
output:
['€', '€', '€', 'a']
€€€a
['b', 'c', '€', '€']
bc€€
['€']
€

除了已经给出的答案外,对于Crystal中的字符串,您可以读取X个字符,范围如下:

my_string = "A foo, a bar."
my_string[0..5] => "A foo"

这个解决方法似乎对我有效:

io = IO::Memory.new("abcdefghz")
chars_to_read = 2 # Number of chars to read
while true
chunk = io.gets(chars_to_read) # Grab the chunk of type String?
break if chunk.nil? # Break if nothing else to read aka `nil`
end

相关内容

  • 没有找到相关文章

最新更新