如何用PowerShell脚本将多编码文件转为无BOM的UTF-8并保留重音?
解决ANSI转UTF-8无BOM时重音字符乱码问题
原脚本的问题在于使用Get-Content时未指定正确编码,PowerShell默认的编码检测逻辑对无BOM的ANSI文件(如Windows-1252)处理不当,导致重音字符在读取阶段就已损坏,最终写入UTF-8时出现乱码。
修改后的解决方案脚本
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False) $source = "你的源文件夹路径" $destination = "你的目标文件夹路径" # 检测文件编码的工具函数 function Get-FileEncoding { param([string]$Path) $bytes = Get-Content -Path $Path -Encoding Byte -ReadCount 4 -TotalCount 4 # 检测UTF-8 BOM if ($bytes[0] -eq 0xef -and $bytes[1] -eq 0xbb -and $bytes[2] -eq 0xbf) { return [System.Text.Encoding]::UTF8 } # 检测Unicode BOM elseif ($bytes[0] -eq 0xff -and $bytes[1] -eq 0xfe) { return [System.Text.Encoding]::Unicode } # 检测大端Unicode BOM elseif ($bytes[0] -eq 0xfe -and $bytes[1] -eq 0xff) { return [System.Text.Encoding]::BigEndianUnicode } # 无BOM默认使用Windows-1252(常见ANSI编码,若为其他ANSI编码可替换编码页,比如GB2312用936) else { return [System.Text.Encoding]::GetEncoding(1252) } } foreach ($file in Get-ChildItem $source -Recurse -Force) { if ($file.PSIsContainer) { continue } # 构建目标文件路径,避免字符串替换的路径格式问题 $relativePath = $file.FullName.Substring($source.Length) $targetPath = Join-Path -Path $destination -ChildPath $relativePath $targetDir = Split-Path -Path $targetPath -Parent # 创建目标文件夹(不存在则创建) if (-not (Test-Path -Path $targetDir)) { New-Item -Path $targetDir -ItemType Directory -Force | Out-Null } try { # 获取文件编码并读取内容 $fileEncoding = Get-FileEncoding -Path $file.FullName $content = Get-Content -Path $file.FullName -Encoding $fileEncoding -Raw # 写入UTF-8无BOM格式文件 [System.IO.File]::WriteAllText($targetPath, $content, $Utf8NoBomEncoding) } catch { Write-Host "处理文件失败: $($file.FullName),错误信息: $_" } }
关键优化点
- 精准编码检测:通过读取文件前4字节判断BOM类型,无BOM文件默认使用Windows-1252编码(可根据实际ANSI编码替换编码页,如中文ANSI用936)。
- 指定编码读取:用
Get-Content -Encoding $fileEncoding确保重音字符被正确解析,避免默认编码导致的乱码。 - 高效读取写入:使用
-Raw参数一次性读取文件内容,提升处理效率同时避免逐行读取的编码异常。 - 路径处理优化:用
Substring和Join-Path替代字符串替换,避免不同系统下的路径格式错误。
内容的提问来源于stack exchange,提问作者Jax22
相关产品推荐
相关产品推荐

