【问题标题】:Adding BOM (unicode signature) while saving file in python在 python 中保存文件时添加 BOM(unicode 签名)
【发布时间】:2011-03-05 08:31:18
【问题描述】:

如何在 python 中保存文件时添加 BOM(unicode 签名):

file_old = open('old.txt', mode='r', encoding='utf-8')
file_new = open('new.txt', mode='w', encoding='utf-16-le')
file_new.write(file_old.read())

我需要将文件转换为utf-16-le + BOM。现在脚本运行良好,只是没有 BOM。

【问题讨论】:

  • for line in file_old: file_new.write(line) 的内存效率要高得多。为什么你不能使用已经做到这一点的众多软件中的任何一个?
  • 文本编辑器必须打开文件才能“另存为”,而且文件很大。其他软件是共享软件,或者很难找到。此外,我只是在学习python。逐行保存可能更有效,但也更复杂。
  • 如果文件非常大,那可能更有理由逐行转换它——尽管它很“复杂”。
  • 这也取决于脚本执行的频率。在我的情况下,文件为 100 mb,每月转换一次
  • @JohnMachin 实际上在这里得到了正确答案。

标签: python


【解决方案1】:

直接写在文件开头:

file_new.write('\ufeff')

【讨论】:

  • 谢谢,第一次想出这么简单的东西往往很难。
  • @Qiao:没那么简单。看我的回答。
  • @Ocaso:在 Python 2.x 上,'\ufeff' 之前缺少 u 可能会导致 Unicode 编码错误,特别是如果您通过 codecs.open() 显式设置编码。
【解决方案2】:

只需选择带有 BOM 的编码:

with codecs.open('outputfile.csv', 'w', 'utf-8-sig') as f:
   f.write('a,é')

(在 python 3 中,您可以删除 codecs.

【讨论】:

  • 或将codecs模块替换为io,它适用于python 2和3
  • 这个 2017 年的答案应该高于 2011 年的答案,
【解决方案3】:

对于带有 BOM 的 UTF-8,您可以使用:

def addUTF8Bom(filename):
  f = codecs.open(filename, 'r', 'utf-8')
  content = f.read()
  f.close()
  f2 = codecs.open(filename, 'w', 'utf-8')
  f2.write(u'\ufeff')
  f2.write(content)
  f2.close()

【讨论】:

  • 稳固!正在写入 Python 中的 .csv 文件,由于缺少 BOM,Excel 从未真正正确打开过该文件,现在一切都很好。谢谢!
【解决方案4】:

最好使用“编解码器”模块中的常量。

import codecs
f.write(codecs.BOM_UTF16_LE)

【讨论】:

  • 这实际上是错误的答案,原因有两个。首先,@JohnMachin 有写答案。不要使用'utf-16le',只需使用'utf-18'。其次(更重要的是)鉴于 OP 的代码设置了编码,这根本不会导致正确的行为。特别是在 Python3 上。您将bytes 提供给想要str 的东西。
  • 错误.. '正确',而不是'写'。当您在一个窗口中玩代码并在另一个窗口中编写 cmets 时,就会发生这种情况。
  • @Omnifarious:还有utf-16,而不是utf-18。 :p
  • @jamesdlin:哦,哎呀!我需要对这样的错别字做得更好。
  • 在 Python 3 中,使用(默认)文本模式 open,它会出错,因为你扔它字节,而不是字符串,正如 Omnifarious 已经暗示的那样。将字节转换为字符串,如f.write(str(codecs.BOM_UTF8)),在文件开头得到b'\xef\xbb\xbf'
【解决方案5】:

我遇到过类似的情况,第 3 方应用程序不接受我生成的文件,除非它有 BOM。

由于某些原因在 Python 2.7 中,以下内容对我不起作用

write('\ufeff')

我不得不用

代替它
write('\xff\xfe')

这和

是一样的

写(codecs.BOM_UTF16_LE)

我的最终输出文件是用以下代码编写的

import codecs
mytext = "Help me"

with open("c:\\temp\\myFile.txt", 'w') as f:
    f.write(codecs.BOM_UTF16_LE)
    f.write(mytext.encode('utf-16-le'))

这个答案对于最初的提问者可能没用,但它可能会帮助像我这样偶然发现这个问题的人

【讨论】:

    【解决方案6】:

    您认为为什么需要专门将其设为 UTF16LE?只需使用“utf16”作为编码,Python 将使用适当的 BOM 以您的字节顺序编写它,并且所有消费者需要被告知的是该文件是 UTF-16 ......这就是拥有 BOM 的全部意义。

    如果消费者坚持文件必须以 UTF16LE 编码,那么您就不需要 BOM。

    如果文件以您指定的方式编写,并且消费者使用 UTF16LE 编码打开它,他们将在文件的开头得到一个\ufeff,这是一个麻烦,需要忽略。

    【讨论】:

    • “为什么你认为你需要专门使它成为 UTF16LE?” winapi 可以非常讲究,它只接受带有 BOM 的 UCS-2 LE
    【解决方案7】:

    vitperov 对 python3 的回答:

    def add_utf8_bom(filename):
        with codecs.open(filename, 'r', 'utf-8') as f:
            content = f.read()
        with codecs.open(filename, 'w', 'utf-8') as f2:
            f2.write('\ufeff')
            f2.write(content)
    return
    

    【讨论】:

      【解决方案8】:

      试一试:

      def add_bom(file, bom: bytes):
          with open(file, 'r+b') as f:
              org_contents = f.read()
              f.seek(0)
              f.write(bom + org_contents)
      

      用法:

      import codecs
      
      ...
      
      file = 'test.txt'
      with open(file, 'w', encoding='utf-8') as f:  # without BOM
          f.write('A')
      
      add_bom(file, codecs.BOM_UTF16_LE)
      
      # TEST
      with open(file, 'rb') as f:
          print(f.read())  # b'\xff\xfeA'
      

      【讨论】:

        【解决方案9】:

        我添加 BOM 的方法是在文件开头写 ansi 字符“”,然后以 UTF-8 格式打开文件并写入所需数据:

        # Create file with ANSI encoding
        file= open("file.txt", "a", encoding="ansi", errors='ignore')
        # Add BOM at the beginning of the file BOM 0xEFBBBF
        file.write("")
        # Close file
        file.close()
        # Open file in UTF-8 and write data
        file= open("file.txt", "a", encoding="utf-8", errors='ignore')
        file.write("Write your data here, Enjoy!!")
        

        【讨论】:

          猜你喜欢
          • 2015-08-01
          • 2011-09-21
          • 1970-01-01
          • 2018-07-21
          • 2012-11-15
          • 2012-02-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多