2014-04-01 11 views
7

następującej sytuacji:lektura UTF-8 pliki poprawnie z PowerShell

  • skrypt PowerShell tworzy plik z kodowaniem UTF-8
  • Użytkownik może lub nie może edytować plik, ewentualnie utraty LM, ale należy zachować kodowanie jako UTF-8, i ewentualnie zmianę separatorów
  • Ten sam skrypt PowerShell odczytuje plik, dodaje trochę więcej treści i zapisuje je wszystkie jako UTF-8 z powrotem do tego samego pliku
  • ten można powtórzyć wiele razy

Z Get-Content i Out-File -Encoding UTF8 Mam problemy z odczytaniem go poprawnie. To potyka się o BOM, które napisała wcześniej (umieszczając go w treści, przerywając moje regex do analizowania), nie używa kodowania UTF-8, a nawet usuwa podziały wierszy w oryginalnej części treści.

Potrzebuję funkcji, która może odczytać dowolny plik z kodowaniem UTF-8, zignorować i usunąć BOM, a nie modyfikować treści. Co powinienem użyć?

Aktualizacja

Dodałem trochę skrypt testowy, który pokazuje, co staram się robić i co się dzieje, zamiast.

# Read data if exists 
$data = "" 
$startRev = 1; 
if (Test-Path test.txt) 
{ 
    $data = Get-Content -Path test.txt 
    if ($data -match "^[0-9-]{10} - r([0-9]+)") 
    { 
     $startRev = [int]$matches[1] + 1 
    } 
} 
Write-Host Next revision is $startRev 

# Define example data to add 
$startRev = $startRev + 10 
$newMsgs = "2014-04-01 - r" + $startRev + "`r`n`r`n" + ` 
    "Line 1`r`n" + ` 
    "Line 2`r`n`r`n" 

# Write new data back 
$data = $newMsgs + $data 
$data | Out-File test.txt -Encoding UTF8 

Po uruchomieniu go kilka razy, nowe odcinki powinny być dodawane do początku pliku, istniejąca zawartość nie powinna być w żaden sposób zmienione (obecnie traci podziały wiersza) i żadne dodatkowe nowe linie powinny zostać dodane na końcu pliku (zdarza się czasem).

Zamiast tego drugi przebieg daje błąd.

+0

nie jestem wielki z całego temacie kodowania, ale nie będzie musiał ponownie wstrzyknąć LM, jeśli zostanie usunięta, w celu poprawnego odczytania? Jestem nieco zdezorientowany tym pytaniem. Dlaczego chcesz usunąć zestawienie komponentów UTF-8? –

+0

Mój edytor tekstu jest głupi i usuwa go. W każdym razie nigdy nie wiesz, co redaktorzy tekstu robią z plikami UTF-8. Mój skrypt powinien być po prostu wystarczająco inteligentny, aby sobie z nim poradzić. Podobnie jak klasa StreamReader robi to całkiem dobrze. – ygoe

Odpowiedz

19

Jeżeli plik ma być UTF8, dlaczego nie spróbować, aby ją przeczytać dekodowania UTF-8:

Get-Content -Path test.txt -Encoding UTF8 
+2

Ponieważ, zgodnie z oficjalną dokumentacją, ten parametr nawet nie istnieje? Jak mogłem o tym wiedzieć? Dam temu szansę. – ygoe

3

Naprawdę JPBlanc ma rację. Jeśli chcesz, aby był on odczytany jako UTF8, określ, kiedy plik zostanie odczytany.

Na marginesie, tracisz tutaj formatowanie z materiałami [String] + [String]. Nie wspominając o tym, że twoje dopasowanie do wyrażenia regularnego nie działa. Sprawdź zmiany wyszukiwania regex i zmiany wprowadzone w $ newMsgs i sposób w jaki wysyłam twoje dane do pliku.

# Read data if exists 
$data = "" 
$startRev = 1; 
if (Test-Path test.txt) 
{ 
    $data = Get-Content -Path test.txt #-Encoding UTF8 
    if($data -match "\br([0-9]+)\b"){ 
     $startRev = [int]([regex]::Match($data,"\br([0-9]+)\b")).groups[1].value + 1 
    } 
} 
Write-Host Next revision is $startRev 

# Define example data to add 
$startRev = $startRev + 10 
$newMsgs = @" 
2014-04-01 - r$startRev`r`n`r`n 
    Line 1`r`n 
    Line 2`r`n`r`n 
"@ 

# Write new data back 
$newmsgs,$data | Out-File test.txt -Encoding UTF8 
+0

To poprawiło to. Sam regex był dobry, po prostu nie w jaki sposób go użyłem. Znalazłem to gdzie indziej ... Czy nie istnieje sposób bez duplikowania ciągu regex?Co robi przecinek w ostatnim poleceniu? Na początku widzę dużo dodatkowych nowych linii. – ygoe

+0

Znalazłem to, musi być tablicą. Niestety puste dane $ dla pierwszego uruchomienia powodują dodatkowe linie. - A dlaczego operator + dwóch ciągów zmienia ich rzeczywistą treść? To dla mnie nowość w każdym języku programowania. – ygoe

+0

Okay, to wina 'Get-Content'. Daje mi szereg linii, a nie pojedynczy ciąg wielowierszowy. To powoduje różnego rodzaju chaos. Przełączyłem się na '[System.IO.File] :: ReadAllText()' i '[System.IO.File] :: WriteAllText()' i teraz otrzymuję znacznie bardziej przewidywalne wyniki. – ygoe

0

Get-Content nie wydają się obsłużyć UTF-plików bez BOM w ogóle (jeśli pominąć Kodowanie flagą). System.IO.File.ReadLines wydaje się być alternatywą, przykłady:

PS C:\temp\powershellutf8> $a = Get-Content .\utf8wobom.txt 
PS C:\temp\powershellutf8> $b = Get-Content .\utf8wbom.txt 
PS C:\temp\powershellutf8> $a2 = Get-Content .\utf8wbom.txt -Encoding UTF8 
PS C:\temp\powershellutf8> $a 
ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ <== This doesnt seem to be right at all 
PS C:\temp\powershellutf8> $b 
ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ 
PS C:\temp\powershellutf8> $a2 
ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ 
PS C:\temp\powershellutf8> 
PS C:\temp\powershellutf8> $c = [IO.File]::ReadLines('.\utf8wbom.txt'); 
PS C:\temp\powershellutf8> $c 
ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ 
PS C:\temp\powershellutf8> $d = [IO.File]::ReadLines('.\utf8wobom.txt'); 
PS C:\temp\powershellutf8> $d 
ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ <== Works! 
Powiązane problemy