如何在Python中读取可以保存为ansi或unicode的文件?

2023-12-08

我必须编写一个脚本来支持读取可以保存为 Unicode 或 Ansi 的文件(使用 MS 的记事本)。

我的文件中没有任何编码格式的指示,如何支持这两种编码格式? (一种在不提前知道格式的情况下读取文件的通用方法)。


MS 记事本为用户提供了 4 种编码选择,用笨拙且令人困惑的术语表示:

“Unicode”是UTF-16,以little-endian 书写。 “Unicode big endian”是UTF-16,写作big-endian。在这两种 UTF-16 情况下,这意味着将写入适当的 BOM。使用utf-16解码这样的文件。

“UTF-8”是UTF-8;记事本明确写入“UTF-8 BOM”。使用utf-8-sig解码这样的文件。

“ANSI”令人震惊。这是 MS 术语,意思是“此计算机上的默认旧编码是什么”。

以下是我所知道的 Windows 编码及其所使用的语言/脚本的列表:

cp874  Thai
cp932  Japanese 
cp936  Unified Chinese (P.R. China, Singapore)
cp949  Korean 
cp950  Traditional Chinese (Taiwan, Hong Kong, Macao(?))
cp1250 Central and Eastern Europe 
cp1251 Cyrillic ( Belarusian, Bulgarian, Macedonian, Russian, Serbian, Ukrainian)
cp1252 Western European languages
cp1253 Greek 
cp1254 Turkish 
cp1255 Hebrew 
cp1256 Arabic script
cp1257 Baltic languages 
cp1258 Vietnamese
cp???? languages/scripts of India  

如果该文件是在正在读取该文件的计算机上创建的,那么您可以通过以下方式获取“ANSI”编码:locale.getpreferredencoding()。否则,如果您知道它来自哪里,则可以指定要使用的编码(如果它不是 UTF-16)。如果失败的话,猜猜。

小心使用codecs.open()在 Windows 上读取文件。文档说:“”“注意 即使未指定二进制模式,文件也始终以二进制模式打开。这样做是为了避免由于使用 8 位值编码而导致数据丢失。这意味着在读取和写入时不会自动转换 '\n'。""" 这意味着您的行将以\r\n你需要/想要把它们脱掉。

把它们放在一起:

使用所有 4 种编码选项保存的示例文本文件在记事本中如下所示:

The quick brown fox jumped over the lazy dogs.
àáâãäå

这是一些演示代码:

import locale

def guess_notepad_encoding(filepath, default_ansi_encoding=None):
    with open(filepath, 'rb') as f:
        data = f.read(3)
    if data[:2] in ('\xff\xfe', '\xfe\xff'):
        return 'utf-16'
    if data == u''.encode('utf-8-sig'):
        return 'utf-8-sig'
    # presumably "ANSI"
    return default_ansi_encoding or locale.getpreferredencoding()

if __name__ == "__main__":
    import sys, glob, codecs
    defenc = sys.argv[1]
    for fpath in glob.glob(sys.argv[2]):
        print
        print (fpath, defenc)
        with open(fpath, 'rb') as f:
            print "raw:", repr(f.read())
        enc = guess_notepad_encoding(fpath, defenc)
        print "guessed encoding:", enc
        with codecs.open(fpath, 'r', enc) as f:
            for lino, line in enumerate(f, 1):
                print lino, repr(line)
                print lino, repr(line.rstrip('\r\n'))

这是使用命令在 Windows“命令提示符”窗口中运行时的输出\python27\python read_notepad.py "" t1-*.txt

('t1-ansi.txt', '')
raw: 'The quick brown fox jumped over the lazy dogs.\r\n\xe0\xe1\xe2\xe3\xe4\xe5
\r\n'
guessed encoding: cp1252
1 u'The quick brown fox jumped over the lazy dogs.\r\n'
1 u'The quick brown fox jumped over the lazy dogs.'
2 u'\xe0\xe1\xe2\xe3\xe4\xe5\r\n'
2 u'\xe0\xe1\xe2\xe3\xe4\xe5'

('t1-u8.txt', '')
raw: '\xef\xbb\xbfThe quick brown fox jumped over the lazy dogs.\r\n\xc3\xa0\xc3
\xa1\xc3\xa2\xc3\xa3\xc3\xa4\xc3\xa5\r\n'
guessed encoding: utf-8-sig
1 u'The quick brown fox jumped over the lazy dogs.\r\n'
1 u'The quick brown fox jumped over the lazy dogs.'
2 u'\xe0\xe1\xe2\xe3\xe4\xe5\r\n'
2 u'\xe0\xe1\xe2\xe3\xe4\xe5'

('t1-uc.txt', '')
raw: '\xff\xfeT\x00h\x00e\x00 \x00q\x00u\x00i\x00c\x00k\x00 \x00b\x00r\x00o\x00w
\x00n\x00 \x00f\x00o\x00x\x00 \x00j\x00u\x00m\x00p\x00e\x00d\x00 \x00o\x00v\x00e
\x00r\x00 \x00t\x00h\x00e\x00 \x00l\x00a\x00z\x00y\x00 \x00d\x00o\x00g\x00s\x00.
\x00\r\x00\n\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\r\x00\n\x00'
guessed encoding: utf-16
1 u'The quick brown fox jumped over the lazy dogs.\r\n'
1 u'The quick brown fox jumped over the lazy dogs.'
2 u'\xe0\xe1\xe2\xe3\xe4\xe5\r\n'
2 u'\xe0\xe1\xe2\xe3\xe4\xe5'

('t1-ucb.txt', '')
raw: '\xfe\xff\x00T\x00h\x00e\x00 \x00q\x00u\x00i\x00c\x00k\x00 \x00b\x00r\x00o\
x00w\x00n\x00 \x00f\x00o\x00x\x00 \x00j\x00u\x00m\x00p\x00e\x00d\x00 \x00o\x00v\
x00e\x00r\x00 \x00t\x00h\x00e\x00 \x00l\x00a\x00z\x00y\x00 \x00d\x00o\x00g\x00s\
x00.\x00\r\x00\n\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\r\x00\n'
guessed encoding: utf-16
1 u'The quick brown fox jumped over the lazy dogs.\r\n'
1 u'The quick brown fox jumped over the lazy dogs.'
2 u'\xe0\xe1\xe2\xe3\xe4\xe5\r\n'
2 u'\xe0\xe1\xe2\xe3\xe4\xe5'

需要注意的事项:

(1) “mbcs”是一种文件系统伪编码,与解码完全无关contents文件数量。在默认编码为的系统上cp1252,它就像latin1(啊啊啊!!);见下文

>>> all_bytes = "".join(map(chr, range(256)))
>>> u1 = all_bytes.decode('cp1252', 'replace')
>>> u2 = all_bytes.decode('mbcs', 'replace')
>>> u1 == u2
False
>>> [(i, u1[i], u2[i]) for i in xrange(256) if u1[i] != u2[i]]
[(129, u'\ufffd', u'\x81'), (141, u'\ufffd', u'\x8d'), (143, u'\ufffd', u'\x8f')
, (144, u'\ufffd', u'\x90'), (157, u'\ufffd', u'\x9d')]
>>>

(2) chardet非常擅长检测基于非拉丁文字(中文/日文/韩文、西里尔文、希伯来文、希腊文)的编码,但不太擅长检测基于拉丁文的编码(西欧/中欧/东欧、土耳其语、越南语)并且不擅长完全不懂阿拉伯语。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在Python中读取可以保存为ansi或unicode的文件? 的相关文章

随机推荐

  • 登录失败:用户名未知或密码错误。访问其他服务器时出错

    我正在使用登录凭据访问其他服务器 我的问题是 如果我最初运行代码 它会将错误显示为 Logon failure unknown user name or bad password 但是如果我尝试通过命令提示符连接到服务器一次后运行代码 然后
  • JavaScript 按位掩码

    这个问题类似于这另一个问题 但是 我想了解为什么会这样 下面的代码 console log parseInt 0xdeadbeef 16 parseInt 0x000000ff 16 toString 16 console log pars
  • Python 3.7.3 无意中安装在 Mac OS 10.15.1 上 - 现在包含在 Xcode Developer Tools 11.2 中?

    我昨天决定对 Mac 操作系统进行全新安装 例如 擦除整个磁盘并重新安装操作系统 我使用的是 Macbook Air 2018 我全新安装了 Mac OS 10 15 1 由于我之前的 Python 环境非常混乱 所以我进行了全新安装 我希
  • python 中的批量字符串替换?

    假设我有一个如下所示的字符串 str The yquick cbrown bfox Yjumps over the ulazy dog 您会注意到字符串中的很多位置都有一个 符号 后跟一个字符 例如 y 和 c 我需要用字典中的适当值替换这
  • json.org 上使用的生成铁路图的工具[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 我喜欢的语法铁路图 on json org这是 BNF 语言的图形表示 我还没有找到任何工具可以产生如此雄辩的结果 任何人都可以识别用于生成这些图表
  • Chrome 不会删除会话 cookie

    我正在尝试在 javascript 中设置会话 cookie 如下所示 document cookie name alex path 但即使我退出浏览器并再次启动 Chrome 也不会删除它 我检查了 Firefox 和 Opera 它们都
  • Django 1.2 会话丢失

    我以前问过类似的问题 但我做了更多研究 这次迭代应该有点不同 似乎有几个 SO 用户在单个视图中注册和登录用户时遇到了问题 但还没有真正得到解决 问题是我在单个 Django 视图中注册 验证和登录用户 对于大多数用户来说这很好 但对于其他
  • 如何调试涉及 Classes.pas 中 ThreadProc 崩溃的设计时包卸载崩溃?

    我不确定如何追踪以下崩溃 当卸载我公司内部使用的设计时包时会发生这种情况 这是我们的代码 因此这是我们要修复的错误 而不是第三方组件供应商的问题 似乎涉及到一个线程 但由于它发生在 Classes pas 中的 Function Threa
  • 使用 pyodbc 在 Access 中处理日期时出现“参数太少”错误

    我正在使用带有 pyodbc 导入的 Python 我使用的是 Microsoft Office 2013 64 位 我正在尝试查询 accdb 数据库以选择范围内的不同日期并将它们分配给游标 以便我可以将它们附加到列表中 我的 Acces
  • 正则表达式从字符捕获到第一个句点

    我的正则表达式字符串看起来像 您的订单 Q 111 111 1111 账单金额为 100 50 美元 如何提取订单号 即 和第一个 之间的字符串 Q 111 111 1111 我试过了 但它正在捕获最后一个点字符 我确信 我需要使用非贪婪匹
  • Linux 是否对页目录和页表使用自映射?

    我只是问这个问题 因为我很好奇 Linux 内核是如何工作的 根据http i web i u tokyo ac jp edu training ss lecture new documents Lectures 02 VirtualMem
  • 是/否消息框始终返回是 - VB.Net

    我正在尝试消息框 并尝试了一个简单的是 否消息框 所以我写了这段简单的代码 但是 无论我按下哪个按钮 chc 变量始终返回为 1 我提供了代码 所以你可能会看到我做错了什么 这可能是严重错误的 If MsgBoxResult Yes The
  • 将多个类绑定到单个变量

    在使用 Tailwind 和实用程序优先的 css 方法时 我经常发现需要将多个类绑定到单个变量 例如 要设置输入表单的样式 我需要添加border red color red等 如果有错误 在 Vue 中是否有一种漂亮而优雅的方式来表达这
  • 仅使用 javascript 在服务器上读取/写入 txt 文件,而不涉及任何服务器端语言

    我正在开发一个简单的 HTML Javascript 应用程序 该应用程序在文本区域中向用户显示一条随机文本消息 我有15 20条这样的短信 最多500个字符 我不想将这些消息保存在数据库中 我有两种情况 我每条消息都有多个 txt 文件
  • 每当声明停止请求时,HasAnyAuthority 总是让我进入 api

    通过 Spring Security 我创建了一个方法 Configuration EnableWebSecurity EnableGlobalMethodSecurity securedEnabled true public class
  • 使用 cmake 从 llvm 源目录开发 llvm 通道

    我正在尝试在我的项目目录下开发 llvm pass 为此 我遵循中的信息http llvm org docs CMake html developing llvm pass out of source 我按照此链接适当地创建了我的 CMak
  • RegEx 在 Javascript 中获取字符串后的 URL 部分

    我有以下网址 http data test com api v1 entity 1231 我需要获取后面的文本v1 和之前 斜线之间 在本例中为单词entity 我正在使用以下正则表达式 但我得到的是entity 1231第 1 组 v1
  • Java 1.5 中的 JTable 对行进行排序

    有没有一种简单的方法可以使用 Java 1 5 对 JTable 中的行进行排序 setAutoCreateRowSorter and TableRowSorter似乎是 Java 1 6 功能 Java 1 5 中的排序只能通过库实现 例
  • 在 Objective-C 中替换字符串中的坏词

    我有一个带有公共高分列表的游戏 我允许图层输入他们的名称 或任何最多 12 个字符的名称 我正在尝试创建几个函数来从坏词列表中过滤掉坏词 我有一个文本文件 我有两种方法 读取文本文件之一 void getTheBadWordsAndSave
  • 如何在Python中读取可以保存为ansi或unicode的文件?

    我必须编写一个脚本来支持读取可以保存为 Unicode 或 Ansi 的文件 使用 MS 的记事本 我的文件中没有任何编码格式的指示 如何支持这两种编码格式 一种在不提前知道格式的情况下读取文件的通用方法 MS 记事本为用户提供了 4 种编