如何使用 .bat 格式批量将 Unicode 文件转换成 ANSI 文件?

3

我是一个完全的.bat编程初学者,请耐心等待:

我一直在尝试将从科学仪器收集的大量Unicode文件转换为ANSI格式。此外,我需要将所有这些文件转换为.txt文件。

现在,第二部分相当简单——我曾经使用“批量重命名实用程序”进行操作,并且到目前为止,我已经能够使其工作,我想。

第一部分应该很简单,而且我找到了多个类似的问题,但它们似乎都是针对powershell单个文件或以特定编码结束的长时间讨论。 有一个问题与我的完全匹配, 但是尝试他们建议的代码后,只有一半的文件可以正常传输,另一半则以无意义的代码形式出现。我一直在使用以下代码:

for %%F in (*.001) do ren "*SS.001" "*SS1.001"

for %%F in (*.001) do type "%%F" >"%%~nF.txt"

然后删除/移动多余的文件。

我以前曾经成功地手工转换过这些文件(左边),但是当前的编码似乎失败了(右边): 手工编码与程序编码的文件并排比较

我的问题是:

  1. 我从仪器中获得的单个文件是否可能处于多种编码(部分UTF-8,部分UTF-16)中,这会破坏我的程序(或更可能的是,我使用的编码太小了)?如果是这种情况,我会理解为什么像平方和度符号这样的特殊字符会被破坏,但不是数据,它只是数字。
  2. 我的代码中是否有一些明显的错字导致这种奇怪的错误?
  3. 如果错误可能嵌入在我正在使用的unicode(8 vs 16 vs 32)或ANSI(1252 vs ???)中,我该如何检查?
  4. 我该如何修复这个代码使其工作?

如果有更好的问题需要问或需要添加其他信息,请告诉我。谢谢!


1
ANSI 编码无法支持编码所有的 Unicode 字符。大多数仅支持表示 256 个 Unicode 字符。因此,如果您有俄罗斯字符但将其编码为 ANSI 代码页 1252(西欧),则会丢失信息。 - Mark Tolonen
文件中存储的值是否可能是二进制而不是Unicode?如果是,那么没有标准工具可以帮助您。 - Mark Ransom
1
你怎么知道它们是“Unicode”文件?这并不是真正的事情。文件需要编码。Microsoft Notepad所谓的“Unicode”实际上是小端UTF-16编码。你的屏幕截图看起来像Notepad,所以只需选择“文件,另存为...”,然后查看Microsoft默认的文件格式是什么。你知道目标格式的编码吗?“ANSI”是Microsoft称之为默认本地化编码的名称。在美国版本的Windows上,它是Windows-1252 - Mark Tolonen
1个回答

1

我的仪器产生的单个文件是否可能使用多种编码(部分UTF-8,部分UTF-16),并且这会干扰我的程序(或更可能的是我使用的编码太小了)?

我认为一个单独的文件不可能包含多种编码。

我的代码中是否有一些明显的拼写错误导致了这个奇怪的错误?

cmd环境可以轻松处理不同的代码页,但它在处理多字节编码和字节顺序标记时会遇到困难。事实上,在尝试读取以UCS-2 LE返回的WMI结果时,这是一个常见问题。虽然存在一种纯批处理解决方法来清理WMI结果,但它不幸地不能与其他每种编码普遍适用。

如果错误可能嵌入在我使用的unicode(8 vs 16 vs 32)或ANSI(1252 vs ???)中,我该如何检查?我该如何修复这段代码使其正常工作?

.NET在处理未知编码的文件时表现更好。当StreamReader类读取第一个字符时,它会读取BOM并自动检测文件编码。我知道你希望避免使用PowerShell解决方案,但是PowerShell确实是访问IO方法以透明方式处理这些文件的最简单方法。
然而,有一种简单的方法可以将PowerShell混合代码整合到批处理脚本中。将其保存为.bat扩展名,然后查看它是否符合你的要求。
<# : batch portion
@echo off & setlocal

powershell -noprofile "iex (${%~f0} | out-string)"
goto :EOF
: end batch / begin PowerShell hybrid #>

function file2ascii ($infile, $outfile) {

    # construct IO streams for reading and writing
    $reader = new-object IO.StreamReader($infile)
    $writer = new-object IO.StreamWriter($outfile, [Text.Encoding]::ASCII)

    # copy infile to ASCII encoded outfile
    while (!$reader.EndOfStream) { $writer.WriteLine($reader.ReadLine()) }

    # output summary
    $encoding = $reader.CurrentEncoding.WebName
    "{0} ({1}) -> {2} (ascii)" -f (gi $infile).Name, $encoding, (gi $outfile).Name

    # Garbage collection
    foreach ($stream in ($reader, $writer)) { $stream.Dispose() }
}

# loop through all .001 files and apply file2ascii()
gci *.001 | %{
    $outfile = "{0}\{1}.txt" -f $_.Directory, $_.BaseName
    file2ascii $_.FullName $outfile
}

虽然使用get-contentout-file命令可以简化此过程,但上述IO流方法将避免您将整个数据文件加载到内存中,如果您的任何数据文件很大,则会受益。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接