从文本文件python中读取字符串

时间:2018-06-11 17:10:34

标签: python

我正在阅读文本文件中的单词,并将它们与一组单词进行比较,以查看它们在样本文档中出现的次数。例如,我有一个文本文件,我想看看“工程师”这个词出现多少次。

问题是,对于我的示例数据,字符串比较不起作用。我看到该程序确实正在阅读看起来像“工程师”的<type 'str'>的单词;然而,没有比赛。使用ord(character)打印单词中每个字符的ASCII时,每个字符之间似乎都有0。字符串“engineer”的输出如下所示:

0 101 0 110 0 103 0 105 0 110 0 101 0 101 0 114 0

使用strip()删除开头和结尾0,但不删除中间的0。有关这些字符串的格式以及如何解决这些问题的想法吗?

我正在使用Python 2.7。

2 个答案:

答案 0 :(得分:2)

这是字符串engineer的{​​{3}}编码。 1

UTF-16对BMP字符(包括ASCII字符)使用两个字节,因此,例如,字符e,即Unicode(和ASCII)字符编号101(0x65十六进制),显示为16位代码单元101.在big-endian中(这是-BE部分的含义),第一个字节为0,第二个字节为101.因此,如果你的文本是纯ASCII,你的UTF-16最终看起来像ASCII,每个字符前加一个\0字节。

解决此问题的最简单方法是将文件作为Unicode文件打开。作为一般规则,如果您将所有内容解码为unicode作为阅读它的一部分,则只在最后编码回字节作为编写它的一部分,并使用unicode在中间完成所有工作一切都比较简单。

在Python 2.7中,有两种方法可以执行此操作:UTF-16-BEcodecs.open。使用codecs使您的代码更容易移植到Python 2.5,使用io使得移植到3.x更容易,但是在这样的简单情况下它没有区别

请注意,您的line字符串现在为unicode而不是str,因此理想情况下,您希望您的搜索字符串集合也为unicode值。< / p>

d = {u'engineer': 0, u'conductor': 0, u'transit cop': 0}
with io.open(path, encoding='utf-16-be') as f:
    for line in f:
        try:
            d[line.strip()] += 1
        except KeyError:
            pass

另一种方法是将文件读取为二进制UTF-16-BE,并使搜索字符串为UTF-16-BE编码str值:

d = {u'engineer': 0, u'conductor': 0, u'transit cop': 0}
d = {key.encode('utf-16-be'): count for key, count in d.items()}
with open(path) as f:
    for line in f:
        try:
            d[line.rstrip('\n\0')] += 1
        except KeyError:
            pass

请注意,我必须小心剥离,以确保在末尾删除整个双字节\0\n而不是\n字节,并且不会剥离{{ 1}}开头的字节。这只是处理编码字节的许多方法之一,而不是处理Unicode。如果您的最终输出将涉及,例如,将这些字符串打印到您的控制台或将它们写入UTF-8文件,它将变得更加痛苦。如果最终输出将是另一个UTF-16-BE文件,并且如果保存一点CPU非常重要,那么这样做可能是值得的。但除此之外,我会选择第一个。

<子> 1。实际上,你最后还有一个额外的\0。但可能在您的真实数据中,这实际上是下一个字符的第一个字节 - 也许是\0,在UTF-16-BE中,当然看起来像\n

答案 1 :(得分:-1)

看起来像正则表达式库https://docs.python.org/3/library/re.html的工作。匹配合适的正则表达式以获得每行的命中数。添加em以获取文件级别:

pattern = re.compile("engine")
len(pattern.findall("engine engineers love engineering"))
>>>
3