【问题标题】:Why is it true that string.encode('utf-8') != bytes(map(ord, string))?为什么 string.encode('utf-8') != bytes(map(ord, string)) 是真的?
【发布时间】:2014-10-06 20:03:21
【问题描述】:

我们认为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 文件。

【问题讨论】:

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


    【解决方案1】:

    UTF-8 将 Unicode 代码点直接映射到字节。这仅适用于 U+0000 到 U+007F 范围内的 ASCII 码点。超出该范围,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

    【讨论】:

    • 值得注意的是,如果您确实需要通过纯文本通道传递任意字节数据(而不是仅仅人为地调用纯文本通道,即使它处理任意字节,作为 OP由于Django 1.5的限制,似乎在这里做,但我不确定......),正确的答案通常是'surrogateescape'
    • @abarnert:看来这更多是关于浏览器 - Django 后处理程序数据传输。
    • 谢谢。这正是我一直在寻找的。我不完全理解编码,所以这很有帮助。
    猜你喜欢
    • 1970-01-01
    • 2017-05-07
    • 2016-06-05
    • 1970-01-01
    • 2020-05-29
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    • 1970-01-01
    相关资源
    最近更新 更多