在不同操作系统中写入文件时如何保留原始字符(编码)?

How to preserve original characters (encoding) when writing to file in different operating systems?

我有一个脚本可以将文件从 HTML 转换为 JSON,反之亦然。 当我在不同的操作系统上测试我的脚本时出现问题(主要问题是 windows)。

我通过在 result.json 文件中复制预期结果并将其与输出 output.json 进行比较来测试代码。 那就是当某些字符最终转换为奇怪的符号时。当然测试失败了。 (注意: 这只发生在 Windows,Linux 和 macOS 都通过了测试。)

以下是我遇到的有问题的符号:

Original Character Windows resulting symbol
·
| �|�

下面是我用来将文件内容读入我的脚本的函数:

with open(filepath, "r", encoding="utf-8") as input_file, 
     open(output_filepath, "w", encoding="utf-8") as output_file:

    for line in input_file:
        # some string manipulation with .replace() and .strip()
        output_file.write(line)

# I then read the contents again using beautifulsoup
with open(self.temp_filepath, "r") as file_:
    soup = BeautifulSoup(
        markup=file_,
        features="html.parser",
        from_encoding="Utf-8",
        element_classes={Tag: HTMLBookmark},
    )

最后,在用我的脚本修改内容后,我将内容写入 JSON 文件,如下所示:

with open(output_file, "w", encoding="utf-8") as file_:
    json.dump(data, file_, ensure_ascii=False)

知道如何让输出文件的内容在所有操作系统中始终相同(最好显示原始字符)吗?

这是 GitHub 操作的 link ,但 windows 测试失败。 Link

这是 pytest 中检查文件是否相同的代码:

with open(result_file, mode="r", encoding="utf-8") as orig, open(
    output_file, mode="r", encoding="utf-8") as new:

    assert orig.readline() == new.readline()

编辑: 我更改了 hexdump,第一个 hexdump 来自原始 HTML 文件,第二个 hexdump 来自结果输出 JSON 文件.

这是输出文件 hexdump -s -C 的结果,出于某种原因,它没有在右侧显示正确的文本(也许我为 hexdump 使用了错误的参数?)但是第一个 code block 包含来自源 HTML 文件的正确文本,而第二个 code block 包含来自输​​出 JSON 文件的错误文本。 错误的部分是显示为 It�s what�s happening.

It’s what’s happening
00000a30  54 6b 53 75 51 6d 43 43  22 3e 54 77 69 74 74 65  |TkSuQmCC">Twitte|
00000a40  72 2e 20 49 74 e2 80 99  73 20 77 68 61 74 e2 80  |r. It...s what..|
00000a50  99 73 20 68 61 70 70 65  6e 69 6e 67 20 2f 20 54  |.s happening / T|
00000a60  77 69 74 74 65 72 3c 2f  41 3e 0d 0a 20 20 20 20  |witter</A>..    |
00000a70  20 20 20 20 20 20 20 20  3c 44 54 3e 3c 41 20 48  |        <DT><A H|
00000a80  52 45 46 3d 22 68 74 74  70 73 3a 2f 2f 77 77 77  |REF="https://www|
00000a90  2e 66 61 63 65 62 6f 6f  6b 2e 63 6f 6d 2f 22 20  |.facebook.com/" |
00000aa0  41 44 44 5f 44 41 54 45  3d 22 31 35 39 39 37 35  |ADD_DATE="159975|
00000ab0  30 38 30 37 22 20 49 43  4f 4e 3d 22 64 61 74 61  |0807" ICON="data|
00000ac0  3a 69 6d 61 67 65 2f 70  6e 67 3b 62 61 73 65 36  |:image/png;base6|
00000730  6c 65 22 3a 20 22 54 77  69 74 74 65 72 2e 20 49  |le": "Twitter. I|
00000740  74 c3 a2 e2 82 ac e2 84  a2 73 20 77 68 61 74 c3  |t........s what.|
00000750  a2 e2 82 ac e2 84 a2 73  20 68 61 70 70 65 6e 69  |.......s happeni|
00000760  6e 67 20 2f 20 54 77 69  74 74 65 72 22 2c 20 22  |ng / Twitter", "|
00000770  64 61 74 65 5f 61 64 64  65 64 22 3a 20 31 35 39  |date_added": 159|
00000780  39 37 35 30 37 39 35 2c  20 22 75 72 6c 22 3a 20  |9750795, "url": |
00000790  22 68 74 74 70 73 3a 2f  2f 74 77 69 74 74 65 72  |"https://twitter|
000007a0  2e 63 6f 6d 2f 3f 6c 61  6e 67 3d 65 6e 22 2c 20  |.com/?lang=en", |
000007b0  22 69 63 6f 6e 22 3a 20  22 64 61 74 61 3a 69 6d  |"icon": "data:im|
000007c0  61 67 65 2f 70 6e 67 3b  62 61 73 65 36 34 2c 69  |age/png;base64,i|

首先,我要感谢@tripleee 和@ekhumoro,因为他们的评论让我能够找到问题并学到很多东西。

问题如@ekhumoro 所述 () and @tripleee (), a Mojibake。 如问题的第一个代码片段所示:

# original code snippet from questions
with open(self.temp_filepath, "r") as file_:
    soup = BeautifulSoup(
        markup=file_,
        features="html.parser",
        from_encoding="Utf-8",
        element_classes={Tag: HTMLBookmark},
    )

# correct code snippet
with open(self.temp_filepath, "r", encoding="utf-8") as file_:
    soup = BeautifulSoup(
        markup=file_,
        features="html.parser",
        from_encoding="Utf-8",
        element_classes={Tag: HTMLBookmark},
    )

缺少一个 encoding="utf-8"。这导致了所有问题。