Files

98 lines
4.1 KiB
C#
Raw Permalink Normal View History

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using PCL.Core.Logging;
using fNbt;
namespace PCL.Core.Minecraft;
/// <summary>
/// 提供 NBT 文件的异步读写操作。
/// </summary>
public static class NbtFileHandler {
/// <summary>
/// 异步读取 NBT 文件中指定 Tag 内容。
/// </summary>
/// <typeparam name="T">要读取的 NbtTag 类型,必须继承自 NbtTag。</typeparam>
/// <param name="filePath">目标文件路径(完整或相对)。</param>
/// <param name="tagName">要读取的 NbtTag 的标签名称。</param>
/// <param name="cancelToken">取消操作的令牌。</param>
/// <returns>一个指定类型的 NbtTag 对象,如果文件或标签不存在则返回 null。</returns>
public static async Task<T?> ReadTagInNbtFileAsync<T>(string filePath, string tagName, CancellationToken cancelToken = default) where T: NbtTag {
try {
var fullPath = Path.GetFullPath(filePath);
if (!File.Exists(fullPath)) {
LogWrapper.Warn($"NBT 文件不存在:{fullPath}");
return null;
}
const int bufferSize = 4096;
var nbtFile = new NbtFile();
await Task.Run(async () => {
await using var fs = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.Asynchronous);
nbtFile.LoadFromStream(fs, NbtCompression.AutoDetect);
}, cancelToken);
var result = nbtFile.RootTag.Get<T>(tagName);
if (result is null) {
LogWrapper.Warn($"未找到指定的 NBT 标签:{tagName}");
}
return result;
} catch (OperationCanceledException) {
LogWrapper.Info($"读取 NBT 文件操作被取消:{filePath}");
return null;
} catch (Exception ex) {
LogWrapper.Warn(ex, $"读取 NBT 文件出错:{filePath}");
return null;
}
}
/// <summary>
/// 异步将指定标签写入 NBT 文件的 RootTag 中。(文件可以不存在)
/// </summary>
/// <param name="nbtTag">要写入文件的 NbtTag 对象。</param>
/// <param name="filePath">目标文件路径(完整或相对)。</param>
/// <param name="compression">NBT 文件的压缩类型,默认为 NbtCompression.None。</param>
/// <param name="cancelToken">取消操作的令牌。</param>
/// <returns>返回操作是否成功。</returns>
public static async Task<bool> WriteTagInNbtFileAsync(NbtTag nbtTag, string filePath, NbtCompression compression = NbtCompression.None, CancellationToken cancelToken = default) {
try {
var fullPath = Path.GetFullPath(filePath);
var directoryName = Path.GetDirectoryName(fullPath);
if (string.IsNullOrEmpty(directoryName)) {
LogWrapper.Warn($"无法获取目标目录:{fullPath}");
return false;
}
Directory.CreateDirectory(directoryName);
var rootTag = new NbtCompound { Name = "" };
rootTag.Add(nbtTag);
var nbtFile = new NbtFile(rootTag);
const int bufferSize = 4096;
await Task.Run(async () => {
await using var fs = new FileStream(fullPath, FileMode.Create, FileAccess.Write, FileShare.Read, bufferSize, FileOptions.Asynchronous);
nbtFile.SaveToStream(fs, compression);
}, cancelToken);
LogWrapper.Info($"NBT 文件成功保存于:{fullPath}");
return true;
} catch (OperationCanceledException) {
LogWrapper.Info($"写入 NBT 文件操作被取消:{filePath}");
return false;
} catch (NbtFormatException ex) {
LogWrapper.Warn(ex, $"NBT 格式错误:{filePath}");
return false;
} catch (IOException ex) {
LogWrapper.Warn(ex, $"文件操作错误:{filePath}");
return false;
} catch (Exception ex) {
LogWrapper.Warn(ex, $"写入 NBT 文件出错:{filePath}");
return false;
}
}
}