将BOM添加到UTF-8文件

时间:2010-06-27 13:14:37

标签: utf-8 batch-file scripting byte-order-mark

我正在搜索(没有成功)一个脚本,它可以作为一个批处理文件使用,如果没有一个脚本,允许我在前面添加一个带有BOM的UTF-8文本文件。

它所写的语言(perl,python,c,bash)和它所使用的操作系统都不重要。我可以使用各种计算机。

我发现有很多脚本可以反过来(剥离BOM),这听起来有点傻,因为许多Windows程序在读取UTF-8文本文件时如果没有BOM。

我是否想念显而易见的事?

谢谢!

8 个答案:

答案 0 :(得分:41)

我使用'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,很高兴这个脚本非常有用!

答案 1 :(得分:26)

我找到的最简单方法是

#!/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(!)

答案 2 :(得分:12)

(基于https://stackoverflow.com/a/9815107/1260896的回答yingted)

要将BOM添加到以“foo-”开头的所有文件,您可以使用sedsed可以选择进行备份。

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?

答案 3 :(得分:4)

我觉得很简单。假设文件总是 UTF-8(你没有检测到编码,你知道编码):

阅读前三个字符。将它们与UTF-8 BOM序列进行比较(维基百科说它是0xEF,0xBB,0xBF)。 如果相同,则在新文件中打印它们,然后将原始文件中的所有其他内容复制到新文件中。 如果不同,首先打印BOM,然后打印三个字符,然后将原始文件中的所有内容打印到新文件中。

在C中,fopen / fclose / fread / fwrite就足够了。

答案 4 :(得分:3)

作为Yaron U.解决方案的改进,您可以在一行上完成所有操作:

printf '\xEF\xBB\xBF' | cat - source.txt > source-with-bom.txt

cat -位指示将连接到source.txt前面的内容从print命令中传递。在OS X和Ubuntu上进行了测试。

答案 5 :(得分:0)

答案 6 :(得分:0)

在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

答案 7 :(得分:-1)

我以为我不必自己编写这么简单的东西,但是因为我还需要做一些字符集转换,所以这里是:

#!/usr/bin/python
import os
import sys
import codecs

INPUT_ENCODING = 'utf-8'       # utf-8 without BOM
OUTPUT_ENCODING = 'utf-8-sig'  # utf-8 with BOM

if len(sys.argv) == 1:
    print 'Usage:\n\t%s <filename.txt>' % sys.argv[0]
    sys.exit(-1)

output_file = os.path.splitext(os.path.split(sys.argv[1])[-1])[0]
fin = codecs.open(sys.argv[1], 'rb', encoding=INPUT_ENCODING)
fout = codecs.open(output_file + '_utf8bom.txt', 'wb', encoding=OUTPUT_ENCODING)
fout.write(fin.read())
fin.close()
fout.close()

print 'done'

仅使用原始文件名称,即:

# utf8bom_add.py myfilename.txt

如果您要从无BOM表UTF-8进行转换,请将INPUT_ENCODING设置为适当的值。

如果您需要,您还可以检查物料清单是否已存在,以便您不会将其添加两次。