如何在 Crystal 中读取一定数量的字符(而不是字节)?
How to read a certain number of characters (as opposed to bytes) in Crystal?
在Crystal中,如果我有一个字符串(或文件),如何一次读取一定数量的字符 ? 使用 IO#read
、IO#gets
、IO#read_string
和 IO#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
成为用于字符串大小写的 class,但据我所知,它的方法不允许这样做。 如何以一种高效和惯用的方式做到这一点(对于字符串和文件——也许每个答案都不同)in Crystal?
这个解决方法似乎对我有用:
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
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 中没有对此可用的快捷方式实现。
您可以使用 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 都是无关紧要的,行为都是一样的。
除了已经给出的答案之外,对于 Crystal 中的字符串,您可以读取 X 数量的字符,范围如下:
my_string = "A foo, a bar."
my_string[0..5] => "A foo"
在Crystal中,如果我有一个字符串(或文件),如何一次读取一定数量的字符 ? 使用 IO#read
、IO#gets
、IO#read_string
和 IO#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
成为用于字符串大小写的 class,但据我所知,它的方法不允许这样做。 如何以一种高效和惯用的方式做到这一点(对于字符串和文件——也许每个答案都不同)in Crystal?
这个解决方法似乎对我有用:
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
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 中没有对此可用的快捷方式实现。
您可以使用 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 都是无关紧要的,行为都是一样的。
除了已经给出的答案之外,对于 Crystal 中的字符串,您可以读取 X 数量的字符,范围如下:
my_string = "A foo, a bar."
my_string[0..5] => "A foo"