掘金 后端 ( ) • 2024-05-06 14:31

基础操作

CSV文件的读写

示例代码

import csv
from pathlib import Path

# 检查文件是否存在,如果不存在则创建空文件
file_path = Path('data.csv')
file_path.touch(exist_ok=True)

# 读取CSV文件
with open('data.csv', 'r') as csvfile:
    reader = csv.reader(csvfile)
    for row in reader:
        print(row)

# 写入CSV文件
with open('data.csv', 'w', newline='') as csvfile:
    writer = csv.writer(csvfile)
    writer.writerow(['name', 'department', 'birthday month'])

csv模块

Python的csv模块是一个强大的库,用于处理CSV(逗号分隔值)文件。它是Python标准库的一部分,因此不需要安装任何额外的包就可以使用。csv模块提供了一系列功能,使得读取和写入CSV文件变得非常简单和直接。它支持各种自定义选项,包括自定义分隔符、引号处理、行结束符等,使其能够处理各种不同格式的CSV文件。

主要特性

  • 简单性:提供了简单的接口来读取和写入CSV文件。
  • 灵活性:可以处理不同的CSV方言(例如,不同的分隔符、引号规则等)。
  • 自动化:自动处理复杂的转义和引号,简化了编程工作。
读取CSV文件
  • csv.reader(csvfile, dialect='excel', **fmtparams)

    • 用于创建一个读取器对象,该对象将遍历给定的csvfile中的每一行。
    • csvfile参数应该是一个已打开的文件对象或类似文件的对象。
    • dialectfmtparams允许自定义文件的格式,如分隔符、引号规则等。
  • csv.DictReader(csvfile, fieldnames=None, restkey=None, restval=None, dialect='excel', **fmtparams)

    • 创建一个字典读取器对象,该对象将遍历csvfile中的每一行,将每行映射为一个字典。其中,字典的键由fieldnames提供。
    • 如果fieldnames参数为空,读取器会将文件的第一行视为列名。
写入CSV文件
  • csv.writer(csvfile, dialect='excel', **fmtparams)

    • 用于创建一个写入器对象,该对象提供了将数据写入csvfile的方法。
    • csvfile参数应该是一个已打开的文件对象或类似文件的对象,通常以写入模式打开。
  • csv.DictWriter(csvfile, fieldnames, restval='', extrasaction='raise', dialect='excel', **fmtparams)

    • 创建一个字典写入器对象,该对象提供了将字典写入csvfile的方法。
    • fieldnames参数是一个序列,指定了输出CSV文件的列名。每个字典的键应与fieldnames中的一个条目相对应。
常用方法

对于csv.readercsv.writer对象:

  • writer.writerow(row)
    • row(一个字符串列表)写入到CSV文件中,作为一行数据。
  • writer.writerows(rows)
    • rows(一个字符串列表的列表)写入到CSV文件中,每个内部列表作为一行数据。

对于csv.DictReadercsv.DictWriter对象:

  • writer.writeheader()DictWriter特有):
    • 将列名(即fieldnames)写入CSV文件作为头行。
  • writer.writerow(rowdict)DictWriter特有):
    • rowdict(一个字典)写入CSV文件中,每个键值对应一列。
参数和方言

csv模块中的dialectfmtparams参数允许用户自定义CSV文件的解析和写入方式,以适应不同的CSV格式。这些参数可以控制如分隔符、引号规则、行结束符等方面的行为。

  • 方言(Dialect)
    • 方言是预定义的格式设置集合,如excelunix等,分别对应Excel兼容的CSV格式和Unix/Linux系统中常见的CSV格式。
  • 格式参数(Format parameters)
    • 包括delimiterquotecharescapecharquoting等,允许更细粒度地控制CSV的读写行为。

通过灵活运用这些函数、方法和参数,可以高效地处理各种CSV文件。

pathlib模块

pathlib是Python 3.4及更高版本中引入的一个库,它提供了面向对象的文件系统路径操作。pathlib旨在以一种更直观和易于理解的方式来处理文件系统路径,它将文件系统路径视为适当的对象,而不是仅仅处理字符串表示。这使得执行路径相关操作(如合并路径、获取文件的绝对路径、检查文件是否存在等)变得更加直观和安全。

主要特性

  • 面向对象:路径被封装为Path对象,提供了丰富的方法和属性来处理和查询路径。
  • 易用性:通过方法链式调用,使得代码更加清晰和简洁。
  • 跨平台:自动处理不同操作系统之间路径表示的差异,提高代码的可移植性。
  • 综合性:提供了创建文件、文件夹、读写文件、路径解析等多种功能。

结合csvpathlib模块,可以非常方便地处理CSV文件的读写操作,同时确保了代码的健壮性和可读性。pathlib提供的路径操作方法与csv模块的读写功能搭配使用,可以有效地管理和操作文件系统中的CSV文件。

JSON数据的处理

JSON包官网文档传送门

2024年05月06日12:55:28

py.v 3.12.3

示例代码

import json

# 解析JSON字符串
json_string = '{"name": "王德发", "age": 30, "city": "北京"}'
parsed_json = json.loads(json_string)
print(parsed_json['name'])

# 生成JSON字符串
person_dict = {'name': '王德发', 'age': 30, 'city': '北京'}
json_string = json.dumps(person_dict,)
print(json_string)

# 输出
# 王德发
# {"name": "\u738b\u5fb7\u53d1", "age": 30, "city": "\u5317\u4eac"}

这里的“乱码”可以看一下dumps的ensure_ascii参数

Python的json模块是标准库的一部分,提供了一套简单的方法和过程,用于编码和解码JSON(JavaScript Object Notation)数据。JSON是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。json模块使得Python能够轻松地将Python对象层次结构转换成JSON格式的字符串,或者将JSON格式的字符串转换成Python对象。

主要特性

  • 简单易用json模块提供了直观的函数和方法,用于处理JSON数据,使得从Python程序到JSON格式的转换,以及反向转换变得非常简单。

  • 灵活性:支持几乎所有的Python基本类型和数据结构转换为JSON格式,包括列表、字典、字符串、整数、浮点数、布尔值等。

  • 可扩展:通过自定义编码器(JSONEncoder的子类)和解码器(JSONDecoder的子类),可以处理更复杂的数据类型(如日期时间等)的转换。

  • json.dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

    • 将Python对象编码成JSON格式的字符串,并写入到文件类对象fp中。
  • json.dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

    • 将Python对象编码成JSON格式的字符串,返回该字符串。
  • json.load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

    • 从文件类对象fp中读取JSON格式的字符串,并将其解码成Python对象。
  • json.loads(s, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

    • 将JSON格式的字符串s解码成Python对象。

综合示例——CSV和JSON相互转化

需求

可以让CSV和JSON相互转化

不传入目录就在当前目录查找和输出

带操作耗时

源文件CSV

BattleID,StartTime,EndTime,Duration,WinnerID,LoserID,EventID,Timestamp,EventType,ActorID,ActorName,TargetID,TargetName,SkillID,SkillName,Damage,Effect,Outcome
1,2024-05-01 10:00:00,2024-05-01 10:05:00,300,1,2,1,2024-05-01 10:00:05,"攻击",1,"英雄A",2,"英雄B",,"普通攻击",100,,"击中"
1,2024-05-01 10:00:10,2024-05-01 10:05:00,300,1,2,2,2024-05-01 10:00:15,"技能释放",2,"英雄B",1,"英雄A",1,"冰霜新星",150,"冰冻","成功"
1,2024-05-01 10:00:20,2024-05-01 10:05:00,300,1,2,3,2024-05-01 10:00:25,"攻击",1,"英雄A",2,"英雄B",,"普通攻击",120,,"闪避"
1,2024-05-01 10:00:30,2024-05-01 10:05:00,300,1,2,4,2024-05-01 10:00:35,"技能释放",1,"英雄A",2,"英雄B",2,"火球术",200,"燃烧","成功"
2,2024-05-01 10:10:00,2024-05-01 10:15:00,300,3,4,5,2024-05-01 10:10:05,"攻击",3,"英雄C",4,"英雄D",,"普通攻击",90,,"击中"
2,2024-05-01 10:10:10,2024-05-01 10:15:00,300,3,4,6,2024-05-01 10:10:15,"技能释放",4,"英雄D",3,"英雄C",3,"治疗波",0,"治疗","成功"
2,2024-05-01 10:10:20,2024-05-01 10:15:00,300,3,4,7,2024-05-01 10:10:25,"攻击",3,"英雄C",4,"英雄D",,"普通攻击",110,,"击中"
2,2024-05-01 10:10:30,2024-05-01 10:15:00,300,3,4,8,2024-05-01 10:10:35,"技能释放",3,"英雄C",4,"英雄D",4,"雷霆一击",170,"眩晕","成功"
3,2024-05-01 10:20:00,2024-05-01 10:25:00,300,5,6,9,2024-05-01 10:20:05,"攻击",5,"英雄E",6,"英雄F",,"普通攻击",80,,"击中"
3,2024-05-01 10:20:10,2024-05-01 10:25:00,300,5,6,10,2024-05-01 10:20:15,"技能释放",6,"英雄F",5,"英雄E",5,"暗影突袭",130,"恐惧","成功"
3,2024-05-01 10:20:20,2024-05-01 10:25:00,300,5,6,11,2024-05-01 10:20:25,"攻击",5,"英雄E",6,"英雄F",,"普通攻击",100,,"闪避"
3,2024-05-01 10:20:30,2024-05-01 10:25:00,300,5,6,12,2024-05-01 10:20:35,"技能释放",5,"英雄E",6,"英雄F",6,"光辉之箭",160,"眩晕","成功"

代码

import csv
import json
import os
import time

class DataConverter:
    @staticmethod
    def csv_to_json(csv_file_path, json_file_path=None):
        start_time = time.time()
        
        # 如果没有提供完整路径,尝试在当前目录查找文件
        if not os.path.isfile(csv_file_path):
            csv_file_path = os.path.join(os.getcwd(), csv_file_path)
        
        # 确定CSV文件所在的目录和文件名
        directory, csv_filename = os.path.split(csv_file_path)
        filename, _ = os.path.splitext(csv_filename)
        
        # 如果没有指定json_file_path,构建JSON文件路径
        if json_file_path is None:
            json_file_path = os.path.join(directory, filename + '.json')
        elif not os.path.isabs(json_file_path):  # 如果提供的是相对路径
            json_file_path = os.path.join(os.getcwd(), json_file_path)
        
        # 读取CSV文件并转换为JSON
        data = []
        with open(csv_file_path, mode='r', encoding='utf-8') as csv_file:
            csv_reader = csv.DictReader(csv_file)
            for row in csv_reader:
                data.append(row)
        
        # 写入JSON文件
        with open(json_file_path, 'w', encoding='utf-8') as json_file:
            json_file.write(json.dumps(data, indent=4, ensure_ascii=False))
        
        elapsed_time = time.time() - start_time
        print(f"JSON文件已创建于:{json_file_path}。操作耗时 {elapsed_time:.6f} 秒。")


    @staticmethod
    def json_to_csv(json_file_path, csv_file_path=None):
        start_time = time.time()
        
        # 如果没有提供完整路径,尝试在当前目录查找文件
        if not os.path.isfile(json_file_path):
            json_file_path = os.path.join(os.getcwd(), json_file_path)
        
        # 确定JSON文件所在的目录和文件名
        directory, json_filename = os.path.split(json_file_path)
        filename, _ = os.path.splitext(json_filename)
        
        # 如果没有指定csv_file_path,构建CSV文件路径
        if csv_file_path is None:
            csv_file_path = os.path.join(directory, filename + '.csv')
        elif not os.path.isabs(csv_file_path):  # 如果提供的是相对路径
            csv_file_path = os.path.join(os.getcwd(), csv_file_path)
        
        # 读取JSON文件并转换为CSV
        with open(json_file_path, 'r', encoding='utf-8') as json_file:
            data = json.load(json_file)
        
        # 写入CSV文件
        if data:
            with open(csv_file_path, 'w', encoding='utf-8', newline='') as csv_file:
                writer = csv.DictWriter(csv_file, fieldnames=data[0].keys())
                writer.writeheader()
                for row in data:
                    writer.writerow(row)
        
        elapsed_time = time.time() - start_time
        print(f"CSV文件已创建于:{csv_file_path}。操作耗时 {elapsed_time:.6f} 秒。")

# 使用示例
# 将CSV转换为JSON
DataConverter.csv_to_json('example.csv')

# 将JSON转换回CSV
DataConverter.json_to_csv('example.json')

这段代码定义了一个名为 DataConverter 的类,它包含两个静态方法:csv_to_jsonjson_to_csv。这两个方法分别用于将 CSV 文件转换为 JSON 格式,以及将 JSON 文件转换回 CSV 格式。下面是对整段代码的详细解释:

  • DataConverter:这是一个工具类,提供了 CSV 和 JSON 文件格式相互转换的功能。

  • 静态方法 csv_to_json(csv_file_path, json_file_path=None):这个方法接受一个 CSV 文件路径作为输入,并将其转换为 JSON 格式。转换后的 JSON 文件路径可以作为第二个参数提供,如果不提供,则默认在 CSV 文件所在的同一目录下创建一个同名的 JSON 文件。

  • 静态方法 json_to_csv(json_file_path, csv_file_path=None):这个方法接受一个 JSON 文件路径作为输入,并将其转换回 CSV 格式。转换后的 CSV 文件路径可以作为第二个参数提供,如果不提供,则默认在 JSON 文件所在的同一目录下创建一个同名的 CSV 文件。

方法详细解释

csv_to_json 方法
  1. 开始计时:记录方法开始执行的时间,以便计算整个操作的耗时。
  2. 处理文件路径
    • 首先检查提供的 CSV 文件路径是否指向一个实际存在的文件。如果不是,尝试在当前工作目录下查找该文件。
    • 提取 CSV 文件的目录和文件名,用于确定输出文件的位置和名称。
    • 如果未提供 JSON 文件路径,或提供的是相对路径,构建输出 JSON 文件的完整路径。
  3. 读取 CSV 并转换为 JSON
    • 使用 csv.DictReader 读取 CSV 文件,将每行转换为字典对象,并添加到列表中。
    • 将列表转换为 JSON 格式的字符串,并写入到指定的 JSON 文件中。
  4. 记录耗时并输出结果:计算操作耗时,并输出转换后的 JSON 文件路径和耗时信息。
json_to_csv 方法
  1. 开始计时:同上,记录方法开始执行的时间。
  2. 处理文件路径
    • 类似于 csv_to_json 方法,检查和处理 JSON 文件路径,确定输出 CSV 文件的位置和名称。
  3. 读取 JSON 并转换为 CSV
    • 读取 JSON 文件内容,将其解析为 Python 对象(通常是列表或字典)。
    • 使用 csv.DictWriter 将解析后的数据写入到 CSV 文件中。首先写入表头(即字典的键),然后写入每行数据(字典的值)。
  4. 记录耗时并输出结果:计算操作耗时,并输出转换后的 CSV 文件路径和耗时信息。

使用示例

代码的最后部分展示了如何使用 DataConverter 类将一个 CSV 文件转换为 JSON 格式,以及如何将一个 JSON 文件转换回 CSV 格式。这通过调用类的静态方法并传入相应的文件路径来实现。

附件

1. 战斗事件表(BattleEvents)

这个表用于记录战斗中发生的所有事件,每一行代表一个独立的事件。

字段名称 数据类型 描述 EventID INT PRIMARY KEY AUTO_INCREMENT 事件的唯一标识符 BattleID INT 关联的战斗ID,用于将事件与特定的战斗关联起来 Timestamp DATETIME 事件发生的时间戳 EventType VARCHAR(50) 事件类型(如“攻击”、“技能释放”、“死亡”等) ActorID INT 事件发起者的ID(例如攻击者或技能释放者) TargetID INT 事件目标的ID(如被攻击者或技能作用对象),如果适用 SkillID INT 使用的技能ID,如果事件类型是技能释放 Damage INT 造成的伤害量,如果适用 Effect VARCHAR(255) 特殊效果的描述(如“眩晕”、“冰冻”等),如果适用 Outcome VARCHAR(255) 事件结果的简短描述,如“击杀”、“技能被闪避”等

2. 战斗表(Battles)

这个表用于记录每一场战斗的基本信息。

字段名称 数据类型 描述 BattleID INT PRIMARY KEY AUTO_INCREMENT 战斗的唯一标识符 StartTime DATETIME 战斗开始的时间戳 EndTime DATETIME 战斗结束的时间戳 WinnerID INT 获胜方的ID LoserID INT 失败方的ID Duration INT 战斗持续时间(秒)

3. 角色表(Characters)

这个表用于记录战斗中出现的角色(包括英雄和单位)的信息。

字段名称 数据类型 描述 CharID INT PRIMARY KEY AUTO_INCREMENT 角色的唯一标识符 Name VARCHAR(50) 角色的名称 Type VARCHAR(50) 角色的类型(如“英雄”、“单位”) Icon VARCHAR(255) 角色图标的路径

4. 技能表(Skills)

这个表用于记录游戏中技能的信息。

字段名称 数据类型 描述 SkillID INT PRIMARY KEY AUTO_INCREMENT 技能的唯一标识符 Name VARCHAR(50) 技能的名称 Description VARCHAR(255) 技能的描述 Icon VARCHAR(255) 技能图标的路径