15.json文件读取与写入

python 复制代码
# -*- coding: utf-8 -*-
"""
@Created on : 2026/5/6 10:03
@creator : er_nao
@File :Day_15.py
@Description :json文件读取与写入
"""
import jieba
import json
import os

""" 核心知识点 1:JSON 文件读取进阶用法 """

# 进阶用法 1:批量读取文件夹里的所有 JSON 文件(NLP 批量处理核心)


# ------------------ 核心配置 ----------------
# 存放JSON文件的文件夹路径(替换成你自己的文件夹路径)
JSON_FOLDER = 'C:\\Users\\hp\\Desktop\\json_file'
# 筛选条件:只读取.json结尾的文件
FILE_SUFFIX = '.json'


def batch_read_json_file(folder_path, file_suffix):
    """
        批量读取文件夹里的所有JSON文件,返回合并后的所有数据
        :param folder_path: JSON文件所在的文件夹路径
        :param file_suffix: 要筛选的文件后缀,比如.json
        :return: 合并后的所有JSON数据列表
    """
    # 存储所有读取到的json数据
    all_json_data =[]
    # 遍历文件夹里的所有文件
    for filename in os.listdir(folder_path):
        # 只处理制定后缀的文件
        if filename.endswith(file_suffix):
            # 拼接完整的文件路径
            file_path = os.path.join(folder_path, filename)
            try:
                # 读取json文件
                with open(file_path,'r',encoding='utf-8') as f:
                    json_data = json.load(f)

                    if isinstance(json_data,list):
                        all_json_data.append(json_data)
                    else:
                        all_json_data.append(json_data)
                print(f"成功读取文件:{filename}")
            except Exception as e:
                print(f"读取文件失败:{filename},错误原因:{e}")
    # 返回所有合并后的数据
    return all_json_data

# ---------------------- 主程序:批量读取 + 简单统计 ----------------------
# if __name__ == '__main__':
#     # 批量读取所有JSON文件
#     all_chat_data = batch_read_json_file(JSON_FOLDER, FILE_SUFFIX)
#
#     # 简单统计结果
#     print(f"\n 批量读取完成!")
#     print(f"总读取文件数:{len(os.listdir(JSON_FOLDER))}")
#     print(f"总读取到的对话轮数:{len(all_chat_data)}")
#
#     # 打印前两条数据,验证读取结果
#     if len(all_chat_data) > 0:
#         print("\n 前两条读取到的内容结果")
#         for i, chat in enumerate(all_chat_data[:2]):
#             print(f"第{i+1}条:{chat}")


# 进阶用法 2:大 JSON 文件流式读取(避免内存溢出,NLP 大语料处理核心)

# ---------------------- 核心配置 ----------------------
# 大JSON文件路径(替换成你自己的大文件路径)
BIG_JSON_FILE = '/mnt/nlp_corpus.jsonl'
# 停用词列表
STOP_WORDS = ["的", "是", "在", "和", "有", "也", "就", "都", "而", "及", "与", "着", ",", "。", "!", "?", ";", ":", "、", " "]

# ---------------------- 大JSON文件流式读取 + 处理 ----------------------
def stream_read_big_json(file_path):
    """
       流式读取大JSON文件(行级JSON格式),每读取一行就处理一行
       :param file_path: 大JSON文件路径
       :return: 处理后的所有语料数据
       """
    # 存储处理后的结果
    processed_corpus = []
    with open(file_path, 'r',encoding="utf-8") as f:

        for line_num,line in enumerate(f,start=1):
            line = line.strip()
            if not line:
                continue
            try:
                # 把当前行的json字符串,转换成python字典
                json_data = json.loads(line)
                # 提取语料文件
                text = json_data.get('text','')
                if not text:
                    continue
                # ---------------------- 对文本做NLP处理 ----------------------
                # 1.清洗文本
                clean_text = text.strip().replace(' ','')
                # 2.分词+过滤停用词
                words = jieba.lcut(clean_text)
                valid_words = [word for word in words if word not in STOP_WORDS and word.strip()!=""]

                # 把处理后的结果添加到列表里
                processed_data = {
                    "行号": line_num,
                    "原始文本": text,
                    "清洗后的文本": clean_text,
                    "分词结果": valid_words,
                    "有效词数": len(valid_words)
                }
                processed_corpus.append(processed_data)

                # 每处理1000行,打印一次进度
                if line_num % 1000 == 0:
                    print(f"已处理{line_num}行语料")

            except Exception as e:
                print(f" 处理第 {line_num} 行失败,错误原因:{e}")
                continue
    return processed_corpus

# ---------------------- 主程序:流式读取 + 结果保存 ----------------------
# if __name__ == '__main__':
#     print(" 开始流式读取大JSON语料文件...")
#     processed_result = stream_read_big_json(BIG_JSON_FILE)
#     # 把处理后的结果,写入到新的JSON文件里
#     with open("C:\\Users\\hp\\Desktop\\processed_corpus.json", 'w', encoding="utf-8") as f:
#         json.dump(processed_result, f, ensure_ascii=False, indent=4)
#
#     # 打印最终结果
#     print(f"\n 大文件处理完成!")
#     print(f"总处理行数:{len(processed_result)}")
#     print(f"处理后的结果已保存到:processed_corpus.json")


# 进阶用法 3:JSON 嵌套数据的精准提取

# ---------------------- 模拟大模型API返回的复杂嵌套JSON结果 ----------------------
api_response_json = """
{
    "id": "chatcmpl-20241231-001",
    "object": "chat.completion",
    "created": 1735689600,
    "model": "ep-20240520182611-2jvzk",
    "choices": [
        {
            "index": 0,
            "message": {
                "role": "assistant",
                "content": "学习NLP自然语言处理,建议从以下几个步骤开始:1. 先掌握Python基础语法;2. 学习文本预处理;3. 学习核心NLP任务;4. 学习大模型API调用;5. 学习RAG检索增强生成技术。",
                "refusal": null
            },
            "finish_reason": "stop",
            "stop_reason": null
        }
    ],
    "usage": {
        "prompt_tokens": 50,
        "completion_tokens": 150,
        "total_tokens": 200
    },
    "system_fingerprint": "fp_20241231",
    "refs": ["NLP基础", "大模型API", "RAG"]
}
"""

# ---------------------- 从嵌套JSON里精准提取核心数据 ----------------------
# 把JSON字符串转换成Python字典
api_response = json.loads(api_response_json)

# 1. 提取第一层的基础数据
chat_id = api_response.get("id", "未知ID")
model_name = api_response.get("model", "未知模型")
create_time = api_response.get("created", 0)
print("【第一层基础数据】:")
print(f"对话ID:{chat_id}")
print(f"模型名称:{model_name}")
print(f"创建时间戳:{create_time}")
print("-"*50)

# 2. 提取第二层的Token消耗数据(嵌套对象)
usage_data = api_response.get("usage", {})
prompt_tokens = usage_data.get("prompt_tokens", 0)
completion_tokens = usage_data.get("completion_tokens", 0)
total_tokens = usage_data.get("total_tokens", 0)
print("【第二层Token消耗数据】:")
print(f"输入Token数:{prompt_tokens}")
print(f"输出Token数:{completion_tokens}")
print(f"总消耗Token数:{total_tokens}")
print("-"*50)

# 3. 提取第三层的AI回答内容(嵌套数组+嵌套对象)
choices_data = api_response.get("choices", [])
if len(choices_data) > 0:
    first_choice = choices_data[0]
    message_data = first_choice.get("message", {})
    ai_answer = message_data.get("content", "无人回答")
    finish_reason = first_choice.get("finish_reason","未知原因")
    print("【第三层AI回答核心数据】:")
    print(f"AI回答内容:{ai_answer}")
    print(f"对话结束原因:{finish_reason}")
print("-" * 50)

# 4. 提取数组里的所有引用标签
refs_list = api_response.get('refs', [])
print("【第四层引用标签数据】:")
print(f"所有引用标签:{refs_list}")
for i, ref in enumerate(refs_list):
    print(f"标签{i+1}:{ref}")


# 进阶用法 4:JSON 文件读取的格式校验与异常处理

# ---------------------- 核心配置 ----------------------
JSON_FILE_PATH = '/mnt/chat_history.json'
# 业务要求的JSON必须包含的键
REQUIRED_KEYS = ['对话ID', '用户问题', 'AI回答', '是否完成']

# ---------------------- 企业级JSON文件读取 + 格式校验 + 异常处理 ----------------------
def safe_read_json_file(file_path, required_keys = None):
    """
        安全读取JSON文件,做完整的异常处理和格式校验
        :param file_path: JSON文件路径
        :param required_keys: 业务要求的必须包含的键列表
        :return: 读取成功返回JSON数据,读取失败返回None
    """
    # 1. 先校验文件是否存在
    if not os.path.exists(file_path):
        print(f" 读取失败:文件 {file_path} 不存在")
        return None

    # 2. 校验是否是文件(不是文件夹)
    if not os.path.isfile(file_path):
        print(f" 读取失败:{file_path} 不是一个文件")
        return None

    # 3. 校验是否有读取权限
    if not os.access(file_path, os.R_OK):
        print(f" 读取失败:没有读取文件 {file_path} 的权限")
        return None

    # 4. 读取文件并解析JSON,捕获所有异常
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            # 读取文件内容
            file_content = f.read()
            # 解析JSON
            json_data = json.loads(file_content)
    except json.JSONDecodeError as e:
        print(f" 读取失败:JSON格式错误,错误原因:{e}")
        return None
    except UnicodeDecodeError as e:
        print(f" 读取失败:JSON格式错误,错误原因:{e}")
        return None
    except Exception as e:
        print(f" 读取失败:未知错误,错误原因:{e}")
        return None

    # 5. 业务格式校验:检查是否包含必须的键
    if required_keys:
        # 如果JSON是数组,遍历每个元素校验
        if isinstance(json_data,list):
            for i, item in enumerate(json_data):
                if not isinstance(item, dict):
                    print(f"  格式警告:第{i + 1}个元素不是字典格式")
                    continue

                # 检查是否包含所有必须的键
                missing_keys = [key for key in required_keys if key not in item]
                if missing_keys:
                    print(f"  格式警告:第{i + 1}个元素缺少必须的键:{missing_keys}")

        elif isinstance(json_data, dict):
            missing_keys = [key for key in required_keys if key not in json_data]
            if missing_keys:
                print(f"  格式警告:JSON对象缺少必须的键:{missing_keys}")

    # 6. 所有校验通过,返回JSON数据
    print(f" 成功读取JSON文件:{file_path}")
    return json_data

# 安全读取JSON文件,同时做业务格式校验
chat_data = safe_read_json_file(JSON_FILE_PATH, REQUIRED_KEYS)

# 读取成功,做后续处理
if chat_data:
    print(f"\n 读取结果统计:")
    if isinstance(chat_data, list):
        print(f"总对话轮数:{len(chat_data)}")
        # 统计已完成的对话
        completed_chats = [chat for chat in chat_data if isinstance(chat, dict) and chat.get('是否完成', False)]
        print(f"已完成对话数:{len(completed_chats)}")
        print(f"对话完成率:{round(len(completed_chats) / len(chat_data) * 100, 2)}%")


""" 核心知识点 2:JSON 文件写入进阶用法 """

# 进阶用法 1:JSON 文件增量写入
import time

# ---------------------- 核心配置 ----------------------
# 对话历史JSON文件路径
CHAT_HISTORY_FILE = '/mnt/user_chat_history.jsonl'


# ---------------------- 对话历史增量写入函数 ----------------------
def append_chat_to_history(chat_data, file_path):
    """
    把新的对话数据,增量写入到对话历史JSON文件里(行级JSON格式)
    :param chat_data: 新的对话数据(字典格式)
    :param file_path: 对话历史文件路径
    :return: 写入成功返回True,失败返回False
    """
    # 校验对话数据是否是字典格式
    if not isinstance(chat_data, dict):
        print(" 写入失败:对话数据必须是字典格式")
        return False

    # 把对话数据转换成JSON字符串,一行一个JSON对象
    chat_json_str = json.dumps(chat_data, ensure_ascii=False) + '\n'

    try:
        # 用'a'模式打开文件,代表追加写入,不会覆盖原来的内容
        with open(file_path, 'a', encoding='utf-8') as f:
            # 把新的对话JSON字符串,写入到文件末尾
            f.write(chat_json_str)
        print(f" 成功把新对话写入到历史文件:{file_path}")
        return True
    except Exception as e:
        print(f" 写入失败:{e}")
        return False


# ---------------------- 主程序:模拟对话系统的增量写入 ----------------------
if __name__ == "__main__":
    print("模拟大模型对话系统,增量写入对话历史...")

    # 模拟3轮对话,每轮对话都增量写入到文件里
    for i in range(1, 4):
        # 模拟新的对话数据
        new_chat = {
            "对话ID": f"chat_20241231_{i:02d}",
            "用户ID": "user_001",
            "用户问题": f"我想学习NLP的第{i}个核心知识点",
            "AI回答": f"这是NLP第{i}个核心知识点的详细讲解...",
            "对话时间": time.strftime("%Y-%m-%d %H:%M:%S"),
            "是否完成": True,
            "消耗Token": 100 + i * 50
        }

        # 增量写入到对话历史文件里
        append_chat_to_history(new_chat, CHAT_HISTORY_FILE)

        # 模拟对话间隔
        time.sleep(0.5)

    print(f"\n 3轮对话全部写入完成!")
    print(f"对话历史已保存到:{CHAT_HISTORY_FILE}")
相关推荐
知识分享小能手1 小时前
R语言入门学习教程,从入门到精通,R语言入门(3)
开发语言·学习·r语言
AI人工智能+电脑小能手1 小时前
【大白话说Java面试题 第41题】【JVM篇】第1题:JVM由哪些部分组成?
java·开发语言·jvm·后端·面试
0xDevNull1 小时前
ConcurrentHashMap 与 Hashtable 深度对比
java·开发语言
木易 士心1 小时前
深度解析:一个 Java 对象究竟占用多少字节?
java·开发语言·后端
水云桐程序员9 小时前
C++可以写手机应用吗
开发语言·c++·智能手机
测试员周周9 小时前
【AI测试智能体】为什么传统测试方法对智能体失效?
开发语言·人工智能·python·功能测试·测试工具·单元测试·测试用例
dfdfadffa10 小时前
如何用模块化方案组织一个可扩展的前端组件库项目
jvm·数据库·python
2301_8125396710 小时前
SQL中如何高效实现分组数据的批量更新_利用窗口函数与JOIN
jvm·数据库·python
RSTJ_162510 小时前
PYTHON+AI LLM DAY THREETY-NINE
开发语言·人工智能·python