#region License /* FNA - XNA4 Reimplementation for Desktop Platforms * Copyright 2009-2016 Ethan Lee and the MonoGame Team * * Released under the Microsoft Public License. * See LICENSE for details. */ #endregion #region Using Statements using System; using System.IO; #endregion namespace Microsoft.Xna.Framework.Storage { /// /// Contains a logical collection of files used for user-data storage. /// /// /// MSDN documentation contains related conceptual article: /// http://msdn.microsoft.com/en-us/library/bb200105.aspx#ID4EDB /// public class StorageContainer : IDisposable { #region Public Properties /// /// The title's (i.e. "game's") filename. /// public string DisplayName { get; private set; } /// /// A bool value indicating whether the instance has been disposed. /// public bool IsDisposed { get; private set; } /// /// The that holds logical files for the container. /// public StorageDevice StorageDevice { get; private set; } #endregion #region Internal Variables private readonly string storagePath; #endregion #region Events /// /// Fired when is called or object is finalized or collected /// by the garbage collector. /// public event EventHandler Disposing; #endregion #region Internal Constructors /// /// Initializes a new instance of the class. /// /// The attached storage-device. /// The title's filename. /// The path of the storage root folder /// /// The index of the player whose data is being saved, or null if data is for all /// players. /// internal StorageContainer( StorageDevice device, string name, string rootPath, PlayerIndex? playerIndex ) { if (string.IsNullOrEmpty(name)) { throw new ArgumentNullException("A title name has to be provided in parameter name."); } StorageDevice = device; DisplayName = name; // Generate the path of the game's savefolder storagePath = Path.Combine( rootPath, Path.GetFileNameWithoutExtension( AppDomain.CurrentDomain.FriendlyName ) ); // Create the root folder for all titles, if needed. if (!Directory.Exists(storagePath)) { Directory.CreateDirectory(storagePath); } storagePath = Path.Combine(storagePath, name); // Create the sub-folder for this container/title's files, if needed. if (!Directory.Exists(storagePath)) { Directory.CreateDirectory(storagePath); } /* There are two types of subfolders within a StorageContainer. * The first is a PlayerX folder, X being a specified PlayerIndex. * The second is AllPlayers, when PlayerIndex is NOT specified. * Basically, you should NEVER expect to have ANY file in the root * game save folder. * -flibit */ if (playerIndex.HasValue) { storagePath = Path.Combine(storagePath, "Player" + ((int) playerIndex.Value + 1).ToString()); } else { storagePath = Path.Combine(storagePath, "AllPlayers"); } // Create the player folder, if needed. if (!Directory.Exists(storagePath)) { Directory.CreateDirectory(storagePath); } } #endregion #region Public Dispose Method /// /// Disposes un-managed objects referenced by this object. /// public void Dispose() { if (Disposing != null) { Disposing(this, null); } IsDisposed = true; } #endregion #region Public Create Methods /// /// Creates a new directory in the storage-container. /// /// Relative path of the directory to be created. public void CreateDirectory(string directory) { if (string.IsNullOrEmpty(directory)) { throw new ArgumentNullException("Parameter directory must contain a value."); } // Directory name is relative, so combine with our path. string dirPath = Path.Combine(storagePath, directory); // Now let's try to create it. if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } } /// /// Creates a file in the storage-container. /// /// Relative path of the file to be created. /// Returns for the created file. public Stream CreateFile(string file) { if (string.IsNullOrEmpty(file)) { throw new ArgumentNullException("Parameter file must contain a value."); } // File name is relative, so combine with our path. string filePath = Path.Combine(storagePath, file); // Return a new file with read/write access. return File.Create(filePath); } #endregion #region Public Delete Methods /// /// Deletes specified directory from the storage-container. /// /// The relative path of the directory to be deleted. public void DeleteDirectory(string directory) { if (string.IsNullOrEmpty(directory)) { throw new ArgumentNullException("Parameter directory must contain a value."); } // Directory name is relative, so combine with our path. string dirPath = Path.Combine(storagePath, directory); // Now let's try to delete it. Directory.Delete(dirPath); } /// /// Deletes a file from the storage-container. /// /// The relative path of the file to be deleted. public void DeleteFile(string file) { if (string.IsNullOrEmpty(file)) { throw new ArgumentNullException("Parameter file must contain a value."); } // Relative, so combine with our path. string filePath = Path.Combine(storagePath, file); // Now let's try to delete it. File.Delete(filePath); } #endregion #region Public Exists Methods /// /// Returns true if specified path exists in the storage-container, false otherwise. /// /// The relative path of the directory to query for. /// True if the directory path exists, false otherwise. public bool DirectoryExists(string directory) { if (string.IsNullOrEmpty(directory)) { throw new ArgumentNullException("Parameter directory must contain a value."); } // Directory name is relative, so combine with our path. string dirPath = Path.Combine(storagePath, directory); return Directory.Exists(dirPath); } /// /// Returns true if the specified file exists in the storage-container, false otherwise. /// /// The relative path of the file to query for. /// True if file exists, false otherwise. public bool FileExists(string file) { if (string.IsNullOrEmpty(file)) { throw new ArgumentNullException("Parameter file must contain a value."); } // File name is relative, so combine with our path. string filePath = Path.Combine(storagePath, file); // Return a new file with read/write access. return File.Exists(filePath); } #endregion #region Public GetNames Methods /// /// Returns an array of the directory names in the storage-container. /// /// Array of directory names. public string[] GetDirectoryNames() { string[] names = Directory.GetDirectories(storagePath); for (int i = 0; i < names.Length; i += 1) { names[i] = names[i].Substring(storagePath.Length + 1); } return names; } /// /// Returns an array of directory names with given search pattern. /// /// /// A search pattern that supports single-character ("?") and multicharacter ("*") /// wildcards. /// /// Array of matched directory names. public string[] GetDirectoryNames(string searchPattern) { if (string.IsNullOrEmpty(searchPattern)) { throw new ArgumentNullException("Parameter searchPattern must contain a value."); } string[] names = Directory.GetDirectories(storagePath, searchPattern); for (int i = 0; i < names.Length; i += 1) { names[i] = names[i].Substring(storagePath.Length + 1); } return names; } /// /// Returns an array of file names in the storage-container. /// /// Array of file names. public string[] GetFileNames() { string[] names = Directory.GetFiles(storagePath); for (int i = 0; i < names.Length; i += 1) { names[i] = names[i].Substring(storagePath.Length + 1); } return names; } /// /// Returns an array of file names with given search pattern. /// /// /// A search pattern that supports single-character ("?") and multicharacter ("*") /// wildcards. /// /// Array of matched file names. public string[] GetFileNames(string searchPattern) { if (string.IsNullOrEmpty(searchPattern)) { throw new ArgumentNullException("Parameter searchPattern must contain a value."); } string[] names = Directory.GetFiles(storagePath, searchPattern); for (int i = 0; i < names.Length; i += 1) { names[i] = names[i].Substring(storagePath.Length + 1); } return names; } #endregion #region Public OpenFile Methods /// /// Opens a file contained in storage-container. /// /// Relative path of the file. /// /// that specifies how the file is to be opened. /// /// object for the opened file. public Stream OpenFile( string file, FileMode fileMode ) { return OpenFile( file, fileMode, FileAccess.ReadWrite, FileShare.ReadWrite ); } /// /// Opens a file contained in storage-container. /// /// Relative path of the file. /// /// that specifies how the file is to be opened. /// /// /// that specifies access mode. /// /// object for the opened file. public Stream OpenFile( string file, FileMode fileMode, FileAccess fileAccess ) { return OpenFile( file, fileMode, fileAccess, FileShare.ReadWrite ); } /// /// Opens a file contained in storage-container. /// /// Relative path of the file. /// /// that specifies how the file is to be opened. /// /// /// that specifies access mode. /// /// A bitwise combination of /// enumeration values that specifies access modes for other stream objects. /// object for the opened file. public Stream OpenFile( string file, FileMode fileMode, FileAccess fileAccess, FileShare fileShare ) { if (string.IsNullOrEmpty(file)) { throw new ArgumentNullException("Parameter file must contain a value."); } // Filename is relative, so combine with our path. string filePath = Path.Combine(storagePath, file); return File.Open(filePath, fileMode, fileAccess, fileShare); } #endregion } }