我有以下问题:假设我有一个UTF8文件,其中每个特殊字符都由REPLACEMENT_CHARACTER“ ...”表示。文件的某些部分可能看起来像:
Das hier r?ckg.ngig ist das zu machenrêckgngig:ist bereits geamcht魏特尔·沃特(Weitere W.rter)更高级别的新世界[Zeile G.hte andGr��e]中的zwei
我编写了一个PowerShell脚本,用相应的特殊字符替换REPLACEMENT_CHARCTERS,例如“ a”,“ü”或“ß”。更正后的文本(也为UTF8)将如下所示:
[das hierrückgängigist das zu machenrückgängig:伊斯特·贝里斯·盖姆奇特魏特瑞·沃特(WeitereWörter)更高级别的einblödes麦芽汁einer ZeileGöhte和Größe中的zwei
问题是,我要导入文本的程序仅采用“西欧DOS(CP850)”编码的文件。顺便说一句,那是该程序已导出的原始编码,如果我没有打开文件,对其进行编辑并将其保存在UTF8中,则可以毫无问题地导入。所以这是发生了什么:
我从特定程序中将文件导出为“西欧DOS(CP850)”。 [注意:每个特殊字符在这里都有其自己的REPLACEMENT CHARACTER,因此导入将很容易进行并恢复特殊字符]
我用自己选择的编辑器打开了文件,编辑器自己检测到“ UTF8”,这是不正确的。我无法识别,编辑文件并将其另存为UTF8。 [现在每个特殊字符都具有相同的替换字符,它的[]
我已经意识到出了点问题,并编写了一个脚本,用UTF8中的正确特殊字符替换了每次出现的。 [我认为脚本执行此操作无关紧要,但如果这样,请询问]
我具有正确的UTF8文件,但是如您所记得,我必须将“西欧DOS(CP850)”导入到我的程序中。与导出文件相同的文件编码。此编码可确保每个特殊字符都有其自己的唯一REPLACEMENT_CHARACTER。那么如何通过PowerShell返回到此位置?
这里有更多信息。脚本读取我要更正的文件所在的行是:
$lines = get-content $file -encoding utf8 | select-string $SearchCharacter
该算法遍历每一行,并要求输入任何带有该字符的错误单词以进行更正,如果再次找到该单词,则跳过该单词。找到所有文件的所有更正之后,它将用以下行循环替换每个文件中每个“键”(错误的单词)到每个“值”(更正的单词)的出现:
foreach key ...
(Get-Content -encoding utf8 $file) -replace "$key", "$value" | Set-Content -encoding utf8 $file
我已经尝试做类似的事情:
foreach key ...
(Get-Content -encoding utf8 $file) -replace "$key", "$value" | Set-Content -encoding OEM $file
但是这导致使用“?”而不是正确的字符:
[Das hier r?ckg?ngig ist das zu machenr?ckg?ngig:ist bereits geamcht魏特雷·沃特(Weitere W?rter)Noch ein bl?des Wortzei in einer Zeile G?hte und Gr ?? e
关于如何从UTF8构建“西欧DOS(CP850)”文件的任何建议?
编辑:
此函数源自http://www.msdynamics.de/viewtopic.php?f=17&t=25726#p138532,解决了我的问题:
Function ConvertAndReplace_UTF8_OEM850
{
Param ([String]$path)
$path = resolve-path $path
$sourceEncoding = [System.Text.Encoding]::GetEncoding(65001)
$targetEncoding = [System.Text.Encoding]::GetEncoding(850)
$textfile = [System.IO.File]::ReadAllText($path, $sourceencoding)
[System.IO.File]::WriteAllText($path, $textfile, $targetencoding)
Write-host "Content in $path converted from UTF-8 to OEM850"
}
考虑到您已经固定了UTF-8编码文件(因此它包含原始字符),您要做的就是将代码转回到代码页850
(CP850):
如果系统的活动OEM代码页是 850
(用chcp
验证:]]]
Set-Content -NoNewline -Encoding OEM $file -Value (Get-Content -Raw -Encoding utf8 $file)
注意:
(Get-Content -encoding utf8 $file) | Set-Content -Encoding OEM $file
也可以,但是可能会更改所使用的换行符序列,并且即使原始文件中没有换行符,也总是追加尾随的换行符。
如果是不是
:在PowerShell [Core] 6+中,Set-Content
的-Encoding
参数现在接受代码页号:
Set-Content -NoNewline -Encoding 850 $file -Value (Get-Content -Raw -Encoding utf8 $file)
在Windows PowerShell(PowerShell最高为v5.1版本)中,需要直接使用.NET Framework:
[IO.File]::WriteAllText(
(Get-Content -Raw -Encoding utf8 $file),
[Text.Encoding]::GetEncoding(850)
)