Я хочу Get-Content
большого (1 ГБ - 10 ГБ) .txt
файла (который имеет только 1 строку!) и разделить его на несколько файлов с несколькими строками, но всякий раз, когда я пытаюсь это сделать, я получаю System.OutOfMemoryException
.
Конечно, я действительно искал решение, но все решения, которые я нашел, заключались в чтении файла построчно, что довольно трудно сделать, когда файл имеет только одну строку.
Хотя PowerShell занимает до 4 ГБ оперативной памяти при загрузке файла объемом 1 ГБ, проблема не связана с моей оперативной памятью, так как у меня всего 16 ГБ, и даже если игра работает в фоновом режиме, пиковое использование составляет около 60%.
Я использую Windows 10 с PowerShell 5.1 (64-разрядная версия ), и для моего MaxMemoryPerShellMB
установлено значение по умолчанию 2147483647
.
Это сценарий, который я написал и использую, он отлично работает с размером файла, например, 100 МБ:
$source = "C:\Users\Env:USERNAME\Desktop\Test\"
$input = "test_1GB.txt"
$temp_dir = "_temp"
# 104'857'600 bytes (or characters) are exactly 100 MB, so a 1 GB file has exactly
# 10 temporary files, which have all the same size, and amount of lines and line lenghts.
$out_size = 104857600
# A line length of somewhere around 18'000 characters seems to be the sweet spot, however
# the line length needs to be dividable by 4 and at best fit exactly n times into the
# temporary file, so I use 16'384 bytes (or characters) which is exactly 16 KB.
$line_length = 16384
$file = (gc $input)
$in_size = (gc $input | measure -character | select -expand characters)
if (!(test-path $source$temp_dir)) {ni -type directory -path "$source$temp_dir" >$null 2>&1}
$n = 1
$i = 0
if ($out_size -eq $in_size) {
$file -replace ".{$line_length}", "$&`r`n" | out-file -filepath "$temp_dir\_temp_0001.txt" -encoding ascii
} else {
while ($i -le ($in_size - $out_size)) {
$new_file = $file.substring($i,$out_size)
if ($n -le 9) {$count = "000$n"} elseif ($n -le 99) {$count = "00$n"} elseif ($n -le 999) {$count = "0$n"} else {$count = $n}
$temp_name = "_temp_$count.txt"
$i += $out_size
$n += 1
$new_file -replace ".{$line_length}", "$&`r`n" | out-file -filepath "$temp_dir\$temp_name" -encoding ascii
}
if ($i -ne $in_size) {
$new_file = $file.substring($i,($in_size-$i))
if ($n -le 9) {$count = "000$n"} elseif ($n -le 99) {$count = "00$n"} elseif ($n -le 999) {$count = "0$n"} else {$count = $n}
$temp_name = "_temp_$count.txt"
$new_file -replace ".{$line_length}", "$&`r`n" | out-file -filepath "$temp_dir\$temp_name" -encoding ascii
}
}
Если есть более простое решение, которое не использует Get-Content
я также с радостью приму его. На самом деле не имеет большого значения, как я добиваюсь результата, если это возможно с каждой современной машиной Windows и без дополнительного программного обеспечения. Если это, однако, не будет возможно, я бы также рассмотрел другие решения.