14-08-29 12:32更新:修复StorageHelper部分bug
WP8以后提供了StorageFile的方式访问文件,StorageFile对文件的操作只提供了异步的支持,包括WP8.1 RT也没有对同步读写文件的支持,可以看出异步在移动开发中的重要性,而且Win8也是通过StorageFile进行文件操作的
跟WP7上的IsolatedStorageFile相比,StorageFile使用起来并不方便,最近总结了一些资料,写了一个通用的类库
StorageFile默认是线程不安全的,如果多个线程同时对文件进行读写会抛出异常,例如多图的场景比较常见
让StorageFile使用起来更加方便,同时提供了线程安全的异步操作,同时也对IsolatedStorageFile(Silverlight)进行了封装
一、StorageFile要点:
StorageFile
1、访问文件(两种方式)
//访问安装目录下的test.txt文件,如果不存在,会抛出FileNotFoundException异常 //1、访问当前目录下的文件
var folder = Package.Current.InstalledLocation;
var storageFile = await folder.GetFileAsync("test.txt"); //2、通过Uri访问文件,Uri为绝对路径
storageFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appdata:///local/test.txt", UriKind.Absolute)); //安装文件目录Uri前缀:ms-appx:///
//本地目录Uri前缀:ms-appdata:///local/
2、没有提供判断文件是否存在的函数,这里通过异常来判断文件是否存在:
try
{
await StorageFile.GetFileFromApplicationUriAsync(new Uri(string.Format("ms-appdata:///local/{0}", filePath), UriKind.Absolute));
return true;
}
catch (Exception)
{
return false;
}
测试发现:使用上面的形式访问文件会出现问题(比如文件明明存在,却还是会报FileNotFound异常),故StorageHelper不适用上面的形式,而是用通过文件夹访问的形式访问文件,可以解决该问题,目前尚不清楚原因
//发现通过ms-appdata:///local/访问的方会出现问题,现改成通过下面方式访问文件
filePath = filePath.Trim('/').Replace("/", "\\");
var file = await ApplicationData.Current.LocalFolder.GetFileAsync(filePath);
3、创建文件
//如果文件已经存在,会抛出异常
var storageFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(fileName);
using (var stream = await storageFile.OpenStreamForWriteAsync())
{
stream.Write(data, , data.Length);
}
StorageFolder
//创建文件夹(用\\分开,前后都不加\\)
var folder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("aa\\bb\\cc\\dd"); //访问文件夹
var folder = await ApplicationData.Current.LocalFolder.GetFolderAsync("aa\\bb\\cc\\dd");
二、线程安全
IsolatedStorageFile的同步操作这里使用线程锁来实现线程安全
//线程锁
private static readonly object lockObj = new object(); public Stream ReadFile(string filePath)
{
lock (lockObj)
{
using (var storageFile = IsolatedStorageFile.GetUserStoreForApplication())
{
if (!storageFile.FileExists(filePath))
{
throw new FileNotFoundException(string.Format("没有找到文件:{0}", filePath));
} using (var fs = new IsolatedStorageFileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, storageFile))
{
var stream = new MemoryStream();
fs.CopyTo(stream); stream.Seek(, SeekOrigin.Begin);
return stream;
}
}
}
}
异步线程锁使用 Asynclock,可以在Nuget下载到(Enough.AsyncLock)
Asynclock提供了两个类:AsyncSemaphore,AsyncLock
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Enough.Async
{
public class AsyncSemaphore
{
private readonly static Task _completed = Task.FromResult(true);
private readonly Queue<TaskCompletionSource<bool>> _waiters = new Queue<TaskCompletionSource<bool>>();
private int _currentCount; public AsyncSemaphore(int initialCount)
{
if (initialCount < )
{
throw new ArgumentOutOfRangeException("initialCount");
}
_currentCount = initialCount;
} public Task WaitAsync()
{
lock (_waiters)
{
if (_currentCount > )
{
_currentCount--;
return _completed;
}
else
{
var waiter = new TaskCompletionSource<bool>();
_waiters.Enqueue(waiter);
return waiter.Task;
}
}
} public void Release()
{
TaskCompletionSource<bool> toRelease = null;
lock (_waiters)
{
if (_waiters.Count > )
{
toRelease = _waiters.Dequeue();
}
else
{
_currentCount++;
}
}
if (toRelease != null)
{
toRelease.SetResult(true);
}
}
}
}
AsyncSemaphore
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace Enough.Async
{
/// <summary>AsyncLock locks across one or several await calls.
///
/// </summary>
public class AsyncLock
{
private readonly AsyncSemaphore _semaphore;
private readonly Task<Releaser> _releaser; public AsyncLock()
{
_semaphore = new AsyncSemaphore();
_releaser = Task.FromResult(new Releaser(this));
} public Task<Releaser> LockAsync()
{
var wait = _semaphore.WaitAsync();
return wait.IsCompleted ?
_releaser :
wait.ContinueWith((_, state) => new Releaser((AsyncLock)state),
this, CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
} public struct Releaser : IDisposable
{
private readonly AsyncLock _toRelease; internal Releaser(AsyncLock toRelease)
{
_toRelease = toRelease;
} public void Dispose()
{
if (_toRelease != null)
{
_toRelease._semaphore.Release();
}
}
}
}
}
AsyncLock
三、接口与实现
提供线程安全的异步操作(IsolatedStorageFile和StorageFile)
IStorageHelper:提供基本的文件操作相关方法
约定:
1、文件夹用'/'分割,
2、路径不以斜杠'/'开头
3、文件夹路径以'/'结束
// *************************************************
//
// 作者:bomo
// 小组:WP开发组
// 创建日期:2014/8/28 21:49:04
// 版本号:V1.00
// 说明: 文件操作接口类,提供文件操作的相关方法
//
// *************************************************
//
// 修改历史:
// Date WhoChanges Made
// 08/28/2014 bomo Initial creation
//
// *************************************************
// 约定:
// 1、文件夹用'/'分割,
// 2、路径不以斜杠'/'开头
// 3、文件夹路劲以'/'结束 using System.IO;
using System.Threading.Tasks; namespace TestDemo
{
public interface IStorageHelper
{
#region 同步方法 Stream ReadFile(string filePath); string ReadText(string filePath); void WriteFile(Stream stream, string filePath, bool replace = false); void WriteFile(byte[] data, string filePath, bool replace = false); void WriteText(string text, string filePath, bool replace = false); bool FileExists(string filePath); bool DirectoryExists(string directory); bool DeleteFile(string filePath); bool DeleteDirectory(string directory, bool isDeleteAll = false); bool CreateDirectory(string directory); long GetFileLength(string filePath); string[] GetFiles(string directory); string[] GetDirectories(string directory); /// <summary>
/// 序列号类到文件(Xml)
/// </summary>
void Serialize<T>(string filePath, T obj); T DeSerialize<T>(string filePath); void CopyPackageFileToLocal(string source, string target = null, bool replace = false); void CopyPackageFolderToLocal(string source, string target = null, bool replace = false); Stream GetResourceStream(string filePath); #endregion #region 异步方法 Task<Stream> ReadFileAsync(string filePath); Task<string> ReadTextAsync(string filePath); Task WriteFileAsync(Stream stream, string filePath, bool replace = false); Task WriteFileAsync(byte[] data, string filePath, bool replace = false); Task WriteTextAsync(string text, string filePath, bool replace = false); Task<bool> FileExistsAsync(string filePath); Task<bool> DirectoryExistsAsync(string directory); Task<bool> DeleteFileAsync(string filePath); Task<bool> DeleteDirectoryAsync(string directory, bool isDeleteAll = false); Task<bool> CreateDirectoryAsync(string directory); Task<ulong> GetFileLengthAsync(string filePath); Task<string[]> GetFilesAsync(string directory); Task<string[]> GetDirectoriesAsync(string directory); Task SerializeAsync<T>(string filePath, T obj); Task<T> DeSerializeAsync<T>(string filePath); /// <summary>
/// 拷贝安装目录的文件到本地
/// </summary>
Task CopyPackageFileToLocalAsync(string source, string target = null, bool replace = false); /// <summary>
/// 拷贝安装目录的文件夹(包括子文件夹和子文件)到本地
/// </summary>
Task CopyPackageFolderToLocalAsync(string source, string target = null, bool replace = false); Task<Stream> GetResourceStreamAsync(string filePath); #endregion
}
}
IsolatedStorageFile不支持从安装目录拷贝文件夹,StorageFile不支持同步处理文件
辅助扩展类
using System;
using System.IO;
using System.Threading.Tasks; namespace TestDemo
{
public static class StreamReaderExtension
{
public static async Task<String> ReadToEndAsyncThread(this StreamReader reader)
{
return await Task.Factory.StartNew<String>(reader.ReadToEnd);
}
}
}
StreamReaderExtension
using System;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Xml.Serialization;
using Enough.Async; namespace TestDemo
{
public class IsolatedStorageHelper : IStorageHelper
{
private static readonly Enough.Async.AsyncLock asyncLock = new Enough.Async.AsyncLock();
private static readonly object lockObj = new object(); private readonly IsolatedStorageFile storageFile; #region 提供单例的支持 public static IStorageHelper Instance { get; private set; } public static object LockObject; static IsolatedStorageHelper()
{
Instance = new IsolatedStorageHelper();
LockObject = new object();
} private IsolatedStorageHelper()
{
storageFile = IsolatedStorageFile.GetUserStoreForApplication();
} #endregion public Stream ReadFile(string filePath)
{
lock (lockObj)
{
if (!storageFile.FileExists(filePath))
{
throw new FileNotFoundException(string.Format("没有找到文件:{0}", filePath));
} using (var fs = new IsolatedStorageFileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, storageFile))
{
var stream = new MemoryStream();
fs.CopyTo(stream); stream.Seek(, SeekOrigin.Begin);
return stream;
}
}
} public string ReadText(string filePath)
{
lock (lockObj)
{
using (var stream = new IsolatedStorageFileStream(filePath, FileMode.Open, storageFile))
{
using (var r = new StreamReader(stream))
{
return r.ReadToEnd();
}
}
}
} public void WriteFile(Stream stream, string filePath, bool replace = false)
{
WriteFile(ToBytes(stream), filePath, replace);
} public void WriteFile(byte[] data, string filePath, bool replace = false)
{
lock (lockObj)
{
var directory = Path.GetDirectoryName(filePath);
if (directory != null)
{
directory = directory.Replace("\\", "/");
if (!storageFile.DirectoryExists(directory))
{
//如果目录不存在,则创建
storageFile.CreateDirectory(directory);
}
} if (storageFile.FileExists(filePath))
{
if (replace)
{
storageFile.DeleteFile(filePath);
}
else
{
return;
}
} using (var fs = new IsolatedStorageFileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, storageFile))
{
fs.Write(data, , data.Length);
}
}
} public void WriteText(string text, string filePath, bool replace = false)
{
WriteFile(Encoding.UTF8.GetBytes(text), filePath, replace);
} public bool FileExists(string filePath)
{
lock (lockObj)
{
return storageFile.FileExists(filePath);
}
} public bool DirectoryExists(string directory)
{
lock (lockObj)
{
return storageFile.DirectoryExists(directory);
}
} public bool DeleteFile(string filePath)
{
lock (lockObj)
{
if (!storageFile.FileExists(filePath)) return false;
storageFile.DeleteFile(filePath);
return true;
}
} public bool DeleteDirectory(string directory, bool isDeleteAll)
{
lock (lockObj)
{
if (storageFile.GetFileNames(directory).Length + storageFile.GetDirectoryNames(directory).Length > )
{
if (isDeleteAll)
{
DeleteDirectory(directory);
return true;
}
else
{
return false;
}
}
else
{
storageFile.DeleteDirectory(directory);
return true;
}
}
} public bool CreateDirectory(string directory)
{
lock (lockObj)
{
if (storageFile.DirectoryExists(directory)) return false;
storageFile.CreateDirectory(directory);
return true;
}
} public long GetFileLength(string filePath)
{
lock (lockObj)
{
if (storageFile.FileExists(filePath))
{
return storageFile.OpenFile(filePath, FileMode.Open, FileAccess.Read).Length;
}
throw new FileNotFoundException(string.Format("没有找到文件:{0}", filePath));
}
} public string[] GetFiles(string directory)
{
lock (lockObj)
{
var files = storageFile.GetFileNames(directory);
return files.Select(f => directory + f).ToArray();
}
} public string[] GetDirectories(string directory)
{
lock (lockObj)
{
var folders = storageFile.GetDirectoryNames(directory);
return folders.Select(f => directory + f).ToArray();
}
} public void Serialize<T>(string filePath, T obj)
{
lock (lockObj)
{
var directory = Path.GetDirectoryName(filePath);
if (directory != null)
{
directory = directory.Replace("\\", "/");
if (!storageFile.DirectoryExists(directory))
{
//如果目录不存在,则创建
storageFile.CreateDirectory(directory);
}
} if (storageFile.FileExists(filePath))
{
storageFile.DeleteFile(filePath);
} using (
var fs = new IsolatedStorageFileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write,
FileShare.None, storageFile))
{
var serializer = new XmlSerializer(obj.GetType());
serializer.Serialize(fs, obj);
}
}
} public T DeSerialize<T>(string filePath)
{
lock (lockObj)
{
if (!storageFile.FileExists(filePath))
{
throw new FileNotFoundException(string.Format("没有找到文件:{0}", filePath));
}
var serializer = new XmlSerializer(typeof (T));
using (var fs = storageFile.OpenFile(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return (T) serializer.Deserialize(fs);
}
}
} public void CopyPackageFileToLocal(string source, string target = null, bool replace = false)
{
using (var stream = Application.GetResourceStream(new Uri(source, UriKind.Relative)).Stream)
{
WriteFile(stream, target ?? source, replace);
}
} public void CopyPackageFolderToLocal(string source, string target = null, bool replace = false)
{
throw new NotImplementedException("IsolatedStorageFile不支持拷贝安装文件夹");
} public Stream GetResourceStream(string filePath)
{
return Application.GetResourceStream(new Uri(filePath, UriKind.Relative)).Stream;
} public async Task<Stream> ReadFileAsync(string filePath)
{
using (await asyncLock.LockAsync())
{
return await Task.Factory.StartNew(() => ReadFile(filePath));
}
} public async Task<string> ReadTextAsync(string filePath)
{
using (await asyncLock.LockAsync())
{
return await Task.Factory.StartNew(() => ReadText(filePath));
}
} public async Task WriteFileAsync(Stream stream, string filePath, bool replace = false)
{
await WriteFileAsync(ToBytes(stream), filePath, replace);
} public async Task WriteFileAsync(byte[] data, string filePath, bool replace = false)
{
using (await asyncLock.LockAsync())
{
await Task.Factory.StartNew(() => WriteFile(data, filePath, replace));
}
} public async Task WriteTextAsync(string text, string filePath, bool replace = false)
{
await WriteFileAsync(Encoding.UTF8.GetBytes(text), filePath, replace);
} public async Task<bool> FileExistsAsync(string filePath)
{
using (await asyncLock.LockAsync())
{
return await Task.Factory.StartNew(() => FileExists(filePath));
}
} public async Task<bool> DirectoryExistsAsync(string directory)
{
using (await asyncLock.LockAsync())
{
return await Task.Factory.StartNew(() => DirectoryExists(directory));
}
} public async Task<bool> DeleteFileAsync(string filePath)
{
using (await asyncLock.LockAsync())
{
return await await Task.Factory.StartNew(() => DeleteFileAsync(filePath));
}
} public async Task<bool> DeleteDirectoryAsync(string directory, bool isDeleteAll = false)
{
using (await asyncLock.LockAsync())
{
return await Task.Factory.StartNew(() => DeleteDirectory(directory, isDeleteAll));
} } public async Task<bool> CreateDirectoryAsync(string directory)
{
using (await asyncLock.LockAsync())
{
return await Task.Factory.StartNew(() => CreateDirectory(directory));
}
} public async Task<ulong> GetFileLengthAsync(string filePath)
{
using (await asyncLock.LockAsync())
{
return await Task.Factory.StartNew(() => (ulong)GetFileLength(filePath));
}
} public async Task<string[]> GetFilesAsync(string directory)
{
using (await asyncLock.LockAsync())
{
return await Task.Factory.StartNew(() => GetFiles(directory));
}
} public async Task<string[]> GetDirectoriesAsync(string directory)
{
using (await asyncLock.LockAsync())
{
return await Task.Factory.StartNew(() => GetDirectories(directory));
}
} public async Task SerializeAsync<T>(string filePath, T obj)
{
using (await asyncLock.LockAsync())
{
await Task.Factory.StartNew(() => Serialize(filePath, obj));
}
} public async Task<T> DeSerializeAsync<T>(string filePath)
{
using (await asyncLock.LockAsync())
{
return await Task.Factory.StartNew(() => DeSerialize<T>(filePath));
}
} public async Task CopyPackageFileToLocalAsync(string source, string target = null, bool replace = false)
{
using (await asyncLock.LockAsync())
{
await Task.Factory.StartNew(() => CopyPackageFileToLocal(source, target, replace));
}
} public async Task CopyPackageFolderToLocalAsync(string source, string target = null, bool replace = false)
{
using (await asyncLock.LockAsync())
{
await Task.Factory.StartNew(() => CopyPackageFolderToLocal(source, target, replace));
}
} public async Task<Stream> GetResourceStreamAsync(string filePath)
{
using (await asyncLock.LockAsync())
{
return await Task.Factory.StartNew(() =>
Application.GetResourceStream(new Uri(filePath, UriKind.Relative)).Stream);
}
} #region 辅助函数 //递归删除文件夹
private void DeleteDirectory(string directory)
{
var directories = storageFile.GetDirectoryNames(directory);
foreach (var d in directories)
{
DeleteDirectory(string.Format("{0}{1}/", directory, d));
}
var files = storageFile.GetFileNames(directory);
foreach (var f in files)
{
storageFile.DeleteFile(f);
}
} private byte[] ToBytes(Stream stream)
{
if (stream.CanSeek)
{
stream.Seek(, SeekOrigin.Begin);
}
var length = Convert.ToInt32(stream.Length);
var data = new byte[length];
stream.Read(data, , length);
return data;
} #endregion
}
}
IsolatedStorageHelper
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using Windows.ApplicationModel;
using Windows.Storage;
using Enough.Async; namespace TestDemo
{
public class StorageHelper : IStorageHelper
{
private static readonly AsyncLock asyncLock = new AsyncLock(); #region 提供单例的支持 public static IStorageHelper Instance { get; private set; } public static object LockObject; static StorageHelper()
{
Instance = new StorageHelper();
LockObject = new object();
} private StorageHelper()
{
} #endregion #region 同步方法(StorageFile不支持同步方法) public Stream ReadFile(string filePath)
{
throw new NotImplementedException();
} public string ReadText(string filePath)
{
throw new NotImplementedException();
} public void WriteFile(Stream stream, string filePath, bool replace = false)
{
throw new NotImplementedException();
} public void WriteFile(byte[] data, string filePath, bool replace = false)
{
throw new NotImplementedException();
} public void WriteText(string text, string filePath, bool replace = false)
{
throw new NotImplementedException();
} public bool FileExists(string filePath)
{
throw new NotImplementedException();
} public bool DirectoryExists(string directory)
{
throw new NotImplementedException();
} public bool DeleteFile(string filePath)
{
throw new NotImplementedException();
} public bool DeleteDirectory(string directory, bool isDeleteAll = false)
{
throw new NotImplementedException();
} public bool CreateDirectory(string directory)
{
throw new NotImplementedException();
} public long GetFileLength(string filePath)
{
throw new NotImplementedException();
} public string[] GetFiles(string directory)
{
throw new NotImplementedException();
} public string[] GetDirectories(string directory)
{
throw new NotImplementedException();
} public void Serialize<T>(string filePath, T obj)
{
throw new NotImplementedException();
} public T DeSerialize<T>(string filePath)
{
throw new NotImplementedException();
} public void CopyPackageFileToLocal(string source, string target = null, bool replace = false)
{
throw new NotImplementedException();
} public void CopyPackageFolderToLocal(string source, string target = null, bool replace = false)
{
throw new NotImplementedException();
} public Stream GetResourceStream(string filePath)
{
throw new NotImplementedException();
} #endregion #region 异步方法 public async Task<Stream> ReadFileAsync(string filePath)
{
using (await asyncLock.LockAsync())
{
return await await Task.Factory.StartNew(async () =>
{
try
{
filePath = filePath.Trim('/').Replace("/", "\\"); var file = await ApplicationData.Current.LocalFolder.GetFileAsync(filePath); using (Stream stream = await file.OpenStreamForReadAsync())
{
return CopyStream(stream);
}
}
catch (FileNotFoundException)
{
throw new FileNotFoundException(string.Format("没有找到文件:{0}", filePath));
}
});
}
} public async Task<string> ReadTextAsync(string filePath)
{
Debug.WriteLine("Read Begin");
var text = string.Empty;
using (var stream = await ReadFileAsync(filePath))
{
using (var reader = new StreamReader(stream))
{
text = await reader.ReadToEndAsyncThread();
}
}
Debug.WriteLine("Read Complete"); return text;
} public async Task WriteFileAsync(Stream stream, string filePath, bool replace = false)
{
await WriteFileAsync(ToBytes(stream), filePath, replace);
} //只支持本地路径
public async Task WriteFileAsync(byte[] data, string filePath, bool replace = false)
{
Debug.WriteLine("Write Begin!"); using (await asyncLock.LockAsync())
{
await await Task.Factory.StartNew(async () =>
{
try
{
//发现通过ms-appdata:///local/访问的方会出现问题,现改成通过下面方式访问文件
filePath = filePath.Trim('/').Replace("/", "\\");
var file = await ApplicationData.Current.LocalFolder.GetFileAsync(filePath); if (replace)
{
await file.DeleteAsync();
}
else
{
return;
}
}
catch (FileNotFoundException)
{
//文件不存在
} //创建文件
var fileName = filePath.Trim('/').Replace("/", "\\");
var storageFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(fileName);
using (var stream = await storageFile.OpenStreamForWriteAsync())
{
stream.Write(data, , data.Length);
}
});
} Debug.WriteLine("Write Complete!");
} public async Task WriteTextAsync(string text, string filePath, bool replace = false)
{
await WriteFileAsync(Encoding.UTF8.GetBytes(text), filePath, replace);
} public async Task<bool> FileExistsAsync(string filePath)
{
using (await asyncLock.LockAsync())
{
return await await Task.Factory.StartNew(async () =>
{
try
{
filePath = filePath.Trim('/').Replace("/", "\\");
await ApplicationData.Current.LocalFolder.GetFileAsync(filePath);
return true;
}
catch (Exception)
{
Debug.WriteLine(filePath);
return false;
}
});
}
} public async Task<bool> DirectoryExistsAsync(string directory)
{
using (await asyncLock.LockAsync())
{
return await await Task.Factory.StartNew(async () =>
{
try
{
directory = directory.Trim('/').Replace("/", "\\");
await ApplicationData.Current.LocalFolder.GetFolderAsync(directory);
return true;
}
catch (Exception)
{
return false;
}
});
}
} public async Task<bool> DeleteFileAsync(string filePath)
{
using (await asyncLock.LockAsync())
{
return await await Task.Factory.StartNew(async () =>
{
try
{
var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(string.Format("ms-appdata:///local/{0}", filePath), UriKind.Absolute));
await file.DeleteAsync();
return true;
}
catch (Exception)
{
return false;
}
});
}
} public async Task<bool> DeleteDirectoryAsync(string directory, bool isDeleteAll = false)
{
using (await asyncLock.LockAsync())
{
return await await Task.Factory.StartNew(async () =>
{
try
{
directory = directory.Trim('/').Replace("/", "\\");
var folder = await ApplicationData.Current.LocalFolder.GetFolderAsync(directory);
await folder.DeleteAsync();
return true;
}
catch (Exception)
{
return false;
}
});
} } public async Task<bool> CreateDirectoryAsync(string directory)
{
using (await asyncLock.LockAsync())
{
return await await Task.Factory.StartNew(async () =>
{
try
{
directory = directory.Trim('/').Replace("/", "\\");
await ApplicationData.Current.LocalFolder.CreateFolderAsync(directory, CreationCollisionOption.OpenIfExists);
return true;
}
catch (Exception)
{
return false;
}
});
}
} public async Task<ulong> GetFileLengthAsync(string filePath)
{
using (await asyncLock.LockAsync())
{
return await await Task.Factory.StartNew(async () =>
{
var file = await
StorageFile.GetFileFromApplicationUriAsync(new Uri(string.Format("ms-appdata:///local/{0}", filePath),
UriKind.Absolute)); return (await file.OpenReadAsync()).Size;
});
}
} public async Task<string[]> GetFilesAsync(string directory)
{
directory = directory.Trim('/').Replace("/", "\\");
var folder = await ApplicationData.Current.LocalFolder.GetFolderAsync(directory);
var files = await folder.GetFilesAsync();
return files.ToList()
.Select(f => f.Path.Replace(ApplicationData.Current.LocalFolder.Path, string.Empty).Trim('\\').Replace("\\", "/"))
.ToArray();
} public async Task<string[]> GetDirectoriesAsync(string directory)
{
directory = directory.Trim('/').Replace("/", "\\");
var folder = await ApplicationData.Current.LocalFolder.GetFolderAsync(directory);
var files = await folder.GetFoldersAsync();
return files.ToList()
.Select(f => f.Path.Replace(ApplicationData.Current.LocalFolder.Path, string.Empty).Trim('\\').Replace("\\", "/"))
.ToArray();
} public async Task SerializeAsync<T>(string filePath, T obj)
{
var stream = new MemoryStream();
var serializer = new XmlSerializer(obj.GetType());
serializer.Serialize(stream, obj);
stream.Seek(, SeekOrigin.Begin);
await WriteFileAsync(stream, filePath, true);
} public async Task<T> DeSerializeAsync<T>(string filePath)
{
using (var stream = await ReadFileAsync(filePath))
{
var serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(stream);
}
} public async Task CopyPackageFileToLocalAsync(string source, string target = null, bool replace = false)
{
using (var stream = await GetResourceStreamAsync(source))
{
target = target ?? source;
await WriteFileAsync(stream, target, replace);
}
} public async Task CopyPackageFolderToLocalAsync(string source, string target = null, bool replace = false)
{ source = source.Trim('/').Replace("/", "\\");
target = target != null ? target.Trim('/').Replace("/", "\\") : source; var sourseFolder = await Package.Current.InstalledLocation.GetFolderAsync(source); //创建目标文件夹
var targetFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(target, CreationCollisionOption.OpenIfExists); await CopyPackageFolderToLocalAsync(sourseFolder, targetFolder, replace);
} public async Task CopyPackageFolderToLocalAsync(StorageFolder source, StorageFolder target, bool replace = false)
{
var folders = await source.GetFoldersAsync();
foreach (var storageFolder in folders)
{
var targetFolder = await target.CreateFolderAsync(storageFolder.Name, CreationCollisionOption.OpenIfExists);
await CopyPackageFolderToLocalAsync(storageFolder, targetFolder, replace);
} var files = await source.GetFilesAsync();
foreach (var storageFile in files)
{
try
{
await storageFile.CopyAsync(target, storageFile.Name, replace
? NameCollisionOption.ReplaceExisting
: NameCollisionOption.FailIfExists);
}
catch (Exception)
{
//文件已存在(不替换),抛出异常
}
}
} public async Task<Stream> GetResourceStreamAsync(string filePath)
{
using (await asyncLock.LockAsync())
{
return await await Task.Factory.StartNew(async () =>
{
filePath = filePath.Trim('/').Replace("/", "\\"); //发现通过ms-appx:///访问的方会出现问题,现改成通过下面方式访问文件
var f = await Package.Current.InstalledLocation.GetFileAsync(filePath);
using (Stream stream = await f.OpenStreamForReadAsync())
{
return CopyStream(stream);
}
});
}
} #endregion #region 辅助函数 private static byte[] ToBytes(Stream stream)
{
if (stream.CanSeek)
{
stream.Seek(, SeekOrigin.Begin);
}
int length = Convert.ToInt32(stream.Length);
var data = new byte[length];
stream.Read(data, , length);
return data;
} public Stream CopyStream(Stream stream)
{
if (stream.CanSeek)
{
stream.Seek(, SeekOrigin.Begin);
}
var tempStream = new MemoryStream();
stream.CopyTo(tempStream);
tempStream.Seek(, SeekOrigin.Begin);
return tempStream;
} #endregion
}
}
StorageHelper
参考链接
https://asynclock.codeplex.com/
http://*.com/questions/21246610/access-a-storagefolder-with-ms-appdata
http://*.com/questions/17935624/storagefile-50-times-slower-than-isolatedstoragefile
个人能力有限,如果有更好的实现,可以给我留言