Files
Hasebe/Library/PackageCache/com.unity.addressables@42676f2a154e/Editor/AutoGroupGenerator/Util/FileUtils.cs
T
2026-09-21 12:15:57 +03:00

174 lines
5.5 KiB
C#

using System;
using System.Collections;
using System.IO;
using System.Text;
using UnityEngine;
namespace AutoGroupGenerator
{
/// <summary>
/// File system helpers for synchronous and coroutine-based IO.
/// </summary>
public static class FileUtils
{
#region Static Methods
/// <summary>
/// Loads all text from a file.
/// </summary>
/// <param name="filePath">Path to the file to read.</param>
/// <returns>The file contents as text.</returns>
public static string LoadFromFile(string filePath)
{
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
using (BufferedStream bs = new BufferedStream(fs))
using (StreamReader sr = new StreamReader(bs, Encoding.UTF8))
{
return sr.ReadToEnd();
}
}
/// <summary>
/// Saves text to a file, creating directories as needed.
/// </summary>
/// <param name="filePath">Path to the file to write.</param>
/// <param name="data">Text to write.</param>
public static void SaveToFile(string filePath, string data)
{
EnsureDirectoryExist(filePath);
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
using (BufferedStream bs = new BufferedStream(fs))
using (StreamWriter sw = new StreamWriter(bs, Encoding.UTF8))
{
sw.Write(data);
}
}
/// <summary>
/// Loads JSON data from a file asynchronously as a coroutine.
/// </summary>
/// <typeparam name="T">Type to deserialize.</typeparam>
/// <param name="filePath">Path to the file to read.</param>
/// <param name="onComplete">Callback invoked with the deserialized data.</param>
/// <param name="bytesPerStep">Maximum characters read per frame.</param>
/// <returns>An enumerator for coroutine execution.</returns>
public static IEnumerator LoadFromFileAsync<T>(string filePath, Action<T> onComplete, int bytesPerStep = 1024 * 1024)
{
if (!File.Exists(filePath))
{
Debug.LogError("File not found: " + filePath);
yield break;
}
StreamReader streamReader = new StreamReader(filePath);
StringBuilder data = new StringBuilder();
while (true)
{
try
{
char[] buffer = new char[bytesPerStep];
int bytesRead = streamReader.Read(buffer, 0, bytesPerStep);
if (bytesRead > 0)
{
data.Append(buffer, 0, bytesRead);
}
else
{
streamReader.Close();
onComplete?.Invoke(JsonUtility.FromJson<T>(data.ToString()));
break;
}
}
catch (Exception ex)
{
Debug.LogError($"{nameof(LoadFromFileAsync)} Error : {ex.Message}");
streamReader.Close();
break;
}
yield return null;
}
}
/// <summary>
/// Saves text to a file asynchronously as a coroutine.
/// </summary>
/// <param name="serializedData">Text to write.</param>
/// <param name="filePath">Path to the file to write.</param>
/// <param name="onComplete">Callback invoked with success state.</param>
/// <param name="bytesPerStep">Maximum characters written per frame.</param>
/// <returns>An enumerator for coroutine execution.</returns>
public static IEnumerator SaveToFileAsync(string serializedData, string filePath,
Action<bool> onComplete = null, int bytesPerStep = 1024 * 1024)
{
EnsureDirectoryExist(filePath);
var data = new StringBuilder(serializedData);
StreamWriter streamWriter = new StreamWriter(filePath, false, Encoding.UTF8);
while (data.Length > 0)
{
try
{
int lengthToWrite = Math.Min(bytesPerStep, data.Length);
char[] buffer = new char[lengthToWrite];
data.CopyTo(0, buffer, 0, lengthToWrite);
streamWriter.Write(buffer, 0, lengthToWrite);
data.Remove(0, lengthToWrite);
}
catch (Exception ex)
{
Debug.LogError($"{nameof(SaveToFileAsync)} Error : {ex.Message}");
streamWriter?.Close();
onComplete?.Invoke(false);
yield break;
}
yield return null;
}
streamWriter.Close();
onComplete?.Invoke(true);
}
/// <summary>
/// Ensures the directory for the specified file path exists.
/// </summary>
/// <param name="filePath">File path whose directory should exist.</param>
public static void EnsureDirectoryExist(string filePath)
{
string directoryPath = Path.GetDirectoryName(filePath);
if (!string.IsNullOrEmpty(directoryPath) && !Directory.Exists(directoryPath))
{
Directory.CreateDirectory(directoryPath);
}
}
#endregion
}
}