Files
tuiche/lib/common/util/DailyLogUtils.dart
2025-09-11 09:38:14 +08:00

181 lines
5.8 KiB
Dart
Raw Permalink 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:archive/archive_io.dart';
import 'package:path_provider/path_provider.dart';
import 'package:intl/intl.dart';
import 'package:share_plus/share_plus.dart';
import 'dart:convert';
class DailyLogUtils {
// 获取当天日志文件路径
static Future<File> _getLogFile() async {
final dir = await getApplicationDocumentsDirectory();
final date = DateFormat('yyyy-MM-dd').format(DateTime.now());
final file = File('${dir.path}/$date.log');
if (!await file.exists()) {
await file.create(recursive: true);
}
return file;
}
// 写日志核心方法,带日志等级,固定 UTF-8
static Future<void> _writeLogWithLevel(String level, String content) async {
final file = await _getLogFile();
final now = DateTime.now();
final time = DateFormat('HH:mm:ss').format(now);
final logLine = '[$time][$level] $content\n';
await file.writeAsString(logLine, mode: FileMode.append, encoding: utf8);
}
// Info 日志
static Future<void> writeLog(String content) async {
print("[dailylog-->info] $content");
await _writeLogWithLevel('INFO', content);
}
// Warning 日志
static Future<void> writeWarning(String content) async {
print("[dailylog-->warning] $content");
await _writeLogWithLevel('WARNING', content);
}
// Error 日志
static Future<void> writeError(String content) async {
print("[dailylog-->error] $content");
await _writeLogWithLevel('ERROR', content);
}
// Debug 日志
static Future<void> writeDebug(String content) async {
print("[dailylog-->debug] $content");
await _writeLogWithLevel('DEBUG', content);
}
// 读取当天日志,容错 UTF-8
static Future<String> readTodayLog() async {
final file = await _getLogFile();
try {
return await file.readAsString(encoding: utf8);
} catch (e) {
final bytes = await file.readAsBytes();
return utf8.decode(bytes, allowMalformed: true);
}
}
// 获取所有日志文件
static Future<List<FileSystemEntity>> listLogFiles() async {
final dir = await getApplicationDocumentsDirectory();
final files = dir.listSync();
return files.where((f) => f.path.endsWith('.log')).toList();
}
// 清除所有日志
static Future<void> clearAllLogs() async {
final files = await listLogFiles();
for (final f in files) {
await File(f.path).delete();
}
}
// 获取指定日期范围内日志文件
static Future<List<File>> getLogsBetween(
DateTime fromDate, DateTime toDate) async {
final dir = await getApplicationDocumentsDirectory();
final logFiles = <File>[];
final dateFormat = DateFormat('yyyy-MM-dd');
for (DateTime date = fromDate;
!date.isAfter(toDate);
date = date.add(Duration(days: 1))) {
final file = File('${dir.path}/${dateFormat.format(date)}.log');
if (await file.exists()) logFiles.add(file);
}
return logFiles;
}
// 读取日期范围内日志,合并返回
static Future<String> readLogsByDateRange(
DateTime fromDate, DateTime toDate) async {
try {
final dir = await getApplicationDocumentsDirectory();
final dateFormat = DateFormat('yyyy-MM-dd');
String combinedLogs = '';
for (DateTime date = fromDate;
!date.isAfter(toDate);
date = date.add(Duration(days: 1))) {
final file = File('${dir.path}/${dateFormat.format(date)}.log');
if (await file.exists()) {
String content;
try {
content = await file.readAsString(encoding: utf8);
} catch (_) {
final bytes = await file.readAsBytes();
content = utf8.decode(bytes, allowMalformed: true);
}
combinedLogs += '日志日期: ${dateFormat.format(date)}\n$content\n\n';
}
}
return combinedLogs.isNotEmpty ? combinedLogs : '该时间段内没有日志记录';
} catch (e) {
return '读取日志失败: $e';
}
}
// 导出所有日志为 zip 并分享(系统分享)
static Future<void> exportAllLogs() async {
try {
final dir = await getApplicationDocumentsDirectory();
final dateStr = DateFormat('yyyy-MM-dd_HH-mm-ss').format(DateTime.now());
final zipPath = '${dir.path}/logs_$dateStr.zip';
final archive = Archive();
// 遍历日志文件
final logFiles = dir
.listSync()
.whereType<File>()
.where((f) => f.path.endsWith('.log') && f.existsSync());
if (logFiles.isEmpty) {
print("没有日志文件可压缩!");
return;
}
for (var file in logFiles) {
final name = file.path.split('/').last;
final bytes = await file.readAsBytes(); // 读取原始字节
final content =
utf8.decode(bytes, allowMalformed: true); // 转 UTF-8允许非 UTF-8
final utf8Bytes = utf8.encode(content); // 写入压缩包
archive.addFile(ArchiveFile(name, utf8Bytes.length, utf8Bytes));
print("添加日志文件: ${file.path}, 大小: ${utf8Bytes.length}");
}
// 写入 zip 文件
final zipData = ZipEncoder().encode(archive);
final zipFile = File(zipPath);
await zipFile.writeAsBytes(zipData!);
print("压缩包生成成功: ${zipFile.path}, 大小: ${await zipFile.length()} 字节");
// 分享
await Share.shareXFiles([XFile(zipFile.path)], text: '应用日志打包 $dateStr');
} catch (e) {
print('导出日志失败: $e');
}
}
static Future<void> printLog(String content) async {
print("logger---> $content");
// 如果你希望顺便写入 info 日志,也可以取消下面注释
// await writeLog(content);
}
static Future<String> readLogByDate(DateTime date) async {
// 调用 readLogsByDateRangefromDate 和 toDate 都是同一天
return await readLogsByDateRange(date, date);
}
}