[Unity (C #)] Implementation that sets a file storage limit and deletes files in order from the oldest date
Introduction
↑ This is the previous application.
What I want to do is as shown in the image below
Set a file storage limit,
The implementation is to delete the oldest file when the limit is exceeded.
demo
It’s a demo right away.
The file to be saved is an image file.
When I checked the storage area in the PC,
The last 3 sheets were firmly preserved.
code
Below is the full text of this process.
Attach to a suitable object
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UniRx;
using UniRx.Triggers;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
///Texture ⇔ Png Image conversion, saving and loading
/// </summary>
public class TexturePngConverter : MonoBehaviour
{
[SerializeField] private Button _saveButton;
[SerializeField] private Button _loadButton;
[SerializeField] private Image _paintImage;
[SerializeField] private Painter _painter;
[SerializeField] private Transform _loadImagesParentTransform;
private const string IMAGE_SAVE_FOLDER = "Image";
private const string PNG = ".png ";
/// <summary>
///Limit storage number
/// </summary>
private const int UPPER_LIMIT_SAVE_PICTURE = 3;
private void Start()
{
//Save button
_saveButton.OnPointerClickAsObservable()
.Subscribe(_ =>
{
//Save
ConvertToPngAndSave(GetSaveDirectoryPath(IMAGE_SAVE_FOLDER), GetSaveFilePath(IMAGE_SAVE_FOLDER, PNG));
//reset
_painter.ResetTexture();
}).AddTo(this);
//Load button
_loadButton.OnPointerClickAsObservable()
.Subscribe(_ => ConvertToTextureAndLoad(GetSaveDirectoryPath(IMAGE_SAVE_FOLDER))).AddTo(this);
}
/// <summary>
///Get the path of the save destination file
/// </summary>
/// <param name="folderName">Delimited folder name</param>
/// <param name="fileType">extension</param>
/// <returns>Destination path</returns>
private string GetSaveFilePath(string folderName, string fileType)
{
return GetSaveDirectoryPath(folderName) + DateTime.Now.ToString("yyyyMMddHHmmss") + fileType;
}
///Get the path of the save destination directory
/// </summary>
/// <param name="folderName">Delimited folder name</param>
/// <returns>Destination path</returns>
private string GetSaveDirectoryPath(string folderName)
{
string directoryPath = Application.persistentDataPath + "/" + folderName + "/";
if (!Directory.Exists(directoryPath))
{
//Create if it doesn't exist yet
Directory.CreateDirectory(directoryPath);
return directoryPath;
}
return directoryPath;
}
/// <summary>
/// "Files under the directory"Returns a list containing all
///The oldest file is[0]Th
/// </summary>
/// <param name="directoryName">Parent directory of files you want to get</param>
/// <returns>A list containing all the files under the specified directory</returns>
private List<string> GetAllFileFromDirectory(string directoryName)
{
//Sort files so that the oldest one comes first
List<string> imageFilePathList = Directory
//Get all files in the Image directory
.GetFiles(directoryName, "*", SearchOption.AllDirectories)
//.DS_Excludes Store
.Where(filePath => Path.GetFileName(filePath) != ".DS_Store")
//Sort in descending order by date
.OrderBy(filePath => File.GetLastWriteTime(filePath).Date)
//Sort in descending order by time within the same date
.ThenBy(filePath => File.GetLastWriteTime(filePath).TimeOfDay)
.ToList();
return imageFilePathList;
}
/// <summary>
///Convert & save to image
///Check the maximum number of saved items
/// </summary>
/// <param name="directoryPath">Directory to check the number of saved</param>
/// <param name="fileSavePath">Destination path</param>
private void ConvertToPngAndSave(string directoryPath, string fileSavePath)
{
//Get a list containing all the files under the specified directory
List<string> imageFilePaths = GetAllFileFromDirectory(directoryPath);
//Check the maximum number of files
if (imageFilePaths.Count >= UPPER_LIMIT_SAVE_PICTURE)
{
//If the limit is reached, delete the oldest file
File.Delete(imageFilePaths[0]);
}
//Convert to png
byte[] bytes = _paintImage.sprite.texture.EncodeToPNG();
//Save
File.WriteAllBytes(fileSavePath, bytes);
}
/// <summary>
///Convert & load to texture
/// </summary>
/// <param name="directoryPath">Parent directory of files you want to load</param>
private void ConvertToTextureAndLoad(string directoryPath)
{
List<Image> imageList = new List<Image>();
//Create an Image list to display multiple images after loading
foreach (Transform child in _loadImagesParentTransform)
{
Image childImage = child.gameObject.GetComponent<Image>();
if (childImage != null)
{
imageList.Add(childImage);
}
}
//Get a list containing all the files under the specified directory
List<string> imageFilePaths = GetAllFileFromDirectory(directoryPath);
//Index counter
int count = 0;
//Load from the list of files in chronological order and apply to Image
foreach (string imageFilePath in imageFilePaths)
{
Debug.Log(imageFilePath);
//Read
byte[] bytes = File.ReadAllBytes(imageFilePath);
//Convert image to texture
Texture2D loadTexture = new Texture2D(2, 2);
loadTexture.LoadImage(bytes);
//Convert textures to sprites
imageList[count].sprite = Sprite.Create(loadTexture, new Rect(0, 0, loadTexture.width, loadTexture.height), Vector2.zero);
//Advance the index counter
count++;
}
}
}
sort
This time, it is ** the date and time (in seconds) where the concept of the old folder was saved **.
Therefore, from the files in the directory
I needed to get the ** oldest save date file **.
For that purpose, get all the files once
The paths of each save destination are sorted in the order of save.
When loading, get the path of all files in the same way
It is passed to the argument of File.ReadAllBytes
.
I was able to write easily using LINQ by referring to the link below.
DateTime.Now
You can use DateTime.Now
to get the current date and the time in seconds.
In this implementation,
By using this date and the time up to the second as the file name
Generating a unique path.
However, when I gave it as a file name as it was, it was a little troublesome.
Interpreted as a directory delimiter like ʻImage / 2020/09/21 17: 12: 43.png
/ (Slash)` will be included.
If you try to save as it is
** I get angry that such a directory does not exist **.
Therefore, we are passing " yyyyMMddHHmmss "
as an argument as shown below.
DateTime.Now.ToString("yyyyMMddHHmmss")
By doing this, it becomes ʻImage / 20200921171710.png`
It is possible to get all numbers up to the number of seconds.
2020/09/21 postscript
GetFiles(directoryName, "*", SearchOption.AllDirectories)
It is better to change the part of to " * "
→ " * .png "
etc.
I received a comment that you can exclude unexpected files.
I will make a note (Thank you!)
in conclusion
No processing failure was seen even when 5,60 sheets were read at once on a mobile terminal.
When the number of sheets reaches hundreds or thousands, it seems that various ingenuity is required.