2014-04-01 115 views
7

以下情況:讀UTF-8文件正確使用PowerShell

  • PowerShell腳本創建使用UTF-8編碼文件
  • 用戶可以或不可以編輯的文件,可能失去了BOM,但應保持編碼爲UTF-8,並可能改變行分隔符
  • 同樣的PowerShell腳本讀取文件,增加了一些更多的內容,這一切寫爲UTF-8回同一個文件
  • 這可以迭代很多次

With Get-Content and Out-File -Encoding UTF8我在正確閱讀時遇到問題。它在之前編寫的BOM(將其放入內容中,打破了我的解析正則表達式)的絆腳石,不使用UTF-8編碼,甚至刪除原始內容部分中的換行符。

我需要一個函數,它可以讀取任何UTF-8編碼的文件,忽略並刪除BOM並不修改內容。我應該使用什麼?

我添加了一個小的測試腳本,顯示我想要做什麼更新發生吧。

# 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 

運行了幾次之後,新的章節應該被添加到文件的開頭,現有的內容不應該以任何方式改變(目前失去換行符),應添加任何額外的新行在文件末尾(似乎有時會發生)。

相反,第二次運行給我一個錯誤。

+0

我不是偉大的整個編碼話題,但你不會有重新注入BOM,如果它被刪除,爲了正確閱讀它?我對這個問題有點困惑。爲什麼要刪除UTF-8 BOM? –

+0

我的文本編輯器很笨,並刪除它。無論如何,你永遠不知道文本編輯器用UTF-8文件做什麼。我的腳本應該足夠聰明來處理它。像StreamReader類一樣,它很好。 – ygoe

回答

19

如果文件被認爲是UTF8你爲什麼不試着去閱讀它解碼UTF8:

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

因爲根據官方文檔,這個參數甚至不存在?我怎麼知道這件事?我會試一試。 – ygoe

3

真的JPBlanc是正確的。如果您希望它讀取爲UTF8,則指定在讀取文件時。

在一個側面說明,你在這裏丟失格式與[String] + [String]的東西。更不用說你的正則表達式匹配不起作用了。查看正則表達式搜索更改以及對$ newMsgs所做的更改以及將數據輸出到文件的方式。

# 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

改善了它。正則表達式本身很好,但不是我如何使用它。我發現在別的地方...沒有重複正則表達式字符串的方式嗎?另外,最後一個命令中的逗號是做什麼的?最初我在最後看到很多額外的新行。 – ygoe

+0

發現它,必須是一個數組。不幸的是,第一次運行的空數據會導致額外的行數。 - 爲什麼兩個字符串的+運算符會改變它們的實際內容?這對我來說在任何編程語言中都是新的。 – ygoe

+0

好吧,它是'Get-Content'的錯。它給了我一個行數組,而不是一個多行字符串。這會導致各種混亂。我已經切換到'[System.IO.File] :: ReadAllText()'和'[System.IO.File] :: WriteAllText()',現在我得到了更多可預測的結果。 – ygoe

0

Get-Content似乎無法處理沒有BOM的UTF文件(如果您省略了Encoding標誌)。 System.IO.File.ReadLines似乎是一個另類,例:

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! 
相關問題