为什么string.encode(' utf-8')!= bytes(map(ord,string))是真的吗?

时间:2014-10-06 20:03:21

标签: python python-3.x encoding utf-8 bytearray

我们认为bytes(map(ord, string))使用的是什么编码?为什么string.encode('utf-8') != bytes(map(ord, string))

有时候是真的

当客户端javascript与Django 1.5(Python 3)应用程序交互时,我遇到了这个问题。

基本上我是使用ajax和jDataView上传一个mp3文件作为字符串(我找不到直接上传文件的解决方案)。我使用jDataView将文件转换为字符串。在我的Django应用程序中,当我保存文件时,它会改变大小。但是,如果不使用string.encode('utf-8'),我使用bytes(map(ord, string))文件可以保存。这是为什么?为什么string.encode('utf-8') != bytes(map(ord, string))

我的客户端代码如下所示:

function send(file) {
    var reader = new FileReader();
    reader.onload = function(event) {
        var self = this;
        $.ajax({
            url: 'upload/',
            type: 'POST'
            data: {contents: (new jDataView(self.result)).getString()}
        });
    }
    reader.readAsArrayBuffer(file);
}

我的视图收到如下数据:

def upload(request):
    contents = request.POST.get('contents')
    track = Track.objects.all[0] # For testing only
    contents = bytes(map(ord, contents))
    track.file.save('file.mp3', ContentFile(contents))

我检查了JS代码和Python代码中的contents是一回事。它们具有相同的字节长度,并且看起来具有相同的内容,可以通过适合我屏幕的第一个和最后几个字符来判断。

如果我将代码更改为

def upload(request):
    contents = request.POST.get('contents')
    track = Track.objects.all[0] # For testing only
    contents = contents.encoding('utf-8')
    track.file.save('file.mp3', ContentFile(contents))

文件更改大小,不再是有效的mp3文件。

1 个答案:

答案 0 :(得分:5)

UTF-8 将Unicode代码点直接映射到字节。这仅适用于ASCII码点,范围为U + 0000至U + 007F。超出该范围,UTF-8每个代码点使用2个或更多字节:

>>> '\u007f'.encode('utf8')
b'\x7f'
>>> '\u0080'.encode('utf8')
b'\xc2\x80'

您正在考虑使用Latin-1编码,其中代码点U + 0000到U + 00FF直接映射到字节:

>>> string = ''.join([chr(i) for i in range(0x100)])
>>> string.encode('latin-1') == bytes(map(ord, string))
True

您可以在存储之前对二进制数据进行base64编码,也可以升级到Django 1.6或更高版本,以使用binary field type,而不是编码为文本。