2012-02-02 11 views
23

私は現在、powershellを使用して自動化しようとしている検索と置換操作を行っています。残念ながら私は昨日、コードベース(UTF8とASCII)で異なるファイルエンコーディングがあることを認識しました。私たちはこれらの検索と別のブランチでの操作を置き換えているので、私はこの段階でファイルのエンコーディングを変更することはできません。PowerShell out-file:エンコードの変更を防止する

デフォルトのpowershellエンコーディングがiso-8859-1(西ヨーロッパ(Windows))に設定されていても、次の行を実行すると、すべてのファイルがUCS-2 Little Eindianに変更されます。

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

ファイルのエンコードを変更できないようにする方法はありますか? -Encodingパラメータで上書きしない限り、

答えて

31

Out-Fileは、デフォルトのエンコーディングを持っている:私はこれを解決するために何をやったか

はそれがbyte order markだ読み取ろうと読み、-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クラスを使用して、元のファイルのエンコーディングを取得する例です。この例では、内部のBOM検出ルーチンの結果に基づいてCurrentEncodingプロパティが設定されるように、ファイルの最初の3バイトを読み取ります。

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

detectEncodingFromByteOrderMarksパラメータは、ストリームの最初の3つのバイトを見 による符号化を検出します。自動的に がUTF-8、リトルエンディアンのUnicode、およびビッグエンディアンのUnicodeテキスト を認識します。ファイルが適切なバイト順序記号で始まる場合それ以外の場合は、 UTF8Encodingが使用されます。さらに 情報については、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 
+0

私はすでにそれについて考えたが、もっと簡単な方法がなければならない、それはなりませんか?しかし、それは今私のために働く。ありがとうAndy! – Pete

+2

@Peteエンコーディングを取得する必要があります。それを取得するコマンドレットはありません。私は別のアプローチを追加して私の答えを更新しました。どちらの方法もBOM検出を使用します。 –

+0

'Set-Content -Path BOM_Utf32.txt -Value $ null -Encoding UTF32'は、リトルエンディアンBOM、すなわち' FF FE 00 00'バイトシーケンスの_UTF-32を書き込みます。しかし、 'Get-FileEncoding'関数は' Unicode'を返します。一方、 '00 00 FE FF'バイトシーケンスは' UTF32'と認識されますが、[The Unicode Consortium](http://unicode.org/faq/utf_bom.html#BOM)のように_UTF-32ですが、ビッグエンディアン_ BOM。私が間違っている?エラーはどこですか? – JosefZ

関連する問題