将 BOM 添加到 UTF-8 文件
Posted
技术标签:
【中文标题】将 BOM 添加到 UTF-8 文件【英文标题】:Adding BOM to UTF-8 files 【发布时间】:2011-03-08 19:58:51 【问题描述】:我正在搜索(没有成功)一个脚本,它可以作为批处理文件使用,如果没有 BOM,我可以在 UTF-8 文本文件前面添加一个 BOM。
它所用的语言(perl、python、c、bash)和它所运行的操作系统对我来说都不重要。我可以使用各种计算机。
我发现很多脚本可以做相反的事情(剥离 BOM),这听起来有点傻,因为许多 Windows 程序如果没有物料清单。
我错过了显而易见的事情吗?
谢谢!
【问题讨论】:
【参考方案1】:我使用 'file' 命令和 ICU 的 'uconv' 命令编写了这个 addbom.sh。
#!/bin/sh
if [ $# -eq 0 ]
then
echo usage $0 files ...
exit 1
fi
for file in "$@"
do
echo "# Processing: $file" 1>&2
if [ ! -f "$file" ]
then
echo Not a file: "$file" 1>&2
exit 1
fi
TYPE=`file - < "$file" | cut -d: -f2`
if echo "$TYPE" | grep -q '(with BOM)'
then
echo "# $file already has BOM, skipping." 1>&2
else
( mv "$file" "$file"~ && uconv -f utf-8 -t utf-8 --add-signature < "$file~" > "$file" ) || ( echo Error processing "$file" 1>&2 ; exit 1)
fi
done
编辑:在mv
参数周围添加了引号。感谢@DirkR,很高兴这个脚本很有帮助!
【讨论】:
绝对完美!比我自带的好多了。非常感谢。 "$@" 比 $* 这里好。这将保留带空格的参数(在 windows+cygwin 上很有用) mv 也需要 "" 否则它不适用于带有空格的路径名。不错的脚本,谢谢! 出现了一个问题,关于如何在子目录上使用它……你可以这样使用它:find . -type f -print0 | xargs -0 addbom.sh
它将为所有子目录调用 addbom.sh 脚本。【参考方案2】:
我找到的最简单的方法是
#!/usr/bin/env bash
#Add BOM to the new file
printf '\xEF\xBB\xBF' > with_bom.txt
# Append the content of the source file to the new file
cat source_file.txt >> with_bom.txt
我知道它使用外部程序 (cat)...但它会在 bash 中轻松完成这项工作
在 osx 上测试过,但也可以在 linux 上运行
请注意,它假定文件还没有 BOM (!)
【讨论】:
【参考方案3】:(根据 yingtedhttps://***.com/a/9815107/1260896 回答)
要向所有以“foo-”开头的文件添加 BOM,您可以使用sed
。 sed
可以选择进行备份。
sed -i '1s/^\(\xef\xbb\xbf\)\?/\xef\xbb\xbf/' foo-*
如果您确定已经没有 BOM,您可以简化命令:
sed -i '1s/^/\xef\xbb\xbf/' foo-*
确保您需要设置 UTF-8,因为即 UTF-16 不同(否则检查 How can I re-add a unicode byte order marker in linux?)
【讨论】:
对于 UTF-8 使用\xef\xbb\xbf
;对于 UTF-16 little-endian 使用 \xff\xfe
;对于 UTF-16 大端使用 \xfe\xff
。见w3.org/International/questions/qa-byte-order-mark
这对我在 Mac 上不起作用。命令行sed -i '1s/^/\xef\xbb\xbf/' temp.csv
给了我sed: 1: "temp.csv": undefined label 'emp.csv'
@PerLundberg 您可以尝试进行故障排除.. 尝试sed '1s/asdfasdfasdf//' blah.csv
缺少 -i 将使其非常安全,因为它使输入文件保持不变并将结果输出到控制台。该行应查看第一行,搜索字符串 asdfasdfasdf 并将其替换为空,即删除该字符串。然后尝试将其设置为^adsfasdfasdf
^
标记行的开头,也许这由于某种原因导致了问题。也许你需要使用带有 sed 的开关来让它使用 ^
就像也许 -E 虽然我不知道。
@PerlLundberg 我在 macOS 10.13 上遇到了同样的问题,经过大量的摆弄,我发现 sed -i '' $'1s/^/\xef\xbb\xbf/' foo-*
有效【参考方案4】:
作为对 Yaron U. 解决方案的改进,您可以在一行中完成所有操作:
printf '\xEF\xBB\xBF' | cat - source.txt > source-with-bom.txt
cat -
位表示连接到 source.txt
的前面,从打印命令中输入的内容。在 OS X 和 Ubuntu 上测试。
【讨论】:
【参考方案5】:我觉得很简单。假设文件总是 UTF-8(你没有检测到编码,你知道编码):
阅读前三个字符。将它们与 UTF-8 BOM 序列进行比较(***说它是 0xEF、0xBB、0xBF)。 如果相同,请将它们打印到新文件中,然后将其他所有内容从原始文件复制到新文件中。 如果不同,请先打印 BOM,然后打印三个字符,然后再打印从原始文件到新文件的所有其他内容。
在 C 语言中,fopen/fclose/fread/fwrite 应该足够了。
【讨论】:
【参考方案6】:我已经根据Steven R. Loomis 的代码创建了一个脚本。 https://github.com/Vdragon/addUTF-8bomb
结帐https://github.com/Vdragon/C_CPP_project_template/blob/development/Tools/convertSourceCodeToUTF-8withBOM.bash.sh 以使用此脚本为例。
【讨论】:
【参考方案7】:在 VBA 访问中:
Dim name As String
Dim tmpName As String
tmpName = "tmp1.txt"
name = "final.txt"
Dim file As Object
Dim finalFile As Object
Set file = CreateObject("Scripting.FileSystemObject")
Set finalFile = file.CreateTextFile(name)
'Add BOM
finalFile.Write Chr(239)
finalFile.Write Chr(187)
finalFile.Write Chr(191)
'transfer text from tmp to final file:
Dim tmpFile As Object
Set tmpFile = file.OpenTextFile(tmpName, 1)
finalFile.Write tmpFile.ReadAll
finalFile.Close
tmpFile.Close
file.DeleteFile tmpName
【讨论】:
以上是关于将 BOM 添加到 UTF-8 文件的主要内容,如果未能解决你的问题,请参考以下文章