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, 0, 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(0, 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 < 0){throw new ArgumentOutOfRangeException("initialCount");}_currentCount = initialCount;}public Task WaitAsync(){lock (_waiters){if (_currentCount > 0){_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 > 0){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(1);_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();}#endregionpublic 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(0, 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, 0, 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 > 0){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(0, SeekOrigin.Begin);}var length = Convert.ToInt32(stream.Length);var data = new byte[length];stream.Read(data, 0, 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, 0, 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 = awaitStorageFile.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(0, 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(0, SeekOrigin.Begin);}int length = Convert.ToInt32(stream.Length);var data = new byte[length];stream.Read(data, 0, length);return data;}public Stream CopyStream(Stream stream){if (stream.CanSeek){stream.Seek(0, SeekOrigin.Begin);}var tempStream = new MemoryStream();stream.CopyTo(tempStream);tempStream.Seek(0, SeekOrigin.Begin);return tempStream;}#endregion}
}

StorageHelper

参考链接

  https://asynclock.codeplex.com/

  http://stackoverflow.com/questions/21246610/access-a-storagefolder-with-ms-appdata

  http://stackoverflow.com/questions/17935624/storagefile-50-times-slower-than-isolatedstoragefile

个人能力有限,如果有更好的实现,可以给我留言

转载请注明出处:http://www.cnblogs.com/bomo/p/3942750.html

转载于:https://www.cnblogs.com/bomo/p/3942750.html

【WP8】线程安全的StorageHelper相关推荐

  1. 多线程编程指南 part 2

    多线程编程指南 Sun Microsystems, Inc. 4150 Network Circle Santa Clara, CA95054 U.S.A. 文件号码819–7051–10 2006 ...

  2. Cocos2d-x项目移植到WP8系列之二:开篇

    原文链接: http://www.cnblogs.com/zouzf/p/3970130.html 开发环境一笔带过吧,主板和CPU要支持虚拟化技术,要开启才行,装个64位win8.1系统,win8不 ...

  3. java 手编线程池_死磕 java线程系列之自己动手写一个线程池

    欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. (手机横屏看源码更方便) 问题 (1)自己动手写一个线程池需要考虑哪些因素? (2)自己动手写 ...

  4. Redis 笔记(12)— 单线程架构(非阻塞 IO、多路复用)和多个异步线程

    Redis 使用了单线程架构.非阻塞 I/O .多路复用模型来实现高性能的内存数据库服务.Redis 是单线程的.那么为什么说是单线程呢? Redis 在 Reactor 模型内开发了事件处理器,这个 ...

  5. Python 多线程总结(2)— 线程锁、线程池、线程数量、互斥锁、死锁、线程同步

    主要介绍使用 threading 模块创建线程的 3 种方式,分别为: 创建 Thread 实例函数 创建 Thread 实例可调用的类对象 使用 Thread 派生子类的方式 多线程是提高效率的一种 ...

  6. 详解 Tomcat 的连接数与线程池

    原文出处:编程迷思 前言 在使用tomcat时,经常会遇到连接数.线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的连接器(Connector). 在前面的文章 详解Tomcat配置文 ...

  7. Spring并发访问的线程安全性问题

    下面的记录对spring中并发的总结.理论分析参考Spring中Singleton模式的线程安全,建议先看 spring中的并发访问题: 我们知道在一般情况下,只有无状态的Bean才可以在多线程环境下 ...

  8. 聊一聊Spring中的线程安全性

    原文出处:SylvanasSun Spring与线程安全 ThreadLocal ThreadLocal中的内存泄漏 参考文献 Spring与线程安全 Spring作为一个IOC/DI容器,帮助我们管 ...

  9. 线程的状态、调度、同步

    线程的状态 java中的线程共五个状态:新建.就绪.运行.阻塞.死亡: 新建状态(New):处于系统创建线程,但未启动此线程,系统未为其分配资源. 就绪状态(Runnable):线程调用start( ...

最新文章

  1. mysql 配置执行计划_MySQL深入学习(二)--配置、索引、执行计划
  2. php.ini 中文版第二部分(关于这个配制文件)
  3. mysql 行自动增量为23,Mysql Innodb:自动增量非主键
  4. orcal 数据库密码修改(表密码,sys密码,system密码)
  5. php查询过滤字段,PHPelasticsearch过滤查询字符串搜索
  6. Windows下curl的下载与使用
  7. python怎么创建方法_python中的__new__方法
  8. 判断网络是否为真正的公网IP
  9. intellij idea 热部署 spring jvm 版
  10. php的常量和变量的区别,php中常量与变量的区别是什么?
  11. 如何编写Ruby控制台程序(一)
  12. 为什么要自定义ClassLoader进行类加载
  13. 常见 HTTP/FTP/WebSocket 错误代码大全 - 转
  14. 中职计算机专业学Excel,2013年中职计算机应用专业中文Excel电子表格处理实际操作练习.doc...
  15. Git修改用户名和密码
  16. C#编写的winform程序绑定comboBox成功,添加一个默认的文字选项请选择
  17. 邮件营销群发6大技巧!怎么群发邮件效果好?
  18. 再见PanDownload ,下一个已经来了。
  19. linux系统上ros安装,Ubuntu中安装ROS Kinetic
  20. 衡水二中2021清华北大高考成绩查询,前进中的衡水二中,2019清华北大106人,成功绝非偶然...

热门文章

  1. devc编译器配置如何配置_如何使用notepad++搭配MinGW配置编译C/C++
  2. 企业进销存管理系统 email_移动进销存让企业高效进行汽车配件管理
  3. python绘制双正切激活函数
  4. java构造方法与重载牛肉粉,IT兄弟连Java基础视频教程
  5. matlab背景点状,基于MATLAB的点状目标检测
  6. Java让数据库执行一条sql_java数据库编程——执行SQL 语句
  7. 金陵科技学院计算机答辩,金陵科技学院优秀毕业论文答辩ppt模板
  8. 关于韩京清学者的《直线型倒立摆的自抗扰控制设计方案》仿真
  9. Feign 超时设置
  10. java考前复习之Scanner 类