IO#gets 的工作方式与从命令行捕获输入相同:“Enter”不作为输入的一部分发送;在 File 或 IO 的其他子类上调用 #gets 时也不会通过,因此这些数字肯定不会匹配。
请参阅相关的镐部分
我可以问一下您为什么如此担心行长与文件大小的总和吗?你可能正在解决一个比必要的更难的问题......
啊哈。我想我现在明白了。
缺少一个方便的 iPod(或任何其他类型,就此而言),我不知道您是否想要精确的 4K 块,在这种情况下 IO#read(4000) 将是您的朋友(4000 或 4096?)或者如果您更乐意按行打破,在这种情况下,这样的事情应该可以工作:
class Chunkifier
def Chunkifier.to_chunks(path)
chunks, current_chunk_size = [""], 0
File.readlines(path).each do |line|
line.chomp! # strips off \n, \r or \r\n depending on OS
if chunks.last.size + line.size >= 4_000 # 4096?
chunks.last.chomp! # remove last line terminator
chunks << ""
end
chunks.last << line + "\n" # or whatever terminator you need
end
chunks
end
end
if __FILE__ == $0
require 'test/unit'
class TestFile < Test::Unit::TestCase
def test_chunking
chs = Chunkifier.to_chunks(PATH)
chs.each do |chunk|
assert 4_000 >= chunk.size, "chunk is #{chunk.size} bytes long"
end
end
end
end
请注意使用 IO#readlines 将所有文本一次性获取:#each 或 #each_line 也可以。我用过字符串#chomp!以确保无论操作系统在做什么,最后的字节都被删除,以便 \n 或任何可以强制进入输出。
我建议使用 File#write,而不是 #print 或 #puts 作为输出,因为后者倾向于提供特定于操作系统的换行符序列。
如果您真的关心多字节字符,请考虑使用 each_byte 或 unpack(C*) 选项和猴子修补字符串,如下所示:
class String
def size_in_bytes
self.unpack("C*").size
end
end
顺便说一句,解包版本比我机器上的 each_byte 快大约 8 倍。