swagger_generator_flutter/lib/utils/file_utils.dart

457 lines
12 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:io';
import 'package:path/path.dart' as path;
/// 文件工具类
/// 提供文件操作、目录管理和代码格式化功能
class FileUtils {
/// 确保目录存在
static Future<Directory> ensureDirectoryExists(String dirPath) async {
final directory = Directory(dirPath);
if (!await directory.exists()) {
await directory.create(recursive: true);
}
return directory;
}
/// 安全写入文件
static Future<void> safeWriteFile(String filePath, String content) async {
try {
final file = File(filePath);
final directory = file.parent;
// 确保目录存在
if (!await directory.exists()) {
await directory.create(recursive: true);
}
// 写入文件
await file.writeAsString(content);
} catch (e) {
throw FileSystemException('写入文件失败: $filePath', filePath);
}
}
/// 安全读取文件
static Future<String> safeReadFile(String filePath) async {
try {
final file = File(filePath);
if (!await file.exists()) {
throw FileSystemException('文件不存在: $filePath', filePath);
}
return await file.readAsString();
} catch (e) {
throw FileSystemException('读取文件失败: $filePath', filePath);
}
}
/// 检查文件是否存在
static Future<bool> fileExists(String filePath) async {
return await File(filePath).exists();
}
/// 检查目录是否存在
static Future<bool> directoryExists(String dirPath) async {
return await Directory(dirPath).exists();
}
/// 删除文件(如果存在)
static Future<void> deleteFileIfExists(String filePath) async {
final file = File(filePath);
if (await file.exists()) {
await file.delete();
}
}
/// 删除目录(如果存在)
static Future<void> deleteDirectoryIfExists(String dirPath) async {
final directory = Directory(dirPath);
if (await directory.exists()) {
await directory.delete(recursive: true);
}
}
/// 复制文件
static Future<void> copyFile(
String sourcePath, String destinationPath) async {
try {
final sourceFile = File(sourcePath);
final destinationFile = File(destinationPath);
if (!await sourceFile.exists()) {
throw FileSystemException('源文件不存在: $sourcePath', sourcePath);
}
// 确保目标目录存在
final destinationDir = destinationFile.parent;
if (!await destinationDir.exists()) {
await destinationDir.create(recursive: true);
}
await sourceFile.copy(destinationPath);
} catch (e) {
throw FileSystemException('复制文件失败: $sourcePath -> $destinationPath',
sourcePath, e is OSError ? e : null);
}
}
/// 移动文件
static Future<void> moveFile(
String sourcePath, String destinationPath) async {
try {
final sourceFile = File(sourcePath);
final destinationFile = File(destinationPath);
if (!await sourceFile.exists()) {
throw FileSystemException('源文件不存在: $sourcePath', sourcePath);
}
// 确保目标目录存在
final destinationDir = destinationFile.parent;
if (!await destinationDir.exists()) {
await destinationDir.create(recursive: true);
}
await sourceFile.rename(destinationPath);
} catch (e) {
throw FileSystemException('移动文件失败: $sourcePath -> $destinationPath',
sourcePath, e is OSError ? e : null);
}
}
/// 获取文件大小
static Future<int> getFileSize(String filePath) async {
try {
final file = File(filePath);
if (!await file.exists()) {
return 0;
}
return await file.length();
} catch (e) {
return 0;
}
}
/// 获取目录大小
static Future<int> getDirectorySize(String dirPath) async {
try {
final directory = Directory(dirPath);
if (!await directory.exists()) {
return 0;
}
int totalSize = 0;
await for (final entity in directory.list(recursive: true)) {
if (entity is File) {
totalSize += await entity.length();
}
}
return totalSize;
} catch (e) {
return 0;
}
}
/// 列出目录中的文件
static Future<List<String>> listFiles(String dirPath,
{String? extension}) async {
try {
final directory = Directory(dirPath);
if (!await directory.exists()) {
return [];
}
final files = <String>[];
await for (final entity in directory.list()) {
if (entity is File) {
if (extension == null || entity.path.endsWith(extension)) {
files.add(entity.path);
}
}
}
return files;
} catch (e) {
return [];
}
}
/// 列出目录中的子目录
static Future<List<String>> listDirectories(String dirPath) async {
try {
final directory = Directory(dirPath);
if (!await directory.exists()) {
return [];
}
final directories = <String>[];
await for (final entity in directory.list()) {
if (entity is Directory) {
directories.add(entity.path);
}
}
return directories;
} catch (e) {
return [];
}
}
/// 创建备份文件
static Future<String> createBackup(String filePath) async {
try {
final file = File(filePath);
if (!await file.exists()) {
throw FileSystemException('文件不存在: $filePath', filePath);
}
final timestamp = DateTime.now().toIso8601String().replaceAll(':', '-');
final backupPath = '${filePath}.backup.$timestamp';
await file.copy(backupPath);
return backupPath;
} catch (e) {
throw FileSystemException(
'创建备份失败: $filePath', filePath, e is OSError ? e : null);
}
}
/// 恢复备份文件
static Future<void> restoreBackup(
String backupPath, String originalPath) async {
try {
final backupFile = File(backupPath);
if (!await backupFile.exists()) {
throw FileSystemException('备份文件不存在: $backupPath', backupPath);
}
await backupFile.copy(originalPath);
} catch (e) {
throw FileSystemException('恢复备份失败: $backupPath -> $originalPath',
backupPath, e is OSError ? e : null);
}
}
/// 格式化文件路径
static String formatPath(String filePath) {
return path.normalize(filePath);
}
/// 获取文件名(不包括路径)
static String getFileName(String filePath) {
return path.basename(filePath);
}
/// 获取文件名(不包括扩展名)
static String getFileNameWithoutExtension(String filePath) {
return path.basenameWithoutExtension(filePath);
}
/// 获取文件扩展名
static String getFileExtension(String filePath) {
return path.extension(filePath);
}
/// 获取文件所在目录
static String getDirectoryPath(String filePath) {
return path.dirname(filePath);
}
/// 连接路径
static String joinPath(List<String> parts) {
return path.joinAll(parts);
}
/// 获取相对路径
static String getRelativePath(String filePath, String basePath) {
return path.relative(filePath, from: basePath);
}
/// 获取绝对路径
static String getAbsolutePath(String filePath) {
return path.absolute(filePath);
}
/// 检查路径是否为绝对路径
static bool isAbsolute(String filePath) {
return path.isAbsolute(filePath);
}
/// 清理文件名(移除不合法字符)
static String sanitizeFileName(String fileName) {
// 移除或替换不合法的文件名字符
return fileName
.replaceAll(RegExp(r'[<>:"/\\|?*]'), '_')
.replaceAll(RegExp(r'\s+'), '_')
.replaceAll(RegExp(r'_{2,}'), '_')
.replaceAll(RegExp(r'^_|_$'), '');
}
/// 生成唯一文件名
static Future<String> generateUniqueFileName(
String basePath, String fileName) async {
final extension = getFileExtension(fileName);
final nameWithoutExt = getFileNameWithoutExtension(fileName);
String uniqueName = fileName;
int counter = 1;
while (await File(path.join(basePath, uniqueName)).exists()) {
uniqueName = '${nameWithoutExt}_$counter$extension';
counter++;
}
return uniqueName;
}
/// 批量操作文件
static Future<void> batchOperation(
List<String> filePaths,
Future<void> Function(String filePath) operation,
) async {
for (final filePath in filePaths) {
try {
await operation(filePath);
} catch (e) {
print('批量操作失败: $filePath - $e');
}
}
}
/// 查找文件
static Future<List<String>> findFiles(
String searchPath,
String pattern, {
bool recursive = false,
}) async {
try {
final directory = Directory(searchPath);
if (!await directory.exists()) {
return [];
}
final regex = RegExp(pattern);
final foundFiles = <String>[];
await for (final entity in directory.list(recursive: recursive)) {
if (entity is File) {
final fileName = getFileName(entity.path);
if (regex.hasMatch(fileName)) {
foundFiles.add(entity.path);
}
}
}
return foundFiles;
} catch (e) {
return [];
}
}
/// 获取文件修改时间
static Future<DateTime?> getFileModifiedTime(String filePath) async {
try {
final file = File(filePath);
if (!await file.exists()) {
return null;
}
final stat = await file.stat();
return stat.modified;
} catch (e) {
return null;
}
}
/// 比较文件修改时间
static Future<bool> isFileNewer(String filePath1, String filePath2) async {
final time1 = await getFileModifiedTime(filePath1);
final time2 = await getFileModifiedTime(filePath2);
if (time1 == null || time2 == null) {
return false;
}
return time1.isAfter(time2);
}
/// 计算文件哈希
static Future<String?> calculateFileHash(String filePath) async {
try {
final file = File(filePath);
if (!await file.exists()) {
return null;
}
final bytes = await file.readAsBytes();
return bytes.hashCode.toString();
} catch (e) {
return null;
}
}
/// 格式化文件大小
static String formatFileSize(int bytes) {
if (bytes < 1024) {
return '${bytes}B';
} else if (bytes < 1024 * 1024) {
return '${(bytes / 1024).toStringAsFixed(1)}KB';
} else if (bytes < 1024 * 1024 * 1024) {
return '${(bytes / (1024 * 1024)).toStringAsFixed(1)}MB';
} else {
return '${(bytes / (1024 * 1024 * 1024)).toStringAsFixed(1)}GB';
}
}
/// 创建临时文件
static Future<File> createTempFile(String prefix, {String? suffix}) async {
final tempDir = Directory.systemTemp;
final timestamp = DateTime.now().millisecondsSinceEpoch;
final fileName = '$prefix$timestamp${suffix ?? ''}';
return File(path.join(tempDir.path, fileName));
}
/// 清理临时文件
static Future<void> cleanupTempFiles(String pattern) async {
try {
final tempDir = Directory.systemTemp;
final regex = RegExp(pattern);
await for (final entity in tempDir.list()) {
if (entity is File) {
final fileName = getFileName(entity.path);
if (regex.hasMatch(fileName)) {
await entity.delete();
}
}
}
} catch (e) {
print('清理临时文件失败: $e');
}
}
/// 获取项目根目录下的generator目录路径兼容旧版本
static String getProjectRootGeneratorDir() {
final currentDir = Directory.current.path;
return joinPath([currentDir, 'generator']);
}
/// 安全地写入文件(兼容旧版本)
static Future<void> writeFile(String path, String content) async {
await safeWriteFile(path, content);
}
/// 获取目录中的文件列表(兼容旧版本)
static Future<List<FileSystemEntity>> listDirectory(String path) async {
try {
final directory = Directory(path);
if (!await directory.exists()) {
return [];
}
return await directory.list().toList();
} catch (e) {
return [];
}
}
}