在不同操作系统中写入文件时如何保留原始字符(编码)?
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"
。这导致了所有问题。
我有一个脚本可以将文件从 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 所述 (
# 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"
。这导致了所有问题。