繁体   English   中英

如何将包含unicode的2d数组保存到.txt文件或从其中保存。[Python] [编码问题] [utf8]

[英]How to save/load a 2d array containing unicode to/from a .txt file [Python] [encoding issues][utf8]

因此,我遇到的基本问题是,当我将Unicode字符\\ u2656写入txt文件时, 变成了b'\\ xe2 \\ x99 \\ x96' (我相信这是字节码?)。 然后,当我读取文件时,无法将其解码回\\ u2656

Board_visual只是一个二维数组,其中每个项目都是unicode字符或None类型(一个空的正方形)。 它用于表示棋子在我的tkinter gui使用的棋盘上的位置。 实际的棋子是对象,所以这只是代表国际象棋棋子的Unicode字符。

示例board_visual内容

['♖', '♘', '♗', '♔', '♕', '♗', '♘', '♖']
['♙', None, '♙', '♙', '♙', '♙', '♙', '♙']
[None, '♙', None, None, None, None, None, None]
[None, None, None, None, None, None, None, None]
[None, None, None, '♟', None, None, None, None]
[None, None, None, None, None, None, None, None]
['♟', '♟', '♟', None, '♟', '♟', '♟', '♟']
['♜', '♞', '♝', '♚', '♛', '♝', '♞', '♜']

这是我使用的代码:

def save():
    filename=input("Enter the name of the file")
    myFile=open(str(filename)+".txt","w")
    for i in board_visual:
        for j in i:
            myFile.write(str(str(j).encode('utf8')))
            myFile.write("\n")
    myFile.close()

它给出了这种文件格式(在.txt文件中):

b'\xe2\x99\x97'
b'\xe2\x99\x98'
b'\xe2\x99\x96'
b'None'
b'\xe2\x99\x99'
b'\xe2\x99\x99'
b'None'
b'\xe2\x99\x99'
b'\xe2\x99\x99'
b'\xe2\x99\x99'
b'\xe2\x99\x99'
b'None'
...

然后我尝试用

def load():
    global board_visual
    global board
    filename=input("Enter the name of the file")
    myFile=open(str(filename)+".txt","r", encoding='utf8')
    index=0
    index2=0
    for i in myFile:
        if i!="b'None'\n":
            i=i.strip("\n")
            board_visual[index//8][index%8]=i#places it into the 8*8 grid
        else:
            board_visual[index//8][index%8]=None
        index=index+1
    myFile.close()

该网站上的一些帖子提到使用.decode,但仅在python 2中有效我正在使用python 3.3,当我没有任何unicode字符时,该程序可以完美运行。这意味着问题一定与编码有关,但这是我第一次使用它,但似乎无法正确解码。 我浏览了网站上的许多类似问题,但是没有一种解决方案对我有用(很多是针对Python 2的),我最初尝试在写入文件时没有.encode(utf8)的尝试,但这给了我错误:UnicodeEncodeError :'charmap'编解码器无法在位置0编码字符'\\ u2656':从研究错误起,我映射了.encode(utf8)来映射字符映射,但这在程序中将其解码回Unicode时会引起问题。 我也使用了unicode(i),但这是一个未知命令。

因为只有12个不同的字符,所以我可以创建一个if / elif语句来检查它们并将其转换为我的自我,但这显然是一个非常差的解决方案。

我对编程很陌生,而python是我唯一的语言,它在国际象棋游戏引擎中使用。 (我的第一个大型项目)我不确定我缺少什么。 任何帮助将不胜感激,我希望我的职位符合要求。 如果有一个网站,您可以推荐帮助我学习python编码,那也很好,我似乎无法正常工作。

提前致谢

那当然不是您真正想要做的,但是ast.literal_eval能够逆转您对utf8编码数据的序列化:

>>> t = r"b'\xe2\x99\x96'"
>>> print(t)
b'\xe2\x99\x96'
>>> print(ast.literal_eval(r"b'\xe2\x99\x96'").decode())
♖
>>> print(hex(ord(ast.literal_eval(r"b'\xe2\x99\x96'").decode())))
0x2656

但这确实很丑陋,您应该使用json或直接依靠Python在utf-8中自动编码和解码unicode的能力:

    for j in i:
        myFile.write(j)
        myFile.write("\n")

正如@ juanpa.arrivillaga在他的评论中所建议的

这应该为您工作。 在python 3.6上测试

chess = "♔ ♕ ♖ ♗ ♘ \u2655 \u2656 \u2657 \u2658 \u2659 \u265a"
f = open('file', 'wb')
f.write(chess.encode('utf8'))
f.close()

f = open('file', 'rb')
print (f.read().decode('utf-8'))

您的代码中的实际问题是以下部分:

str(str(j).encode('utf8'))

通常,您的代码充满了对str调用。 它们中的大多数是不必要和令人困惑的,但无害。 但这是有害的。

在交互式解释器上尝试表达的每个部分可能会有所帮助。 如果j是一个字符串,则str(j)是该相同字符串的副本。 然后str(j).encode('utf8')是一个bytes保存该字符串的UTF-8编码。 然后str(str(j).encode('utf8'))是该字节对象的字符串表示形式,它将是字母b和一些引号,中间带有一串反斜杠转义。 这就是您最终写入文件的内容。

如果仅使用j.encode('utf8') ,则此问题将消失,但这可能只是许多问题中的第一个。 下一个很有可能是您正在打开一个文本模式文件,然后尝试向其中写入编码的bytes而不是字符串的事实。 您可以通过不执行编码而仅使用j 等等。

更一般而言,您需要先了解正在做的事情,然后才能希望Python知道您正在尝试做的事情。 如果您不知道为什么在某处调用str ,为什么要调用它?

在Python(3.0及更高版本)中,您不应该在各处处理编码。 只需指定一次编码,并尽可能靠近边缘。 特别是,如果要将某些Unicode写入UTF-8文件,只需将Unicode写入UTF-8文件:

s = ‘\u1234\u2345’
with open(‘myfile.txt’, ‘w’, encoding=‘utf-8’) as f:
    f.write(s)

而已。 无需调用encodedecodestr ,也无需在任何地方处理bytes对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM