2012-02-02 13 views
23

Actualmente estoy trabajando en alguna operación de búsqueda y reemplazo que estoy tratando de automatizar con PowerShell. Lamentablemente, reconocí ayer que tenemos diferentes codificaciones de archivos en nuestra base de código (UTF8 y ASCII). Debido a que estamos realizando estas operaciones de búsqueda y reemplazo en una rama diferente, no puedo cambiar las codificaciones de los archivos en esta etapa.Archivo externo de PowerShell: evitar cambios de codificación

Si estoy ejecutando las siguientes líneas, cambia todos los archivos a UCS-2 Little Eindian aunque mi codificación predeterminada de powershell está establecida en iso-8859-1 (Europa occidental (Windows)).

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

¿Hay una manera de prevenir PowerShell desde cambiar la codificación del archivo?

Respuesta

31

Out-File tiene una codificación predeterminada a menos anulado con el -Encoding parámetro:

Lo que he hecho de resolver esto es para tratar de obtener la codificación del archivo original mediante la lectura de tratar de leer es byte order mark y que sirva como el -Encoding valor del parámetro

Aquí hay un ejemplo en el que se procesan varias rutas de archivos de texto, se obtiene la codificación original, se procesa el contenido y se vuelve a escribir en el archivo con la codificación original.

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 
} 

actualización Este es un ejemplo de conseguir la codificación del archivo original utilizando la clase StreamReader. El ejemplo lee los primeros 3 bytes del archivo para que la propiedad CurrentEncoding se configure en función del resultado de su rutina interna de detección de listas de materiales.

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

El parámetro detectEncodingFromByteOrderMarks detecta la codificación por mirando a los tres primeros bytes de la corriente. Automáticamente reconoce UTF-8, Unicode little-endian y texto Unicode big-endian si el archivo comienza con las marcas de orden de bytes apropiadas. De lo contrario, se utiliza el UTF8Encoding. Consulte el método Encoding.GetPreamble para obtener más información sobre .

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

ya he pensado en ello, pero tiene que haber una manera más fácil, ¿no es así? Pero eso funciona para mí ahora. Gracias Andy! – Pete

+2

@Pete Tendrás que obtener la codificación. No hay un cmdlet que lo obtenga por usted. Actualicé mi respuesta agregando un enfoque diferente. Ambas formas usan la detección de BOM. –

+0

'Set-Content -Path BOM_Utf32.txt -Value $ null -Encoding UTF32' escribe _UTF-32, little-endian_ BOM es decir' FF FE 00 00' secuencia de bytes. Sin embargo, la función 'Get-FileEncoding' devuelve' Unicode'. Por otro lado, la secuencia de bytes '00 00 FE FF' se reconoce como' UTF32' pero de acuerdo con [El Consorcio Unicode] (http://unicode.org/faq/utf_bom.html#BOM) esto es _UTF-32, big-endian_ BOM. ¿Me equivoco? ¿Dónde está el error? – JosefZ

Cuestiones relacionadas