# -*- coding: utf-8 -*-#
# -------------------------------------------------------------------------------
# Name: Tools
# Description:
# Author: zhangchunhui
# Date: 2019/1/27
# -------------------------------------------------------------------------------
import collections
import os
import sys
import xml.etree.ElementTree as ET
from pip._vendor import chardet
ConfigPath = "./Config/Server"
class DataParser:
def __init__(self, fullFileName, fileName):
"""
读取文件内容
:param fullFileName:
:param fileName:
"""
# print(fullFileName)
print(fileName)
# f = open(fullFileName, "rb")
# data = f.read()
# print(chardet.detect(data))
# f.close()
self.fileName = fileName.split('.')[0]
file = open(fullFileName, 'r', encoding='GB18030')
self.strCounts = file.read()
self.list = self.strCounts.split('\n')
file.close()
def dealTitel(self):
"""
处理标题
:return:
"""
self.titleDic = collections.OrderedDict()
self.effectrow = []
if (len(self.list) > 4):
titleList = self.list[0].split('\t')
titleTypeList = self.list[1].split('\t')
if titleList.__len__() != titleTypeList.__len__():
print("标题有问题 请检查:" + self.fileName)
return
for i in range(0, len(titleList)):
titleStrName = titleList[i].strip()
titleStrType = titleTypeList[i].strip()
if (len(titleStrName) > 0 and len(titleStrType) > 0):
self.titleDic[titleStrName] = titleStrType
self.effectrow.append(i)
else:
print("配置文件出问题 请检查%s", self.fileName)
def printTest(self):
"""
输出查看
:return:
"""
for i in range(0, len(self.list)):
str1 = self.list[i]
print(str1)
def writeProto3(self):
"""
写出protoBuff3文件
:return:
"""
dom = ET.parse('ProtoTemplate.xml')
importListStr = dom.getiterator("import")
cousntStr = importListStr[0].text
self.protoFileName = self.fileName + ".proto";
cousntStr += "message " + self.fileName
cousntStr += "\n{\n"
i = 1
for titleStr1 in self.titleDic.keys():
cousntStr += " " + getProtoType(self.titleDic[titleStr1]) + " " + titleStr1 + " = " + str(i) + ";\n"
i += 1
cousntStr += "}\n"
cousntStr += "message " + self.fileName + "_ARRAY\n"
cousntStr += "{\n repeated " + self.fileName + " items = 1;";
cousntStr += "\n}\n"
file = open("./protofile/" + self.protoFileName, 'w+', encoding='utf-8')
file.write(cousntStr)
file.close()
def writeUTF8File(self):
"""
写入文件信息
:return:
"""
file = open("./Out/" + self.fileName + ".txt", 'w+', encoding='utf-8')
file.write(self.strCounts)
file.close()
def WritePythonCode(self):
"""
生成proto文件
:return:
"""
command = "protoc --python_out=./ " + "./protofile/" + self.protoFileName
os.system(command)
def DealDataByte(self):
data = ""
try:
self._module_name = self.fileName + "_pb2"
sys.path.append(os.getcwd() + "./protofile")
exec('from ' + self._module_name + ' import *')
self._module = sys.modules[self._module_name]
except Exception as e:
print("Load error" + e + self.fileName)
return
item_array = getattr(self._module, self.fileName + '_ARRAY')()
for i in range(3, len(self.list)):
# print(self.list[i])
# 如果 id 是 空 直接跳过改行
str1 = self.list[i].strip()
if (len(str1) > 0):
str1List = str1.split('\t')
if (len(str1List) > 0 and len(str1List[0]) > 0 and str1List[0].find("#") < 0):
item = item_array.items.add()
self._ParseLine(item, str1List)
data = item_array.SerializeToString()
self.writeDataByte(data)
def _ParseLine(self, item, lineList):
"""
初始化一行数据
:param item:
:return:
"""
i = 0
for key in self.titleDic.keys():
# 如果 id 是 空 直接跳过改行
fild_value = getProtoValue(getProtoType(self.titleDic[key]), lineList[self.effectrow[i]])
item.__setattr__(key, fild_value)
i += 1
def writeDataByte(self, data):
"""
生成byte文件
:param data:
:return:
"""
file_name = self.fileName + ".bin" # self._proto_name.lower() + ".bin"
file = open("./bytedata/" + file_name, 'wb+')
file.write(data)
file.close()
ProtoTypeDic = {"int": "int32", "string": "string", "float": "float"}
def getProtoType(typeStr):
"""
获取类型转换
:param typeStr:
:return:
"""
typeStr = typeStr.lower()
return ProtoTypeDic.get(typeStr, "nothing")
def getProtoValue(typeStr, valueStr):
"""
获取值信息
:param typeStr:
:param valueStr:
:return:
"""
try:
if typeStr == "int32" or typeStr == "int64" \
or typeStr == "uint32" or typeStr == "uint64" \
or typeStr == "sint32" or typeStr == "sint64" \
or typeStr == "fixed32" or typeStr == "fixed64" \
or typeStr == "sfixed32" or typeStr == "sfixed64":
if len(str(typeStr).strip()) <= 0:
return 0
else:
return int(valueStr)
elif typeStr == "double" or typeStr == "float":
if len(str(typeStr).strip()) <= 0:
return float(0)
else:
return float(valueStr)
elif typeStr == "string":
return valueStr
elif typeStr == "bytes":
valueStr = valueStr.encode('utf-8')
return valueStr
else:
return None
except BaseException as e:
print("parse cell(%u, %u) error, please check it, maybe type is wrong." % (typeStr, valueStr))
raise
def gci(filepath):
"""
读取所有的txt 文件
:param filepath:
:return:
"""
files = os.listdir(filepath)
for fi in files:
fi_d = os.path.join(filepath, fi)
if os.path.isdir(fi_d):
gci(fi_d)
else:
txtInfo = DataParser(fi_d, fi)
# txtInfo.writeUTF8File()
# txtInfo.printTest()
txtInfo.dealTitel()
txtInfo.writeProto3()
txtInfo.WritePythonCode()
txtInfo.DealDataByte()
if __name__ == '__main__':
gci(ConfigPath)
Python通过protbuf 处理txt配置。序列化和反序列化
最新推荐文章于 2025-02-11 17:15:09 发布
本文介绍了一个用于解析特定格式配置文件的工具,并能自动生成ProtoBuf定义文件及对应的序列化字节码,支持从配置文件中读取数据并转换为ProtoBuf消息格式,便于在网络传输和数据持久化中使用。

3万+

被折叠的 条评论
为什么被折叠?



