首页 > 解决方案 > 如何在 python 中使用 mmap 加载 json?(在窗户上)

问题描述

我有一个 json 文件,我使用 python 中的内存映射打开它。即使 json_file 不包含那么多字段,我也将大小设置为 1024。当我这样做时,json.loads(...)我得到了Error: raise JSONDecodeError("Extra data", s, end). 我打开json文件,看到最后有NULL字符。看这张图片:空字符

我不确定加载 json 文件的正确方法。我打开 mmap 文件并加载 json 的代码如下。

The json file has contents shown below:
{
    "Gardens": {
        "Seaside": {
            "@loc": "porch",
            "@myID": "1.2.3",
            "Tid": "1",
            "InfoList": {
                "status": {
                    "@default": "0",
                    "@myID": "26"
                },
                "count": {
                    "@default": "0",
                    "@myID": "1"
                }
            },
            "BackYard": {
                "@loc": "backyard",
                "@myID": "75",
                "Tid": "2",
                "InfoList": {
                    "status": {
                        "@default": "6",
                        "@myID": "32"
                    },
                    "count": {
                        "@default": "0",
                        "@myID": "2"
                    }
                }
            }
        }
    }
} #  There are NULL characters here as doing the mmap fills NULL characters as the size of the file provided is 1024               
        # Open and read file and MMAP (WRITE access)
        json_file = open(json_path, "r+", encoding="utf-8")
        mapped_file = mmap.mmap(json_file.fileno(), 1024, access=mmap.ACCESS_WRITE)

        # Create the mmap file buffer
        mappedFile.seek(0)
        file_size = os.path.getsize(json_path)
        buffer_for_json = mappedFile[:file_size]

        # Content is JSON, so load it
        json_data = json.loads(buffer_for_json.decode("utf-8")) # ERROR: raise JSONDecodeError("Extra data", s, end)

我真的很迷茫,不知道如何解决这个问题。任何帮助,将不胜感激。:)

标签: pythonjsonunicodeutf-8mmap

解决方案


我无法对此进行测试,因为我没有 Windows 来测试 Windows 版本mmap.mmap,但我认为这正在发生:

当您mmap.mmap()使用大于文件大小的长度值调用时,磁盘上的原始文件会被更改。文档说:

如果length大于文件的当前大小,则将文件扩展为包含length个字节。

最有可能的是,该文件用空字节填充到 1024 字节的大小(您指定的大小)。1024也是你os.path.getsize(json_path)之后得到的。这就是为什么mappedFile[:file_size]包含这些尾随空字节的原因。

我建议您有条件地设置 mmap 长度,例如:

json_file = open(json_path, "r+", encoding="utf-8")
length = min(1024, os.path.getsize(json_path))
mapped_file = mmap.mmap(json_file.fileno(), length, access=mmap.ACCESS_WRITE)

这应该避免空字节填充(顺便说一句,这也会永久损坏您的 JSON 文件)。


推荐阅读