[Обновлено] Написал короткую версию без каких-либо вспомогательных переменных и поместил все в метод:
def chunker f_in, out_pref, chunksize = 1_073_741_824
File.open(f_in,"r") do |fh_in|
until fh_in.eof?
File.open("#{out_pref}_#{"%05d"%(fh_in.pos/chunksize)}.txt","w") do |fh_out|
fh_out << fh_in.read(chunksize)
end
end
end
end
chunker "inputfile.txt", "output_prefix" (, desired_chunk_size)
Вместо линейного цикла вы можете использовать.read(length)
и выполняйте цикл только для маркера EOF
и курсора файла.
Это гарантирует, что объемные файлы никогда не будут больше желаемого размера фрагмента.
С другой стороныдаже если он не заботится о переносе строк (\n
)!
Числа для файлов чанка будут сгенерированы из целочисленного деления текущей позиции курсора файла на размер чанка, отформатированный с помощью «% 05d», в результате чего получится 5-значныйчисла с начальным нулем (00001
).
Это возможно только потому, что используется .read(chunksize)
.Во втором приведенном ниже примере его нельзя использовать!
Обновление: Разделение с распознаванием разрыва строки
Если вам действительно нужны полные строки с\n
затем используйте этот измененный фрагмент кода:
def chunker f_in, out_pref, chunksize = 1_073_741_824
outfilenum = 1
File.open(f_in,"r") do |fh_in|
until fh_in.eof?
File.open("#{out_pref}_#{outfilenum}.txt","w") do |fh_out|
line = ""
while fh_out.size <= (chunksize-line.length) && !fh_in.eof?
line = fh_in.readline
fh_out << line
end
end
outfilenum += 1
end
end
end
Мне пришлось ввести вспомогательную переменную line
, потому что я хочу убедиться, что размер файла всегда будет на ниже chunksize
предел!Если вы не выполните эту расширенную проверку, вы также получите размеры файлов, превышающие лимит.Оператор while
успешно проверяет только следующий шаг итерации, когда строка уже записана.(Работа с .ungetc
или другими сложными вычислениями сделает код более нечитаемым и не короче, чем в этом примере.)
К сожалению, вам понадобится вторая проверка EOF
, потому что последняя итерация фрагмента в большинстве случаев приведет кв меньшем куске.
Также необходимы две вспомогательные переменные: line
описан выше, outfilenum
необходим, потому что результирующие размеры файлов в основном не соответствуют точным chunksize
.