PowerShell: UTF-16 Little-Endian ohne BOM erzeugen

4. Januar 2017 17:35

Mit diesen Skripten (bzw. dem ersten, das zweite dient u.a. zum Vergleich der Parametereinstellungen) kann man aus einer Ausgangsdatei (hier im OEM 850 Zeichensatz, diese ggf. bei SourceEncoding anpassen) Unicodedateien als UTF-16 (auch UCS-2 genannt, wobei das neuere UTF-16 mehr Funktionalität bietet) in der hier eher ungewöhnlichen Variante ohne BOM (Byte Order Mark) und Little-Endian (LE) statt Big-Endian erzeugen.

Hier zwei Dateien, erzeugt mit den beiden Skriptvarianten unter Verwendung der gleichen Ausgangsdatei im HEX-Editor, links ohne BOM, rechts mit (FF FE).
HEXBOM.png

Gesteuert wird das Dateiformat dabei über die beiden Parameter (false = Little-Endian/true = Big-Endian, false = ohne BOM/true = mit BOM) in dieser Zeile
Code:
$targetEncoding = New-Object System.Text.UnicodeEncoding($false,$false)

.NET-Klasse: UnicodeEncoding Class in dieser Form UnicodeEncoding Constructor (Boolean, Boolean).

Optional kann hier auch noch ein dritter Parameter verwendet werden, der bei unzulässigen Kodierungen den Vorgang abbricht UnicodeEncoding Constructor (Boolean, Boolean, Boolean), dann also im Skript so anwenden:
Code:
$targetEncoding = New-Object System.Text.UnicodeEncoding($false,$false,$true)

Infos zu den anderen Grundlagen hier.

Little-Endian ohne BOM
Code:
        Function Convert_OEM850_UTF16LENOBOM
        {
        $args = resolve-path $args
        $WorkingFolder = Split-Path -Parent $args
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(850)
        # Litte Endian, no BOM
        $targetEncoding = New-Object System.Text.UnicodeEncoding($false,$false)
       
        $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($args) +"_UTF16LE" + [System.IO.Path]::GetExtension($args)
        $convertedfile = New-Item -path "$WorkingFolder\$convertedFileName" -type file
       
        $textfile = [System.IO.File]::ReadAllText($args, $sourceencoding)
        [System.IO.File]::WriteAllText($convertedfile, $textfile, $targetencoding)
       
        Write-host $args 'converted to' $convertedFileName
        }


Anzeige in Notepad++
UCS2LE.png


Little-Endian mit BOM
Code:
        Function Convert_OEM850_UTF16LEBOM
        {
        $args = resolve-path $args
        $WorkingFolder = Split-Path -Parent $args
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(850)
        # Litte Endian, with BOM
        $targetEncoding = New-Object System.Text.UnicodeEncoding($false,$true)
       
        $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($args) +"_UTF16LEBOM" + [System.IO.Path]::GetExtension($args)
        $convertedfile = New-Item -path "$WorkingFolder\$convertedFileName" -type file
       
        $textfile = [System.IO.File]::ReadAllText($args, $sourceencoding)
        [System.IO.File]::WriteAllText($convertedfile, $textfile, $targetencoding)
       
        Write-host $args 'converted to' $convertedFileName
        }


Anzeige in Notepad++
UCS2LEBOM.png
UTF16 LittleEndian, Little Endian BOM, Byte Order Mark
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Variante: Inhalt der Quelldatei austauschen

23. Januar 2017 13:44

Wenn man die Quelldatei selber in Unicode umwandeln möchte, geht das mit dieser Variante. Diese Funktion darf dann aber nur einmal auf die Quelldatei angewandt werden, ist also mehr etwas für automatisierte Batchverarbeitung. Da ja die BOM am Anfang fehlt, kann man leider nicht eindeutig abprüfen, ob die Datei schon im Unicode vorliegt, Skripte wie dieses liefern hier auch Fehlinformationen, und weitere Analysen wie hier sind zwar möglich, aber Disziplin beim Verarbeiten walten zu lassen scheint mir da doch einfacher zu sein :wink: .

Code:
         Function Exchange_OEM850_UTF16LENOBOM
            {
            $args = resolve-path $args
            $WorkingFolder = Split-Path -Parent $args
            $sourceEncoding = [System.Text.Encoding]::GetEncoding(850)
            # Litte Endian, no BOM
            $targetEncoding = New-Object System.Text.UnicodeEncoding($false,$false)
           
            $textfile = [System.IO.File]::ReadAllText($args, $sourceencoding)
            [System.IO.File]::WriteAllText($args, $textfile, $targetencoding)
           
            Write-host $args 'converted from OEM850 to UTF16LE without BOM'
            }