using System;
using System.Collections;
using System.IO;
using System.Text;
using UnityEngine;
namespace AutoGroupGenerator
{
///
/// File system helpers for synchronous and coroutine-based IO.
///
public static class FileUtils
{
#region Static Methods
///
/// Loads all text from a file.
///
/// Path to the file to read.
/// The file contents as text.
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();
}
}
///
/// Saves text to a file, creating directories as needed.
///
/// Path to the file to write.
/// Text to write.
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);
}
}
///
/// Loads JSON data from a file asynchronously as a coroutine.
///
/// Type to deserialize.
/// Path to the file to read.
/// Callback invoked with the deserialized data.
/// Maximum characters read per frame.
/// An enumerator for coroutine execution.
public static IEnumerator LoadFromFileAsync(string filePath, Action 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(data.ToString()));
break;
}
}
catch (Exception ex)
{
Debug.LogError($"{nameof(LoadFromFileAsync)} Error : {ex.Message}");
streamReader.Close();
break;
}
yield return null;
}
}
///
/// Saves text to a file asynchronously as a coroutine.
///
/// Text to write.
/// Path to the file to write.
/// Callback invoked with success state.
/// Maximum characters written per frame.
/// An enumerator for coroutine execution.
public static IEnumerator SaveToFileAsync(string serializedData, string filePath,
Action 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);
}
///
/// Ensures the directory for the specified file path exists.
///
/// File path whose directory should exist.
public static void EnsureDirectoryExist(string filePath)
{
string directoryPath = Path.GetDirectoryName(filePath);
if (!string.IsNullOrEmpty(directoryPath) && !Directory.Exists(directoryPath))
{
Directory.CreateDirectory(directoryPath);
}
}
#endregion
}
}