2016-10-04 1 views
1

У меня есть код Powershell, который позволяет мне добавить строку символов в каждый раздел из 500 символов в текстовом файле с одной строкой.Добавление строки в каждый раздел однострочного файла в Powershell

[system.io.stream]$stream = [system.io.File]::OpenRead($path) 
$number_of_sections = $stream.length/500 
$count = 0 
[Byte[]] $section_bytes = New-Object byte[] 500 

while($count -lt $number_of_sections) { 
     [Void]$stream.Read($section_bytes, 0 ,500) 
     $thisLine = [System.Text.ASCIIEncoding]::ASCII.GetString($section_bytes) 

     $section = $thisLine.Substring(0,500) 
     $string_to_be_added += "example string" + $section 
     $count++ 
} 

[Byte[]] $get_bytes = [System.IO.File]::ReadAllBytes($string_to_be_added) 
$write_bytes = [System.IO.File]::WriteAllBytes($write_path, $get_bytes) 

Теперь этот код считывает большую одиночную строку в байтах текстового файла байтом. Проблема возникает, когда я пытаюсь читать и писать очень большие файлы (60 МБ и выше). Этот скрипт занимает около 30 минут для выполнения, который слишком медленный и использует много памяти.

Есть ли другой способ или обновление моего кода, что позволит мне быстрее обрабатывать файл и добавить мою строку в каждую секцию 500 символов более эффективно? Благодарю.

+0

Параметр 'while' цикл не делает никаких изменений, которые длятся вне цикла до последней итерации, поэтому он не добавляет символы в каждой секции. 'ReadAllBytes()' принимает имя файла в качестве параметра, нет пути '$ string_to_be_added' после того, как последняя итерация цикла также будет действительным (500 + байт) именем файла. Тогда у вас есть неопределенный '$ write_path'. Я подозреваю, что это занимает навсегда, потому что вы никогда не увеличиваете '$ count', поэтому цикл никогда не прекращается, и вы на самом деле не видели его завершения и заметили, что он не работает? – TessellatingHeckler

+0

Я отредактировал код, чтобы включить инкремент. У меня есть $ write_path, уже инициализированный выше этого кода. Я думаю, мне нужно каким-то образом написать каждый сегмент моей строки и 500 символов каждый раз, когда цикл выполняется, но я не уверен, как это сделать. – AJennings1

ответ

1
  1. Использование StreamReader и StreamWriter, которые обрабатывают текстовые файлы правильно
  2. Не накапливают вывод, запишите его сразу

#$outputEncoding = [Text.Encoding]::ASCII 
$outputEncoding = [Text.UTF8Encoding]::new($false), #UTF8 without BOM 
$reader = [IO.StreamReader]::new('r:\1.txt') 
$writer = [IO.StreamWriter]::new('r:\2.txt', 
           $false, # don't append 
           $outputEncoding, 
           10MB) # write-back cache 
$buf = [char[]]::new(500) 

while (!$reader.EndOfStream) { 
    $nRead = $reader.Read($buf, 0, $buf.length) 
    $writer.Write('example string') 
    $writer.Write($buf, 0, $nRead) 
} 

$reader.Close() 
$writer.Close() 

В случае, если вы действительно должны накопить текст в переменной, чтобы использовать его впоследствии, используйте StringBuilder:

$reader = [IO.StreamReader]::new('r:\1.txt') 
$buf = [char[]]::new(500) 
$prefix = 'example string' 
$outputSize = $reader.BaseStream.Length * (1 + $prefix.Length/500) 
$text = [Text.StringBuilder]::new([int]$outputSize) # allocate memory 

while (!$reader.EndOfStream) { 
    $nRead = $reader.Read($buf, 0, $buf.length) 
    $text.Append($prefix) >$null 
    $text.Append($buf, 0, $nRead) >$null 
} 

$reader.Close() 
$newText = $text.ToString() 

А вот пример с использованием регулярных выражений:

$prefix = 'example string' 
$prefixRX = $prefix.Replace('$', '$$') # escape special sequences like $& etc. 
             # see https://msdn.microsoft.com/ewy2t5e0 
$prefix + ([IO.File]::ReadAllText('r:\1.txt') -replace '(?s).{500}', ('$&' + $prefixRX)) | 
    Out-File 'r:\2.txt' -Encoding utf8