198 lines
4.5 KiB
Python
198 lines
4.5 KiB
Python
# 本地文件处理类
|
||
import os
|
||
import sys
|
||
from typing import IO
|
||
|
||
from pywxdump.file.Attachment import Attachment
|
||
|
||
|
||
def singleton(cls):
|
||
instances = {}
|
||
|
||
def create_instance(*args, **kwargs):
|
||
if cls not in instances:
|
||
instances[cls] = cls(*args, **kwargs)
|
||
return instances[cls]
|
||
|
||
return create_instance
|
||
|
||
|
||
@singleton
|
||
class LocalAttachment(Attachment):
|
||
|
||
def open(self, path, mode) -> IO:
|
||
"""
|
||
打开一个文件并返回文件对象。
|
||
|
||
参数:
|
||
path (str): 文件路径。
|
||
mode (str): 打开文件的模式。
|
||
|
||
返回:
|
||
IO: 文件对象。
|
||
"""
|
||
path = self.dealLocalPath(path)
|
||
return open(path, mode)
|
||
|
||
def remove(self, path: str) -> bool:
|
||
"""
|
||
删除文件
|
||
|
||
参数:
|
||
path (str): 文件路径
|
||
|
||
返回:
|
||
bool: 是否删除成功
|
||
"""
|
||
path = self.dealLocalPath(path)
|
||
if not self.exists(path):
|
||
raise FileNotFoundError(f"File not found: {path}")
|
||
|
||
if self.isdir(path):
|
||
raise ValueError(f"Path is not a file: {path}")
|
||
|
||
os.remove(path)
|
||
return True
|
||
|
||
def exists(self, path) -> bool:
|
||
"""
|
||
检查文件或目录是否存在。
|
||
|
||
参数:
|
||
path (str): 文件或目录路径。
|
||
|
||
返回:
|
||
bool: 如果存在返回True,否则返回False。
|
||
"""
|
||
path = self.dealLocalPath(path)
|
||
return os.path.exists(path)
|
||
|
||
def makedirs(self, path) -> bool:
|
||
"""
|
||
创建目录,包括所有中间目录。
|
||
|
||
参数:
|
||
path (str): 目录路径。
|
||
|
||
返回:
|
||
bool: 总是返回True。
|
||
"""
|
||
path = self.dealLocalPath(path)
|
||
os.makedirs(path)
|
||
return True
|
||
|
||
@classmethod
|
||
def join(cls, path: str, *paths: str) -> str:
|
||
"""
|
||
连接一个或多个路径组件。
|
||
|
||
参数:
|
||
path (str): 第一个路径组件。
|
||
*paths (str): 其他路径组件。
|
||
|
||
返回:
|
||
str: 连接后的路径。
|
||
"""
|
||
# 使用os.path.join连接路径
|
||
return os.path.join(path, *paths)
|
||
|
||
@classmethod
|
||
def dirname(cls, path: str) -> str:
|
||
"""
|
||
获取路径的目录名。
|
||
|
||
参数:
|
||
path (str): 文件路径。
|
||
|
||
返回:
|
||
str: 目录名。
|
||
"""
|
||
# 获取路径的目录名
|
||
return os.path.dirname(path)
|
||
|
||
@classmethod
|
||
def basename(cls, path: str) -> str:
|
||
"""
|
||
获取路径的基本名(文件名)。
|
||
|
||
参数:
|
||
path (str): 文件路径。
|
||
|
||
返回:
|
||
str: 基本名(文件名)。
|
||
"""
|
||
# 获取路径的基本名
|
||
return os.path.basename(path)
|
||
|
||
def dealLocalPath(self, path: str) -> str:
|
||
"""
|
||
处理本地路径,替换路径中的分隔符,并根据操作系统进行特殊处理。
|
||
|
||
参数:
|
||
path (str): 文件路径。
|
||
|
||
返回:
|
||
str: 处理后的路径。
|
||
"""
|
||
# 获取当前系统的路径分隔符
|
||
# 将path中的 / 替换为当前系统的分隔符
|
||
path = path.replace('/', os.sep)
|
||
if sys.platform == "win32":
|
||
# 如果是windows系统,且路径长度超过260个字符
|
||
if len(path) >= 260:
|
||
# 添加前缀
|
||
return '\\\\?\\' + path
|
||
else:
|
||
return path
|
||
else:
|
||
return path
|
||
|
||
def isdir(self, path: str) -> bool:
|
||
|
||
"""
|
||
判断是否为目录
|
||
|
||
参数:
|
||
path (str): 文件路径
|
||
|
||
返回:
|
||
bool: 是否为目录
|
||
"""
|
||
# 判断路径是否为目录
|
||
return os.path.isdir(path)
|
||
|
||
def getsize(self, path) -> int:
|
||
"""
|
||
获取文件大小
|
||
|
||
参数:
|
||
path (str): 文件路径
|
||
|
||
返回:
|
||
int: 文件大小
|
||
"""
|
||
if not self.exists(path):
|
||
raise FileNotFoundError(f"File not found: {path}")
|
||
|
||
if os.path.isfile(path):
|
||
return os.path.getsize(path)
|
||
else:
|
||
return self._get_dir_size(path)
|
||
|
||
def _get_dir_size(self, path):
|
||
"""
|
||
计算目录大小
|
||
|
||
参数:
|
||
path (str): 目录路径
|
||
|
||
返回:
|
||
int: 目录大小
|
||
"""
|
||
total_size = 0
|
||
for firePath, surnames, filenames in os.walk(path):
|
||
for f in filenames:
|
||
fp = self.join(firePath, f)
|
||
total_size += os.path.getsize(fp)
|
||
return total_size
|