PowerShell: Textdateikonverter (OEM 850 u.a. Codepages/UTF))

Bild Tipps & Tricks zu den Dynamics NAV Versionen
Hier bitte keine Fragen stellen, sondern nur bereits vorhandene Tricks veröffentlichen.
Forumsregeln
ImpressumCommunity-KniggeNutzungsbedingungenDatenschutzrichtlinie
Hier bitte keine Fragen stellen, sondern nur bereits vorhandene Tricks veröffentlichen.

PowerShell: Textdateikonverter (OEM 850 u.a. Codepages/UTF))

Beitragvon Kowa » 23. Dezember 2014 18:32

Diese Funktionen werden zusammen mit dem Dateinamen in der PowerShell aufgerufen (bzw. in der nur im manuellen Betrieb einsetzbaren Dialogfenstervariante ohne Dateinamen) und erzeugen ein konvertierte umbenannte neue Datei mit der entsprechenden Kodierung im Ordner der Quelldatei. Nachtrag: Optional kann auch der Inhalt der Datei ausgetauscht werden.

codepageconverter1.png

Hier ist auch schön zu erkennen, wie sich die Dateigröße bei UTF-16 verdoppelt.
Bei UTF-8 dagegen nur minimaler Zuwachs, je nach Anzahl der Sonderzeichen (1051493 Byte bei ANSI bzw. OEM, 1051583 bei UTF-8)
codepageconverter2.png


Diese und weitere Nummern der Codepages für andere Konvertierungen: Code Page Identifiers
Diese Nummern werden im Skript in den beiden Zeilen mit $sourceEncoding= bzw. $targetEncoding= eingesetzt.
Die gängigen Codepages bzw. Unicodenummern sind in den Skripten unten enthalten, andere dort nach Bedarf eintragen. Wie bei allen Konvertierungen muss beachtet werden, dass Codepages nur einen begrenzten Zeichenvorrat von meist 256 Zeichen haben, und fehlende Zeichen (d.h. Zeichen in der Sourcecodepage, die in der Targetcodepage nicht vorhanden sind) je nach Konverter als Fragezeichen, Leerstelle,Unterstrich o.a., dargestellt werden. In Unicode kann dagegen jede Codepage konvertiert werden, umgekehrt funktioniert es aber auch nur dann vollständig, wenn die Codepage des Targetencodings alle Zeichen der Unicodequelle aufnehmen und darstellen kann.

Die Konvertierung wird via .NET-Framework durchgeführt:
Encoding.GetEncoding Method (String)
File.ReadAllText Method (String, Encoding)
File::WriteAllText Method (String, String, Encoding)
EncodingInfo.Name Property

Sonstige Links
Character Encoding
International Components for Unicode (ICU)
.NET Source Browser

OEM850 nach UTF-8
Code: Alles auswählen
  Function Convert_OEM850_UTF8
        {
        $args = resolve-path $args
        $WorkingFolder = Split-Path -Parent $args
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(850)
        $targetEncoding = [System.Text.Encoding]::GetEncoding(65001)
       
        $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($args) +"_UTF8" + [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
        }


Neu 04.10.2017 OEM850 nach UTF-8 mit "Datei öffnen"-Dialogfenster
Code: Alles auswählen
      Function Convert_OEM850_UTF8_Dlg
        {
        $ErrorActionPreference = "Stop"
        $PSDefaultParameterValues['*:ErrorAction']='Stop'
        Function Get-FileName($initialDirectory)
         {
         [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
   
        $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
        $OpenFileDialog.initialDirectory = $initialDirectory
        $OpenFileDialog.filter = "TXT (*.txt)|*.txt|CSV (*.csv)|*.csv|All files|*.*"
        $OpenFileDialog.ShowDialog() | Out-Null
        $OpenFileDialog.filename
         }
       
        $inputfile = Get-FileName -initialDirectory "$env:HOMEDRIVE\temp"
        if ($inputfile -eq "") {throw 'Please select a file'}

       
        $WorkingFolder = Split-Path -Parent $inputfile
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(850)
        $targetEncoding = [System.Text.Encoding]::GetEncoding(65001)
       
        $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($inputfile) +"_UTF8" + [System.IO.Path]::GetExtension($inputfile)
        $convertedfile = New-Item -path "$WorkingFolder\$convertedFileName" -type file
       
        $textfile = [System.IO.File]::ReadAllText($inputfile, $sourceencoding)
        [System.IO.File]::WriteAllText($convertedfile, $textfile, $targetencoding)
        Write-host $inputfile 'converted to' $convertedFileName
        }
   


OEM852 nach UTF-8 mit "Datei öffnen"-Dialogfenster (nur für Zentral-/Osteuropa (Central Eastern Europe (PL, CZ, RO, HU, RS, SK etc.))
Code: Alles auswählen
          Function Convert_OEM852_UTF8_Dlg
            {
            $ErrorActionPreference = "Stop"
            $PSDefaultParameterValues['*:ErrorAction']='Stop'
            Function Get-FileName($initialDirectory)
             {
             [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
       
            $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
            $OpenFileDialog.initialDirectory = $initialDirectory
            $OpenFileDialog.filter = "TXT (*.txt)|*.txt|CSV (*.csv)|*.csv|All files|*.*"
            $OpenFileDialog.ShowDialog() | Out-Null
            $OpenFileDialog.filename
             }
           
            $inputfile = Get-FileName -initialDirectory "$env:HOMEDRIVE\temp"
            if ($inputfile -eq "") {throw 'Please select a file'}

           
            $WorkingFolder = Split-Path -Parent $inputfile
            $sourceEncoding = [System.Text.Encoding]::GetEncoding(852)
            $targetEncoding = [System.Text.Encoding]::GetEncoding(65001)
           
            $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($inputfile) +"_UTF8" + [System.IO.Path]::GetExtension($inputfile)
            $convertedfile = New-Item -path "$WorkingFolder\$convertedFileName" -type file
           
            $textfile = [System.IO.File]::ReadAllText($inputfile, $sourceencoding)
            [System.IO.File]::WriteAllText($convertedfile, $textfile, $targetencoding)
            Write-host $inputfile 'converted to' $convertedFileName
            }
       


OEM850 nach UTF-16 (GetEncoding(1200) = Litte-Endian, für Big-Endian statt dessen GetEncoding(1201))
Code: Alles auswählen
        Function Convert_OEM850_UTF16
        {
        $args = resolve-path $args
        $WorkingFolder = Split-Path -Parent $args
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(850)
        $targetEncoding = [System.Text.Encoding]::GetEncoding(1200)
       
        $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($args) +"_UTF16" + [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
        }

Edit 04.01.2017: Für UTF-16 ohne BOM (Byte Order Mark) siehe Variante hier.

OEM850 nach ANSI1252
Code: Alles auswählen
  Function Convert_OEM850_ANSI1252
        {
        $args = resolve-path $args
        $WorkingFolder = Split-Path -Parent $args
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(850)
        $targetEncoding = [System.Text.Encoding]::GetEncoding(1252)
       
        $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($args) +"_ANSI1252" + [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
        }


OEM850 nach ISO 8859-1
Code: Alles auswählen
  Function Convert_OEM850_ISO88591
        {
        $args = resolve-path $args
        $WorkingFolder = Split-Path -Parent $args
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(850)
        $targetEncoding = [System.Text.Encoding]::GetEncoding(28591)
       
        $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($args) +"_ISO8859_1" + [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
        }


ANSI1252 nach UTF-8
Code: Alles auswählen
  Function Convert_ANSI1252_UTF8
        {
        $args = resolve-path $args
        $WorkingFolder = Split-Path -Parent $args
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(1252)
        $targetEncoding = [System.Text.Encoding]::GetEncoding(65001)
       
        $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($args) +"_UTF8" + [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
        }


ISO 8859-1 nach UTF-8
Code: Alles auswählen
  Function Convert_ISO88591_UTF8
        {
        $args = resolve-path $args
        $WorkingFolder = Split-Path -Parent $args
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(28591)
        $targetEncoding = [System.Text.Encoding]::GetEncoding(65001)
       
        $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($args) +"_UTF8" + [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
        }


ISO 8859-1 nach ANSI1252
Code: Alles auswählen
  Function Convert_ISO88591_ANSI1252
        {
        $args = resolve-path $args
        $WorkingFolder = Split-Path -Parent $args
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(28591)
        $targetEncoding = [System.Text.Encoding]::GetEncoding(1252)
       
        $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($args) +"_ANSI1252" + [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
        }


OEM850 nach EBCDIC500 (IBM Mainframes)
Code: Alles auswählen
    Function Convert_OEM850_EBCDIC500
            {
            $args = resolve-path $args
            $WorkingFolder = Split-Path -Parent $args
            $sourceEncoding = [System.Text.Encoding]::GetEncoding(850)
            $targetEncoding = [System.Text.Encoding]::GetEncoding(500)
           
            $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($args) +"_EBCDIC500" + [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
            }



Rückkonvertierung
Falls an den Unicodedateien Änderungen erfolgt sind, muss vor der Rückkonvertierung geprüft werden, ob alle Zeichen im Zeichenvorrat der Codepage vorhanden sind, da diese dort sonst nicht dargestellt werden können.

UTF-8 nach OEM850
Code: Alles auswählen
  Function Convert_UTF8_OEM850
        {
        $args = resolve-path $args
        $WorkingFolder = Split-Path -Parent $args
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(65001)
        $targetEncoding = [System.Text.Encoding]::GetEncoding(850)
       
        $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($args) +"_OEM850" + [System.IO.Path]::GetExtension($args)
        $convertedfile = New-Item -path "$WorkingFolder\$convertedFileName" -type file
       
        $textfile = [System.IO.File]::ReadAllText($args, $sourceencoding)
        # Normalization required if file contains different unicode encoding methods for special chars
        $textfile = $textfile.Normalize([Text.NormalizationForm]::FormC)
        [System.IO.File]::WriteAllText($convertedfile, $textfile, $targetencoding)
        Write-host $args 'converted to' $convertedFileName
        }


UTF-8 nach OEM852 (nur für zentral- oder osteuropäische NAV-Systeme außerhalb des Baltikums z.B. in Polen, Tschechien usw.)
Code: Alles auswählen
Function Convert_UTF8_OEM852
        {
        # Code page 852 is for Central-/Eastern European NAV Systems (Poland, Czech Rep. etc. ) without Baltic States
        $args = resolve-path $args
        $WorkingFolder = Split-Path -Parent $args
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(65001)
        $targetEncoding = [System.Text.Encoding]::GetEncoding(852)
       
        $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($args) +"_OEM852" + [System.IO.Path]::GetExtension($args)
        $convertedfile = New-Item -path "$WorkingFolder\$convertedFileName" -type file
       
        $textfile = [System.IO.File]::ReadAllText($args, $sourceencoding)
        # Normalization required if file contains different unicode encoding methods for special chars
        $textfile = $textfile.Normalize([Text.NormalizationForm]::FormC)
        [System.IO.File]::WriteAllText($convertedfile, $textfile, $targetencoding)
        Write-host $args 'converted to' $convertedFileName
        }


UTF-16 nach OEM850 (GetEncoding(1200) = Litte-Endian, für Big-Endian statt dessen GetEncoding(1201))
Code: Alles auswählen
    Function Convert_UTF16_OEM850
            {
            $args = resolve-path $args
            $WorkingFolder = Split-Path -Parent $args
            $sourceEncoding = [System.Text.Encoding]::GetEncoding(1200) # Little-Endian, for Big-Endian 1201
            $targetEncoding = [System.Text.Encoding]::GetEncoding(850)
           
            $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($args) +"_OEM850" + [System.IO.Path]::GetExtension($args)
            $convertedfile = New-Item -path "$WorkingFolder\$convertedFileName" -type file
           
            $textfile = [System.IO.File]::ReadAllText($args, $sourceencoding)
            # Normalization required if file contains different unicode encoding methods for special chars
            $textfile = $textfile.Normalize([Text.NormalizationForm]::FormC)
            [System.IO.File]::WriteAllText($convertedfile, $textfile, $targetencoding)
            Write-host $args 'converted to' $convertedFileName
            }


ANSI1252 nach OEM850
Code: Alles auswählen
      Function Convert_ANSI1252__OEM850
            {
            $args = resolve-path $args
            $WorkingFolder = Split-Path -Parent $args
            $sourceEncoding = [System.Text.Encoding]::GetEncoding(1252)
            $targetEncoding = [System.Text.Encoding]::GetEncoding(850)
           
            $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($args) +"_OEM850" + [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
            }

UTF-8 nach ANSI1252
Code: Alles auswählen
  Function Convert_UTF8_ANSI1252
        {
        $args = resolve-path $args
        $WorkingFolder = Split-Path -Parent $args
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(65001)
        $targetEncoding = [System.Text.Encoding]::GetEncoding(1252)
       
        $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($args) +"_ANSI1252" + [System.IO.Path]::GetExtension($args)
        $convertedfile = New-Item -path "$WorkingFolder\$convertedFileName" -type file
       
        $textfile = [System.IO.File]::ReadAllText($args, $sourceencoding)
        # Normalization required if file contains different unicode encoding methods for special chars
        $textfile = $textfile.Normalize([Text.NormalizationForm]::FormC)
        [System.IO.File]::WriteAllText($convertedfile, $textfile, $targetencoding)
        Write-host $args 'converted to' $convertedFileName
        }


UTF-8 nach ISO 8859-1
Code: Alles auswählen
  Function Convert_UTF8_ISO88591
        {
        $args = resolve-path $args
        $WorkingFolder = Split-Path -Parent $args
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(65001)
        $targetEncoding = [System.Text.Encoding]::GetEncoding(28591)
       
        $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($args) +"_ISO8859_1" + [System.IO.Path]::GetExtension($args)
        $convertedfile = New-Item -path "$WorkingFolder\$convertedFileName" -type file
       
        $textfile = [System.IO.File]::ReadAllText($args, $sourceencoding)
        # Normalization required if file contains different unicode encoding methods for special chars
        $textfile = $textfile.Normalize([Text.NormalizationForm]::FormC)
        [System.IO.File]::WriteAllText($convertedfile, $textfile, $targetencoding)
        Write-host $args 'converted to' $convertedFileName
        }

Tags: unicode code page file charset converter UTF16 UTF8 UTF-16 UTF-8 UCS UCS-2
Gruß, Kai

Frage beantwortet? Schreibe bitte [Gelöst] vor den Titel des ersten Beitrags.
Bitte erst suchen, dann fragen. Bitte beachte den kleinen Community-Knigge.
Kein Support per PN, Mail, Messenger oder Telefon! Dafür ist dieses Forum da.

Download: Dynamics NAV Object Text Explorer (Alternativlink). MVP Alumni
Benutzeravatar
Kowa
Moderator
Moderator
 
Beiträge: 7835
Registriert: 17. Juni 2005 17:32
Wohnort: Bremen
Realer Name: Kai Kowalewski
Arbeitsort: Osterholz-Scharmbeck
Bezug zu Microsoft Dynamics: Microsoft Partner
Microsoft Dynamics Produkt: Microsoft Dynamics 365
Microsoft Dynamics Version: BC, NAV 2018 bis Navision 2.01

Pfadänderung bei der konvertierten Datei

Beitragvon Kowa » 29. Januar 2016 14:16

Ich habe die Funktionen leicht geändert, damit die konvertierte Datei im Ordner der Quelldatei und nicht im aktuellen PowerShell-Pfad abgelegt wird. So ist es bei den meisten Anwendungsfällen wohl praktischer.
Falls die Datei wie bisher am alten Ort erzeugt werden soll, nur diese geänderte Zeile
Code: Alles auswählen
$convertedfile = New-Item -path "$WorkingFolder\$convertedFileName" -type file

durch die bisherige
Code: Alles auswählen
$convertedfile = New-Item -path ".\$convertedFileName" -type file

ersetzen, diese neue
Code: Alles auswählen
$WorkingFolder = Split-Path -Parent $args

kann dann gelöscht werden (stört aber auch nicht :wink: ) .
Gruß, Kai

Frage beantwortet? Schreibe bitte [Gelöst] vor den Titel des ersten Beitrags.
Bitte erst suchen, dann fragen. Bitte beachte den kleinen Community-Knigge.
Kein Support per PN, Mail, Messenger oder Telefon! Dafür ist dieses Forum da.

Download: Dynamics NAV Object Text Explorer (Alternativlink). MVP Alumni
Benutzeravatar
Kowa
Moderator
Moderator
 
Beiträge: 7835
Registriert: 17. Juni 2005 17:32
Wohnort: Bremen
Realer Name: Kai Kowalewski
Arbeitsort: Osterholz-Scharmbeck
Bezug zu Microsoft Dynamics: Microsoft Partner
Microsoft Dynamics Produkt: Microsoft Dynamics 365
Microsoft Dynamics Version: BC, NAV 2018 bis Navision 2.01

Normalisierung bei Unicode in Codepagekonvertierung

Beitragvon Kowa » 5. August 2017 17:05

Bei den Rückkonvertierungskripten, in denen UTF-16 oder UTF-8 in eine Codepage überführt werden, habe ich noch diese Zeilen eingefügt.
Code: Alles auswählen
# Normalization required if file contains different unicode encoding methods for special chars
$textfile = $textfile.Normalize([Text.NormalizationForm]::FormC)


Da es in Unicode verschiedene Methoden gibt, Sonderzeichen zu kodieren (entweder in einem Codepoint mit dem kompletten Sonderzeichen oder in bis zu drei verschiedenen Codepoints, also Basisbuchstabe + diakritische(s) Zeichen) kommt es sonst bei letzterem Verfahren zu dem Effekt, dass in der Codepagedatei statt einem Zeichen dann 2 oder 3 Zeichen stehen.

Unicode Normalization Forms

Wenn die Ausgangsdatei aus verschiedenen Quellen und/oder Benutzern zusammengestückelt wurde (das kann auch eine zusammengebastelte Exceldatei sein, die als Unicodetext gespeichert wurde - das ist dann im Format UTF-16 Little Endian mit Byte Order Mark (BOM) -, muss man besonders oft mit diesem Effekt rechnen :roll: ). Wenn man dagegen eine solche Exceldatei als Nicht-Unicodetext oder Text(MS-DOS) abspeichert, kommt es hier in der Textdatei auch schnell zum Zeichensalat mit Basisbuchstabe + Fragezeichen, weil viele diakritische Zeichen (Diakritika) in Codepages einzeln nicht enthalten sind.

Ein Beispiel mit einem Zeichen, welches sowohl zusammen als auch getrennt in Codepage 850 oder 1252 darstellbar ist:
Ein ã würde dann, je nachdem wie es erfasst wurde (Tastatur, Copy&Paste aus dem Web etc.) entweder wieder als ã oder als a~ in der konvertierten Codepagedatei erscheinen. Falls die Codepage das diakritische Zeichen gar nicht enthält, wird man hier hinter dem Basisbuchstaben auch nur noch ein Fragezeichen vorfinden.

Durch die Normalisierung mit FormC werden bei Sonderzeichen alle Stellen mit "Buchstabe + diakritisches Zeichen" überall in der Datei einheitlich jeweils in einem Codepoint zusammengefasst, welcher das komplette Sonderzeichen darstellt.
NormalizationForm Enumeration
String.Normalize-Methode
MultiByteToWideChar function (stringapiset.h)

Im Anhang ist eine Testdatei im UTF-16 mit identischen Wörtern, obere Zeilen mit einem Codepoint bei den Sonderzeichen, untere mit zwei Codepoints.
Notepad++ weist übrigens auf die zweite Verfahren durch zwei halbe Cursorsprünge statt einem bei den Sonderzeichen hin.
Der einfache Editor von Windows 7 ist bei der UTF-16-Datei hier sogar informativer als der von Windows 10, die Variante mit zwei Codepoints hat hier einen kleineren Font :-) .
CodepointTestWin7.png
CodepointTestWin7.png (17.13 KiB) 6540-mal betrachtet


Links das Konvertierungsergebnis von UTF-16 in Codepage 1252 mit ausgeführter Normalisierung, rechts ohne.
codepointtest.png
Dateianhänge
Codepointtest.zip
Beispieldatei
(263 Bytes) 275-mal heruntergeladen
Gruß, Kai

Frage beantwortet? Schreibe bitte [Gelöst] vor den Titel des ersten Beitrags.
Bitte erst suchen, dann fragen. Bitte beachte den kleinen Community-Knigge.
Kein Support per PN, Mail, Messenger oder Telefon! Dafür ist dieses Forum da.

Download: Dynamics NAV Object Text Explorer (Alternativlink). MVP Alumni
Benutzeravatar
Kowa
Moderator
Moderator
 
Beiträge: 7835
Registriert: 17. Juni 2005 17:32
Wohnort: Bremen
Realer Name: Kai Kowalewski
Arbeitsort: Osterholz-Scharmbeck
Bezug zu Microsoft Dynamics: Microsoft Partner
Microsoft Dynamics Produkt: Microsoft Dynamics 365
Microsoft Dynamics Version: BC, NAV 2018 bis Navision 2.01

Variante mit "Datei öffnen"-Dialogfenster

Beitragvon Kowa » 4. Oktober 2017 11:00

Ich habe im Startbeitrag für die erste Funktion (von OEM850 nach UTF8) noch eine neue Skriptvariante mit "Datei öffnen"-Dialogfenster hinzugefügt, das klappt natürlich analog auch bei allen anderen Funktionen/Codepages dort :-) .

Bei dieser Variante gibt man also beim Funktionsaufruf nicht die Quelldatei als Pfad mit, sondern ruft diese nur mit dem Namen auf und dann öffnet sich das übliche Fenster, in dem die Datei dann ausgewählt werden kann. Der Vorgabepfad ist hierbei "C:\Temp", mit Filtermöglichkeiten auf txt- und csv-Dateien bzw. alle Dateien, nach Belieben im Skript anpassbar. Die konvertierte Datei wird wie bisher im Ordner der Quelldatei erzeugt.

OpenFileDlg.png


OEM850 nach UTF8
Code: Alles auswählen
      Function Convert_OEM850_UTF8_Dlg
        {
        $ErrorActionPreference = "Stop"
        $PSDefaultParameterValues['*:ErrorAction']='Stop'
        Function Get-FileName($initialDirectory)
         {
         [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
   
        $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
        $OpenFileDialog.initialDirectory = $initialDirectory
        $OpenFileDialog.filter = "TXT (*.txt)|*.txt|CSV (*.csv)|*.csv|All files|*.*"
        $OpenFileDialog.Title = "Please select an OEM850 file"
        $OpenFileDialog.ShowDialog() | Out-Null
        $OpenFileDialog.filename
         }
       
        $inputfile = Get-FileName "C:\temp" # This is the default path in OpenFile window. Use whatever you like :-)
        if ($inputfile -eq "") {throw 'Please select a file'}

       
        $WorkingFolder = Split-Path -Parent $inputfile
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(850)
        $targetEncoding = [System.Text.Encoding]::GetEncoding(65001)
       
        $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($inputfile) +"_UTF8" + [System.IO.Path]::GetExtension($inputfile)
        $convertedfile = New-Item -path "$WorkingFolder\$convertedFileName" -type file
       
        $textfile = [System.IO.File]::ReadAllText($inputfile, $sourceencoding)
        [System.IO.File]::WriteAllText($convertedfile, $textfile, $targetencoding)
        Write-host $inputfile 'converted to' $convertedFileName
        }
   

Shift_JIS nach UTF8
Code: Alles auswählen
  Function Convert_ShiftJIS_UTF8_Dlg
        {
        $ErrorActionPreference = "Stop"
        $PSDefaultParameterValues['*:ErrorAction']='Stop'
        Function Get-FileName($initialDirectory)
         {
         [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
   
        $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
        $OpenFileDialog.initialDirectory = $initialDirectory
        $OpenFileDialog.filter = "TXT (*.txt)|*.txt|CSV (*.csv)|*.csv|All files|*.*"
        $OpenFileDialog.Title = "Please select a Shift_JIS file"
        $OpenFileDialog.ShowDialog() | Out-Null
        $OpenFileDialog.filename
         }
       
        $inputfile = Get-FileName "C:\temp" # This is the default path in OpenFile window. Use whatever you like :-)
        if ($inputfile -eq "") {throw 'Please select a file'}

       
        $WorkingFolder = Split-Path -Parent $inputfile
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(932)
        $targetEncoding = [System.Text.Encoding]::GetEncoding(65001)
       
        $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($inputfile) +"_UTF8" + [System.IO.Path]::GetExtension($inputfile)
        $convertedfile = New-Item -path "$WorkingFolder\$convertedFileName" -type file
       
        $textfile = [System.IO.File]::ReadAllText($inputfile, $sourceencoding)
        [System.IO.File]::WriteAllText($convertedfile, $textfile, $targetencoding)
        Write-host $inputfile 'converted to' $convertedFileName
        }

UTF-8 nach UTF-16
Code: Alles auswählen
     Function Convert_UTF8_UTF16_Dlg
        {
        $ErrorActionPreference = "Stop"
        $PSDefaultParameterValues['*:ErrorAction']='Stop'
        Function Get-FileName($initialDirectory)
         {
         [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
   
        $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
        $OpenFileDialog.initialDirectory = $initialDirectory
        $OpenFileDialog.filter = "TXT (*.txt)|*.txt|CSV (*.csv)|*.csv|All files|*.*"
        $OpenFileDialog.Title = "Please select a UTF-8 file"
        $OpenFileDialog.ShowDialog() | Out-Null
        $OpenFileDialog.filename
         }
       
        $inputfile = Get-FileName "C:\temp" # This is the default path in OpenFile window. Use whatever you like :-)
        if ($inputfile -eq "") {throw 'Please select a file'}

       
        $WorkingFolder = Split-Path -Parent $inputfile
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(65001)
        $targetEncoding = [System.Text.Encoding]::GetEncoding(1200)
       
        $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($inputfile) +"_UTF16" + [System.IO.Path]::GetExtension($inputfile)
        $convertedfile = New-Item -path "$WorkingFolder\$convertedFileName" -type file
       
        $textfile = [System.IO.File]::ReadAllText($inputfile, $sourceencoding)
        [System.IO.File]::WriteAllText($convertedfile, $textfile, $targetencoding)
        Write-host $inputfile 'converted to' $convertedFileName
        }
   

Rückkonvertierung
UTF-16 nach OEM850
Code: Alles auswählen
  Function Convert_UTF16_OEM850_Dlg
            {
        $ErrorActionPreference = "Stop"
        $PSDefaultParameterValues['*:ErrorAction']='Stop'
        Function Get-FileName($initialDirectory)
         {
         [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
   
        $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
        $OpenFileDialog.initialDirectory = $initialDirectory
        $OpenFileDialog.filter = "TXT (*.txt)|*.txt|CSV (*.csv)|*.csv|All files|*.*"
        $OpenFileDialog.ShowDialog() | Out-Null
        $OpenFileDialog.filename
         }
       
        $inputfile = Get-FileName -initialDirectory "$env:HOMEDRIVE\temp"
        if ($inputfile -eq "") {throw 'Please select a file'}

            $WorkingFolder = Split-Path -Parent $inputfile
           
            $sourceEncoding = [System.Text.Encoding]::GetEncoding(1200) # Little-Endian, for Big-Endian 1201
            $targetEncoding = [System.Text.Encoding]::GetEncoding(850)
           
            $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($inputfile) +"_OEM850" + [System.IO.Path]::GetExtension($inputfile)
            $convertedfile = New-Item -path "$WorkingFolder\$convertedFileName" -type file
           
            $textfile = [System.IO.File]::ReadAllText($inputfile, $sourceencoding)
            # Normalization required if file contains different unicode encoding methods for special chars
            $textfile = $textfile.Normalize([Text.NormalizationForm]::FormC)
            [System.IO.File]::WriteAllText($convertedfile, $textfile, $targetencoding)
            Write-host $inputfile 'converted to' $convertedFileName
            }

ANSI1252 nach OEM850
Code: Alles auswählen
      Function Convert_ANSI1252_OEM850_Dlg
        {
        $ErrorActionPreference = "Stop"
        $PSDefaultParameterValues['*:ErrorAction']='Stop'
        Function Get-FileName($initialDirectory)
         {
         [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
   
        $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
        $OpenFileDialog.initialDirectory = $initialDirectory
        $OpenFileDialog.filter = "TXT (*.txt)|*.txt|CSV (*.csv)|*.csv|All files|*.*"
        $OpenFileDialog.Title = "Please select an OEM850 file"
        $OpenFileDialog.ShowDialog() | Out-Null
        $OpenFileDialog.filename
         }
       
        $inputfile = Get-FileName "C:\temp" # This is the default path in OpenFile window. Use whatever you like :-)
        if ($inputfile -eq "") {throw 'Please select a file'}

       
        $WorkingFolder = Split-Path -Parent $inputfile
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(1252)
        $targetEncoding = [System.Text.Encoding]::GetEncoding(850)
       
        $convertedFileName = [System.IO.Path]::GetFileNameWithoutExtension($inputfile) +"_OEM850" + [System.IO.Path]::GetExtension($inputfile)
        $convertedfile = New-Item -path "$WorkingFolder\$convertedFileName" -type file
       
        $textfile = [System.IO.File]::ReadAllText($inputfile, $sourceencoding)
        [System.IO.File]::WriteAllText($convertedfile, $textfile, $targetencoding)
        Write-host $inputfile 'converted to' $convertedFileName
        }
        Convert_ANSI1252_OEM850_Dlg


Links:
https://web.archive.org/web/20171115155907/http://www.workingsysadmin.com/open-file-dialog-box-in-powershell/
https://blogs.technet.microsoft.com/heyscriptingguy/2014/07/09/handling-errors-the-powershell-way/

Tags: Shift-JIS Shift_JIS Shift JIS charset file conversion konverter
Gruß, Kai

Frage beantwortet? Schreibe bitte [Gelöst] vor den Titel des ersten Beitrags.
Bitte erst suchen, dann fragen. Bitte beachte den kleinen Community-Knigge.
Kein Support per PN, Mail, Messenger oder Telefon! Dafür ist dieses Forum da.

Download: Dynamics NAV Object Text Explorer (Alternativlink). MVP Alumni
Benutzeravatar
Kowa
Moderator
Moderator
 
Beiträge: 7835
Registriert: 17. Juni 2005 17:32
Wohnort: Bremen
Realer Name: Kai Kowalewski
Arbeitsort: Osterholz-Scharmbeck
Bezug zu Microsoft Dynamics: Microsoft Partner
Microsoft Dynamics Produkt: Microsoft Dynamics 365
Microsoft Dynamics Version: BC, NAV 2018 bis Navision 2.01

Re: Normalisierung bei Unicode in Codepagekonvertierung

Beitragvon Kowa » 10. November 2017 11:42

Kowa hat geschrieben: […]kommt es sonst bei letzterem Verfahren zu dem Effekt, dass in der Codepagedatei statt einem Zeichen dann 2 oder 3 Zeichen stehen.

Leider nimmt NAV beim Dateiexport in Unicode offensichtlich auch keine Normalisierung vor, wenn in der Quelle das Verfahren Basisbuchstabe + diakritisches Zeichen angewendet wurde.
Kopiert man bspw.
Москва́
aus https://de.wikipedia.org/wiki/Moskau
wird das á im Client noch korrekt als ein Zeichen dargestellt, aber bei Textencoding::UTF8 bzw. UTF16 in eine Datei so exportiert:
Москвa´

Bei Export über XMLports wiederum wird korrekt normalisiert :roll: .
Gruß, Kai

Frage beantwortet? Schreibe bitte [Gelöst] vor den Titel des ersten Beitrags.
Bitte erst suchen, dann fragen. Bitte beachte den kleinen Community-Knigge.
Kein Support per PN, Mail, Messenger oder Telefon! Dafür ist dieses Forum da.

Download: Dynamics NAV Object Text Explorer (Alternativlink). MVP Alumni
Benutzeravatar
Kowa
Moderator
Moderator
 
Beiträge: 7835
Registriert: 17. Juni 2005 17:32
Wohnort: Bremen
Realer Name: Kai Kowalewski
Arbeitsort: Osterholz-Scharmbeck
Bezug zu Microsoft Dynamics: Microsoft Partner
Microsoft Dynamics Produkt: Microsoft Dynamics 365
Microsoft Dynamics Version: BC, NAV 2018 bis Navision 2.01

Inhalt der Datei austauschen

Beitragvon Kowa » 23. August 2019 13:47

Wenn man keine neue Datei erzeugen möchte, sondern den Inhalt der Quelldatei austauschen möchte, vereinfachen sich die Skripte.
Hier für einen Austausch
OEM 850 nach UTF-8
Code: Alles auswählen
 Function ConvertAndReplace_OEM850_UTF8
        {
        $args = resolve-path $args
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(850)
        $targetEncoding = [System.Text.Encoding]::GetEncoding(65001)
        $textfile = [System.IO.File]::ReadAllText($args, $sourceencoding)
        [System.IO.File]::WriteAllText($args, $textfile, $targetencoding)
        Write-host "Content in $args converted from OEM850 to UTF-8"
        }


ANSI 1252 nach UTF-8

Code: Alles auswählen
 Function ConvertAndReplace_ANSI1252_UTF8
        {
        $args = resolve-path $args
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(1252)
        $targetEncoding = [System.Text.Encoding]::GetEncoding(65001)
        $textfile = [System.IO.File]::ReadAllText($args, $sourceencoding)
        [System.IO.File]::WriteAllText($args, $textfile, $targetencoding)
        Write-host "Content in $args converted from ANSI1252 to UTF-8"
        }
Gruß, Kai

Frage beantwortet? Schreibe bitte [Gelöst] vor den Titel des ersten Beitrags.
Bitte erst suchen, dann fragen. Bitte beachte den kleinen Community-Knigge.
Kein Support per PN, Mail, Messenger oder Telefon! Dafür ist dieses Forum da.

Download: Dynamics NAV Object Text Explorer (Alternativlink). MVP Alumni
Benutzeravatar
Kowa
Moderator
Moderator
 
Beiträge: 7835
Registriert: 17. Juni 2005 17:32
Wohnort: Bremen
Realer Name: Kai Kowalewski
Arbeitsort: Osterholz-Scharmbeck
Bezug zu Microsoft Dynamics: Microsoft Partner
Microsoft Dynamics Produkt: Microsoft Dynamics 365
Microsoft Dynamics Version: BC, NAV 2018 bis Navision 2.01


Zurück zu NAV Tipps & Tricks

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast