Show More
Commit Description:
Various UI improvements.
Commit Description:
Various UI improvements.
References:
File last commit:
Show/Diff file:
Action:
FNA/src/Storage/StorageContainer.cs
420 lines | 11.1 KiB | text/x-csharp | CSharpLexer
420 lines | 11.1 KiB | text/x-csharp | CSharpLexer
r0 | #region License | |||
/* FNA - XNA4 Reimplementation for Desktop Platforms | ||||
* Copyright 2009-2020 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 | ||||
{ | ||||
/// <summary> | ||||
/// Contains a logical collection of files used for user-data storage. | ||||
/// </summary> | ||||
/// <remarks> | ||||
/// MSDN documentation contains related conceptual article: | ||||
/// http://msdn.microsoft.com/en-us/library/bb200105.aspx#ID4EDB | ||||
/// </remarks> | ||||
public class StorageContainer : IDisposable | ||||
{ | ||||
#region Public Properties | ||||
/// <summary> | ||||
/// The title's (i.e. "game's") filename. | ||||
/// </summary> | ||||
public string DisplayName | ||||
{ | ||||
get; | ||||
private set; | ||||
} | ||||
/// <summary> | ||||
/// A bool value indicating whether the instance has been disposed. | ||||
/// </summary> | ||||
public bool IsDisposed | ||||
{ | ||||
get; | ||||
private set; | ||||
} | ||||
/// <summary> | ||||
/// The <see cref="StorageDevice"/> that holds logical files for the container. | ||||
/// </summary> | ||||
public StorageDevice StorageDevice | ||||
{ | ||||
get; | ||||
private set; | ||||
} | ||||
#endregion | ||||
#region Internal Variables | ||||
private readonly string storagePath; | ||||
#endregion | ||||
#region Events | ||||
/// <summary> | ||||
/// Fired when <see cref="Dispose"/> is called or object is finalized or collected | ||||
/// by the garbage collector. | ||||
/// </summary> | ||||
public event EventHandler<EventArgs> Disposing; | ||||
#endregion | ||||
#region Internal Constructors | ||||
/// <summary> | ||||
/// Initializes a new instance of the <see cref="StorageContainer"/> class. | ||||
/// </summary> | ||||
/// <param name='device'>The attached storage-device.</param> | ||||
/// <param name='name'>The title's filename.</param> | ||||
/// <param name='rootPath'>The path of the storage root folder</param> | ||||
/// <param name='playerIndex'> | ||||
/// The index of the player whose data is being saved, or null if data is for all | ||||
/// players. | ||||
/// </param> | ||||
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; | ||||
/* 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 | ||||
*/ | ||||
storagePath = Path.Combine( | ||||
rootPath, // Title folder (EXE name)... | ||||
name, // Container folder... | ||||
playerIndex.HasValue ? // Player folder... | ||||
("Player" + ((int) playerIndex.Value + 1).ToString()) : | ||||
"AllPlayers" | ||||
); | ||||
// Create the folders, if needed. | ||||
if (!Directory.Exists(storagePath)) | ||||
{ | ||||
Directory.CreateDirectory(storagePath); | ||||
} | ||||
} | ||||
#endregion | ||||
#region Public Dispose Method | ||||
/// <summary> | ||||
/// Disposes un-managed objects referenced by this object. | ||||
/// </summary> | ||||
public void Dispose() | ||||
{ | ||||
if (Disposing != null) | ||||
{ | ||||
Disposing(this, null); | ||||
} | ||||
IsDisposed = true; | ||||
} | ||||
#endregion | ||||
#region Public Create Methods | ||||
/// <summary> | ||||
/// Creates a new directory in the storage-container. | ||||
/// </summary> | ||||
/// <param name="directory">Relative path of the directory to be created.</param> | ||||
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); | ||||
} | ||||
} | ||||
/// <summary> | ||||
/// Creates a file in the storage-container. | ||||
/// </summary> | ||||
/// <param name="file">Relative path of the file to be created.</param> | ||||
/// <returns>Returns <see cref="Stream"/> for the created file.</returns> | ||||
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 | ||||
/// <summary> | ||||
/// Deletes specified directory from the storage-container. | ||||
/// </summary> | ||||
/// <param name="directory">The relative path of the directory to be deleted.</param> | ||||
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); | ||||
} | ||||
/// <summary> | ||||
/// Deletes a file from the storage-container. | ||||
/// </summary> | ||||
/// <param name="file">The relative path of the file to be deleted.</param> | ||||
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 | ||||
/// <summary> | ||||
/// Returns true if specified path exists in the storage-container, false otherwise. | ||||
/// </summary> | ||||
/// <param name="directory">The relative path of the directory to query for.</param> | ||||
/// <returns>True if the directory path exists, false otherwise.</returns> | ||||
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); | ||||
} | ||||
/// <summary> | ||||
/// Returns true if the specified file exists in the storage-container, false otherwise. | ||||
/// </summary> | ||||
/// <param name="file">The relative path of the file to query for.</param> | ||||
/// <returns>True if file exists, false otherwise.</returns> | ||||
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 | ||||
/// <summary> | ||||
/// Returns an array of the directory names in the storage-container. | ||||
/// </summary> | ||||
/// <returns>Array of directory names.</returns> | ||||
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; | ||||
} | ||||
/// <summary> | ||||
/// Returns an array of directory names with given search pattern. | ||||
/// </summary> | ||||
/// <param name="searchPattern"> | ||||
/// A search pattern that supports single-character ("?") and multicharacter ("*") | ||||
/// wildcards. | ||||
/// </param> | ||||
/// <returns>Array of matched directory names.</returns> | ||||
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; | ||||
} | ||||
/// <summary> | ||||
/// Returns an array of file names in the storage-container. | ||||
/// </summary> | ||||
/// <returns>Array of file names.</returns> | ||||
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; | ||||
} | ||||
/// <summary> | ||||
/// Returns an array of file names with given search pattern. | ||||
/// </summary> | ||||
/// <param name="searchPattern"> | ||||
/// A search pattern that supports single-character ("?") and multicharacter ("*") | ||||
/// wildcards. | ||||
/// </param> | ||||
/// <returns>Array of matched file names.</returns> | ||||
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 | ||||
/// <summary> | ||||
/// Opens a file contained in storage-container. | ||||
/// </summary> | ||||
/// <param name="file">Relative path of the file.</param> | ||||
/// <param name="fileMode"> | ||||
/// <see cref="FileMode"/> that specifies how the file is to be opened. | ||||
/// </param> | ||||
/// <returns><see cref="Stream"/> object for the opened file.</returns> | ||||
public Stream OpenFile( | ||||
string file, | ||||
FileMode fileMode | ||||
) { | ||||
return OpenFile( | ||||
file, | ||||
fileMode, | ||||
FileAccess.ReadWrite, | ||||
FileShare.ReadWrite | ||||
); | ||||
} | ||||
/// <summary> | ||||
/// Opens a file contained in storage-container. | ||||
/// </summary> | ||||
/// <param name="file">Relative path of the file.</param> | ||||
/// <param name="fileMode"> | ||||
/// <see cref="FileMode"/> that specifies how the file is to be opened. | ||||
/// </param> | ||||
/// <param name="fileAccess"> | ||||
/// <see cref="FileAccess"/> that specifies access mode. | ||||
/// </param> | ||||
/// <returns><see cref="Stream"/> object for the opened file.</returns> | ||||
public Stream OpenFile( | ||||
string file, | ||||
FileMode fileMode, | ||||
FileAccess fileAccess | ||||
) { | ||||
return OpenFile( | ||||
file, | ||||
fileMode, | ||||
fileAccess, | ||||
FileShare.ReadWrite | ||||
); | ||||
} | ||||
/// <summary> | ||||
/// Opens a file contained in storage-container. | ||||
/// </summary> | ||||
/// <param name="file">Relative path of the file.</param> | ||||
/// <param name="fileMode"> | ||||
/// <see cref="FileMode"/> that specifies how the file is to be opened. | ||||
/// </param> | ||||
/// <param name="fileAccess"> | ||||
/// <see cref="FileAccess"/> that specifies access mode. | ||||
/// </param> | ||||
/// <param name="fileShare">A bitwise combination of <see cref="FileShare"/> | ||||
/// enumeration values that specifies access modes for other stream objects.</param> | ||||
/// <returns><see cref="Stream"/> object for the opened file.</returns> | ||||
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 | ||||
} | ||||
} | ||||