79 lines
2.4 KiB
Python
79 lines
2.4 KiB
Python
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import json
|
|
import logging
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def read_json_file(file_path: str | Path) -> dict[str, Any]:
|
|
"""读取 JSON 文件并返回字典。"""
|
|
file_path = Path(file_path)
|
|
if not file_path.exists():
|
|
raise FileNotFoundError(f"File not found: {file_path}")
|
|
return json.loads(file_path.read_text(encoding="utf-8"))
|
|
|
|
|
|
def write_json_file(file_path: str | Path, data: dict[str, Any], *, indent: int = 2) -> None:
|
|
"""将字典写入 JSON 文件。"""
|
|
file_path = Path(file_path)
|
|
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
file_path.write_text(json.dumps(data, indent=indent, ensure_ascii=False), encoding="utf-8")
|
|
|
|
|
|
def compute_file_hash(file_path: str | Path, algorithm: str = "sha256") -> str:
|
|
"""计算文件的哈希值。"""
|
|
file_path = Path(file_path)
|
|
if not file_path.exists():
|
|
raise FileNotFoundError(f"File not found: {file_path}")
|
|
|
|
hasher = hashlib.new(algorithm)
|
|
hasher.update(file_path.read_bytes())
|
|
return hasher.hexdigest()
|
|
|
|
|
|
def ensure_directory(dir_path: str | Path) -> Path:
|
|
"""确保目录存在,如果不存在则创建。"""
|
|
path = Path(dir_path)
|
|
path.mkdir(parents=True, exist_ok=True)
|
|
return path
|
|
|
|
|
|
def safe_write_file(file_path: str | Path, content: str, *, encoding: str = "utf-8") -> None:
|
|
"""安全写入文件:先写入临时文件,再原子替换。"""
|
|
file_path = Path(file_path)
|
|
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
temp_path = file_path.with_suffix(f"{file_path.suffix}.tmp")
|
|
temp_path.write_text(content, encoding=encoding)
|
|
temp_path.replace(file_path)
|
|
|
|
|
|
def list_files(
|
|
directory: str | Path,
|
|
pattern: str = "*",
|
|
*,
|
|
recursive: bool = False,
|
|
) -> list[Path]:
|
|
"""列出目录中的文件。"""
|
|
directory = Path(directory)
|
|
if not directory.exists():
|
|
return []
|
|
|
|
if recursive:
|
|
return list(directory.rglob(pattern))
|
|
return list(directory.glob(pattern))
|
|
|
|
|
|
def delete_file(file_path: str | Path, *, missing_ok: bool = True) -> bool:
|
|
"""删除文件。"""
|
|
file_path = Path(file_path)
|
|
try:
|
|
file_path.unlink(missing_ok=missing_ok)
|
|
return True
|
|
except OSError:
|
|
logger.warning("Failed to delete file: %s", file_path)
|
|
return False
|