Каков наиболее эффективный способ заменить все \ на \\ в огромном JSON файле? - PullRequest
0 голосов
/ 06 мая 2020

Мне нужно заменить все вхождения \ на \\ в огромном файле JSON Lines. Я хотел использовать Powershell, но могут быть и другие варианты. Исходный файл состоит из 4 000 000 строк и составляет около 6 ГБ.

Скрипт Powershell, который я использовал, занял слишком много времени, я дал ему поработать 2 часа, но это еще не было сделано. Было бы приемлемо выступление продолжительностью полчаса.

$Importfile = "C:\file.jsonl"
$Exportfile = "C:\file2.jsonl"

(Get-Content -Path $Importfile) -replace "[\\]", "\\" | Set-Content -Path $Exportfile

Ответы [ 3 ]

1 голос
/ 06 мая 2020

Если замена представляет собой простое преобразование одиночного backsla sh в двойное backsla sh, файл может обрабатываться построчно.

Использование StringBuilder помещает данные в буфер памяти, который то и дело сбрасывается на диск. Вот так,

$src = "c:\path\MyBigFile.json"
$dst = "c:\path\MyOtherFile.json"
$sb = New-Object Text.StringBuilder
$reader = [IO.File]::OpenText($src)
$i = 0
$MaxRows = 10000

while($null -ne ($line = $reader.ReadLine())) {
    # Replace slashes
    $line = $line.replace('\', '\\') 
    # ' markdown coloring is confused by backslash-apostrophe
    # so here is an extra one just for looks

    [void]$sb.AppendLine($line)
    ++$i

    # Write builder contents into file every now and then
    if($i -ge $MaxRows) {
        add-content $dst $sb.ToString() -NoNewline
        [void]$sb.Clear()
        $i = 0
    }
}
# Flush the builder after the while loop if there's data
if($sb.Length -gt 0) {
    add-content $dst $sb.ToString() -NoNewline
}
$reader.close()
0 голосов
/ 07 мая 2020

На основе вашего предыдущего вопроса Как я могу оптимизировать этот скрипт Powershell, конвертируя JSON в CSV? . Вы должны попытаться использовать для этого конвейер PopwerShell, особенно когда это касается больших файлов ввода и вывода.
Дело в том, что вы не должны сосредотачиваться на отдельных частях решения для определения производительности, потому что это обычно оставляет неправильное впечатление, поскольку производительность полного (PowerShell) конвейерного решения должна быть лучше, чем сумма его частей . Кроме того, это экономит много памяти, и в результате получается простой синтаксис PowerShell ...
В вашем конкретном случае c, при правильной настройке, ЦП заменит косые черты, перестроит строки json и преобразует их в объекты пока жесткий диск занят чтением и записью данных ...

Для реализации замены косых черт в конвейере PowerShell вместе с ConvertFrom-JsonLines командлетом:

Get-Content .\file.jsonl | ForEach-Object { $_.replace('\', '\\') } |
ConvertFrom-JsonLines | ForEach-Object { $_.events.items } |
Export-Csv -Path $Exportfile -NoTypeInformation -Encoding UTF8
0 голосов
/ 06 мая 2020

Используйте параметр -ReadCount для командлета Get-Content (и установите для него значение 0).

-ReadCount

Указывает, сколько строк содержимого отправляется по конвейеру за раз. Значение по умолчанию - 1. Значение 0 (ноль) отправляет все содержимое за один раз.

Этот параметр не изменяет отображаемое содержимое, но влияет на время, необходимое для отображения содержимого. По мере увеличения значения ReadCount время, необходимое для возврата первой строки, увеличивается, но общее время для операции уменьшается. Это может иметь заметное значение для больших элементов.

Пример (выполняется примерно в 17 раз быстрее для файла примерно 20 МБ):

$file = 'D:\bat\files\FileTreeLista.txt'
(Measure-Command { 
    $xType = (Get-Content -Path $file             ) -replace "[\\]", "\\"
}).TotalSeconds, $xType.Count -join ', '
(Measure-Command {
    $yType = (Get-Content -Path $file -ReadCount 0) -replace "[\\]", "\\"
}).TotalSeconds, $yType.Count -join ', '
Get-Item $file | Select-Object FullName, Length
13,3288848, 338070
 0,7557814, 338070

FullName                         Length
--------                         ------
D:\bat\files\FileTreeLista.txt 20723656
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...