Исходный файл PowerShell: предотвратить изменения кодировки

В настоящее время я работаю над некоторой операцией поиска и замены, которую пытаюсь автоматизировать с помощью powershell. К сожалению, я вчера узнал, что у нас есть разные кодировки файлов в нашей кодовой базе (UTF8 и ASCII). Поскольку мы выполняем эти операции поиска и замены в другой ветви, я не могу изменить кодировки файлов на этом этапе.

Если я запускаю следующие строки, он меняет все файлы на UCS-2 Little Eindian, хотя моя кодировка powershell по умолчанию установлена ​​на iso-8859-1 (западноевропейская (Windows)).

$content = Get-Content $_.Path
$content -replace 'myOldText' , 'myNewText' | Out-File $_.Path

Есть ли способ предотвратить изменение кодировки файла в PowerShell?

1 ответ

Решение

Out-File имеет кодировку по умолчанию, если она не переопределена -Encoding параметр:

Чтобы решить эту проблему, я попытался получить кодировку исходного файла, прочитав попытку прочитать его метку порядка байтов и используя его в качестве-Encoding значение параметра.

Вот пример обработки множества путей текстовых файлов, получения исходной кодировки, обработки содержимого и записи его обратно в файл с кодировкой оригинала.

function Get-FileEncoding {
    param ( [string] $FilePath )

    [byte[]] $byte = get-content -Encoding byte -ReadCount 4 -TotalCount 4 -Path $FilePath

    if ( $byte[0] -eq 0xef -and $byte[1] -eq 0xbb -and $byte[2] -eq 0xbf )
        { $encoding = 'UTF8' }  
    elseif ($byte[0] -eq 0xfe -and $byte[1] -eq 0xff)
        { $encoding = 'BigEndianUnicode' }
    elseif ($byte[0] -eq 0xff -and $byte[1] -eq 0xfe)
         { $encoding = 'Unicode' }
    elseif ($byte[0] -eq 0 -and $byte[1] -eq 0 -and $byte[2] -eq 0xfe -and $byte[3] -eq 0xff)
        { $encoding = 'UTF32' }
    elseif ($byte[0] -eq 0x2b -and $byte[1] -eq 0x2f -and $byte[2] -eq 0x76)
        { $encoding = 'UTF7'}
    else
        { $encoding = 'ASCII' }
    return $encoding
}

foreach ($textFile in $textFiles) {
    $encoding = Get-FileEncoding $textFile
    $content = Get-Content -Encoding $encoding
    # Process content here...
    $content | Set-Content -Path $textFile -Encoding $encoding
}

Обновление Вот пример получения исходной кодировки файла с использованием класса StreamReader. Пример читает первые 3 байта файла, так что CurrentEncoding свойство устанавливается на основе результата его внутренней процедуры обнаружения спецификации.

http://msdn.microsoft.com/en-us/library/9y86s1a9.aspx

Параметр detectEncodingFromByteOrderMarks обнаруживает кодировку, просматривая первые три байта потока. Он автоматически распознает UTF-8, Unicode с прямым порядком байтов и Unicode с прямым порядком байтов, если файл начинается с соответствующих меток порядка байтов. В противном случае используется кодировка UTF8. См. Метод Encoding.GetPreamble для получения дополнительной информации.

http://msdn.microsoft.com/en-us/library/system.text.encoding.getpreamble.aspx

$text = @" 
This is
my text file
contents.
"@

#Create text file.
[IO.File]::WriteAllText($filePath, $text, [System.Text.Encoding]::BigEndianUnicode)

#Create a stream reader to get the file's encoding and contents.
$sr = New-Object System.IO.StreamReader($filePath, $true)
[char[]] $buffer = new-object char[] 3
$sr.Read($buffer, 0, 3)  
$encoding = $sr.CurrentEncoding
$sr.Close()

#Show the detected encoding.
$encoding

#Update the file contents.
$content = [IO.File]::ReadAllText($filePath, $encoding)
$content2 = $content -replace "my" , "your"

#Save the updated contents to file.
[IO.File]::WriteAllText($filePath, $content2, $encoding)

#Display the result.
Get-Content $filePath
Другие вопросы по тегам