【问题标题】:Is there a way to check encoding of files through Install script or batch?有没有办法通过安装脚本或批处理检查文件的编码?
【发布时间】:2021-01-13 14:23:06
【问题描述】:

有没有办法通过安装脚本/Windows 批处理/PowerShell 在传递文件进行转换之前检查文件是否为 UTF-8?

作为背景,我目前正在使用 C++ 中的 Visual Studio 2005(升级到 Visual Studio 2017)开发旧版(日语)Windows 软件。

我正在处理使 GUI 能够显示和输入汉字的要求。因此决定使用 UNICODE 进行项目/解决方案编码。

由于该项目最初使用多字节,为了向后兼容 UNICODE,我决定将配置文件(ini、dat、保存文件)编码为 UTF-8,因为这些文件也被 Web 应用程序引用。

软件的主要部分现在已经完成并且可以工作了,我还有最后一个问题 - 推出版本升级安装程序。

在此安装程序中(使用安装脚本),我需要将保存文件(以前以 SHIFT-JIS 编码,因为这些保存文件包含日语文本)更新为 UTF-8。

我已经在以下几行中创建了一个批处理文件,它将 SHIFT-JIS 转换为 UTF-8,该文件在安装程序的最后部分调用并在转换后被删除。

@echo off
:: Shift_JIS -> UTF-8
setlocal enabledelayedexpansion
for %%f in ("%~dp0\savedfiles\*.sav") do (
    echo %%~ff| findstr /l /e /i ".sav"
      if !ERRORLEVEL! equ 0 (
        powershell -nop -c "&{[IO.File]::WriteAllText($args[1], [IO.File]::ReadAllText($args[0], [Text.Encoding]::GetEncoding(932)))}" \"%%~ff"  \"%%~ff" 
      )
)

但是,这样做的问题是,当用户 (1) 升级、(2) 卸载(.sav 文件被故意留下)和 (3) 重新安装软件时,保存文件会被双重重新编码并导致软件崩溃。 ((1)升级时更新UTF-8日文字符,(3)重新安装后变为垃圾字符。)

【问题讨论】:

  • 字节集合并没有什么特别之处,它应该表示表示它使用何种编码的文本。您必须以其他方式跟踪这一点。
  • 对于答案,我建议查看A: How to detect UTF-8 in plain C?,特别是建议在文件开头添加标识符的部分。在您的情况下,您需要选择通常不会开始您的 .sav 文件的内容。如果你提前考虑,你可以选择一个字节序列,上面写着“这个文件有一个标题”,然后是一个字节或字节序列,上面写着“我是 UTF-8”——因为未来的变化可能需要更多的标识符。 (这应该是重复的吗?知道替代方案是日语可能会引发其他答案。)
  • 谢谢@JaMiT,我已经更新了这个问题。实际上,我最初创建了一个类似的简单 .exe 文件来检查 UTF-8 BOM,并返回简单的真或假,但不幸的是,BOM 会导致 Web 应用程序部分出现显示问题。我认为这篇文章是原因:w3.org/International/questions/qa-utf8-bom.en.html。我将在线程中探索其他解决方案,这很有帮助。
  • @Wolf 是的,您还必须更新读取数据的应用程序代码以说明标头。
  • 一些离题提示:%~dp0 扩展为始终以反斜杠结尾的文件夹路径。出于这个原因,永远不要将%~dp0 与带有文件/文件夹名称或通配符模式的附加\ 连接起来,因为这会导致完整的参数字符串中有两个反斜杠,Windows 稍后必须更正。尽管可能,但不要将f 用作循环变量,尤其是在同时使用~f 之类的修饰符时。有足够多的其他字符不是可用作循环变量的修饰符。使用if not errorlevel 1 代替if !ERRORLEVEL! equ 0 时不需要延迟扩展。

标签: c++ windows batch-file unicode installscript


【解决方案1】:

如果您正在升级,那么所有当前文件都应该在 Shift-JIS 中。即使您在某些情况下同时保留 Shift-JIS 和 UTF-8 文件,那么您只需要处理 2 种类型的编码。因此,您可以通过检查文件是否不是有效的 UTF-8 来解决此问题,然后它是 Shift-JIS。当然,在极少数情况下,这仍然会受到错误检测,但否则它可能对您的用例有好处

默认情况下,读取文本文件时使用best-fit fallback or replacement fallback 处理程序。我们可以更改为exception fallback,这样如果 Shift-JIS 文件以 UTF-8 格式打开,它将引发异常

try {
    $t = [IO.File]::ReadAllText($f, [Text.Encoding]::GetEncoding(65001, `
         (New-Object Text.EncoderExceptionFallback), `
         (New-Object Text.DecoderExceptionFallback)))
} catch {
    # File is not UTF-8, reopen as Shift-JIS
    $t = [IO.File]::ReadAllText($f, [Text.Encoding]::GetEncoding(932))
}

# Write the file as UTF-8
[IO.File]::WriteAllText($f, $t)

最好遍历文件并在 PowerShell 中进行转换。如果您确实需要使用批处理文件,请将所有内容包装在 *.ps1 文件中并从批处理中调用它

【讨论】:

  • ASCII 和 UTF-8 的区别是人为的。 ASCII 有效的 UTF-8。
  • @IInspectable 我知道。我的意思是 Shift-JIS 中可能存在一些也是有效 UTF-8 的序列,但我无法确认,因为我不知道 Shift-JIS 如何对值进行编码
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-17
  • 2017-12-14
  • 1970-01-01
  • 2022-11-23
  • 1970-01-01
相关资源
最近更新 更多