From 513d32f8fec3e91a21022d218175170555607cc5 Mon Sep 17 00:00:00 2001 From: Juergen Koller Date: Fri, 29 May 2015 18:11:45 +0200 Subject: [PATCH 1/9] Added GetFileFromAppBundleAsync to access files from the app bundle like: var cancelationToken = new System.Threading.CancellationToken(); var f = await FileSystem.Current.GetFileFromAppBundleAsync("FileInsideTheAppBundle.txt", cancelationToken); var fileContent = await f.ReadAllTextAsync(); On Windows just copy the the file 'FileInsideTheAppBundle.txt' into your project and mark it as Content in the build action. On iOS copy it into the 'Resources' folder and mark the file as 'BundleResource'. --- build - Copy.bat | 1 + build.bat | 2 +- build/build - Copy.proj | 70 ++++ build/build.proj | 2 +- common/CommonAssemblyInfo.cs | 4 +- src/PCLStorage.Abstractions/IFileSystem.cs | 9 + .../PCLStorage.Android.csproj | 182 ++++----- .../Resources/Resource.Designer.cs | 120 +++--- .../DesktopFileSystem.cs | 11 +- .../IsoStoreFileSystem.cs | 14 +- src/PCLStorage.WinRT/PCLStorage.WinRT.csproj | 295 +++++++------- src/PCLStorage.WinRT/WinRTFileSystem.cs | 25 ++ src/PCLStorage.iOS/PCLStorage.iOS.csproj | 169 ++++---- src/PCLStorage.iOS/iOSFileSystem.cs | 43 ++ .../PCLStorage.Test.Android.csproj | 215 +++++----- .../Properties/AndroidManifest.xml | 2 +- .../Resources/Resource.Designer.cs | 240 ++++++------ .../PCLStorage.Test.WinRT.csproj | 370 +++++++++--------- .../Package.appxmanifest | 63 ++- 19 files changed, 1008 insertions(+), 829 deletions(-) create mode 100644 build - Copy.bat create mode 100644 build/build - Copy.proj create mode 100644 src/PCLStorage.iOS/iOSFileSystem.cs diff --git a/build - Copy.bat b/build - Copy.bat new file mode 100644 index 0000000..76d6a82 --- /dev/null +++ b/build - Copy.bat @@ -0,0 +1 @@ +msbuild %~dp0build\build.proj /p:Configuration=Release /t:Clean;BuildPackage \ No newline at end of file diff --git a/build.bat b/build.bat index 76d6a82..b28d50a 100644 --- a/build.bat +++ b/build.bat @@ -1 +1 @@ -msbuild %~dp0build\build.proj /p:Configuration=Release /t:Clean;BuildPackage \ No newline at end of file +C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild build\build.proj /p:Configuration=Release /t:Clean;BuildPackage \ No newline at end of file diff --git a/build/build - Copy.proj b/build/build - Copy.proj new file mode 100644 index 0000000..9f40576 --- /dev/null +++ b/build/build - Copy.proj @@ -0,0 +1,70 @@ + + + + + + $(MSBuildProjectDirectory)\.. + $(PCLStorageRoot)\.nuget\NuGet.exe + Release + + + + 1 + 0 + 2 + 0 + + + $(MajorVersion).$(MinorVersion).$(Build).$(Revision) + $(MajorVersion).$(MinorVersion).$(Build).$(Revision) + $(MajorVersion).$(MinorVersion).$(Build) + + + + + AssemblyVersion\("\d+\.\d+\.\d+\.\d+"\) + AssemblyVersion("$(AssemblyVersion)") + + + AssemblyFileVersion\("\d+\.\d+\.\d+\.\d+"\) + AssemblyFileVersion("$(AssemblyFileVersion)") + + + + + RestorePackages;UpdateVersion + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build/build.proj b/build/build.proj index 9f40576..4a35bea 100644 --- a/build/build.proj +++ b/build/build.proj @@ -11,7 +11,7 @@ 1 0 - 2 + 4 0 diff --git a/common/CommonAssemblyInfo.cs b/common/CommonAssemblyInfo.cs index 44adde9..89849d2 100644 --- a/common/CommonAssemblyInfo.cs +++ b/common/CommonAssemblyInfo.cs @@ -26,5 +26,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.2.0")] -[assembly: AssemblyFileVersion("1.0.2.0")] +[assembly: AssemblyVersion("1.0.4.0")] +[assembly: AssemblyFileVersion("1.0.4.0")] diff --git a/src/PCLStorage.Abstractions/IFileSystem.cs b/src/PCLStorage.Abstractions/IFileSystem.cs index 2b92e64..acc2a2b 100644 --- a/src/PCLStorage.Abstractions/IFileSystem.cs +++ b/src/PCLStorage.Abstractions/IFileSystem.cs @@ -36,5 +36,14 @@ public interface IFileSystem /// The cancellation token. /// A folder for the specified path, or null if it does not exist. Task GetFolderFromPathAsync(string path, CancellationToken cancellationToken = default(CancellationToken)); + + /// + /// Gets a file from the App Bundle. Returns null if the file does not exist. + /// + /// The path to a file, as returned from the property. + /// The cancellation token. + /// A file for the given path, or null if it does not exist. + Task GetFileFromAppBundleAsync(string path, CancellationToken cancellationToken); + } } diff --git a/src/PCLStorage.Android/PCLStorage.Android.csproj b/src/PCLStorage.Android/PCLStorage.Android.csproj index 126f521..ed7cccc 100644 --- a/src/PCLStorage.Android/PCLStorage.Android.csproj +++ b/src/PCLStorage.Android/PCLStorage.Android.csproj @@ -1,97 +1,99 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {D813C9D8-D6D1-4D2B-AF04-0D877656F47E} - {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Library - Properties - PCLStorage - PCLStorage - 512 - Resources\Resource.Designer.cs - Off - - - true - full - false - bin\Debug\ - TRACE;DEBUG;XAMARIN;ANDROID;FILE_SYSTEM - prompt - 4 - bin\Debug\PCLStorage.XML - - - pdbonly - true - bin\Release\ - TRACE;XAMARIN;ANDROID;FILE_SYSTEM - prompt - 4 - bin\Release\PCLStorage.XML - - - - - - - - - - - - Properties\CommonAssemblyInfo.cs - - - DesktopFileSystem.cs - - - FileSystemFile.cs - - - FileSystemFolder.cs - - - AwaitExtensions.cs - - - Exceptions\PCLStorageExceptions.cs - - - FileSystem.cs - - - PortablePath.cs - - - Requires.cs - - - - - - - - - - - - - - {8F4C2E94-B8C5-477B-A315-CA58C70617E4} - PCLStorage.Abstractions.NoSL - - - + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {D813C9D8-D6D1-4D2B-AF04-0D877656F47E} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + Properties + PCLStorage + PCLStorage + 512 + Resources\Resource.Designer.cs + Off + True + v5.0 + + + true + full + false + bin\Debug\ + TRACE;DEBUG;XAMARIN;ANDROID;FILE_SYSTEM + prompt + 4 + bin\Debug\PCLStorage.XML + + + pdbonly + true + bin\Release\ + TRACE;XAMARIN;ANDROID;FILE_SYSTEM + prompt + 4 + bin\Release\PCLStorage.XML + + + + + + + + + + + + Properties\CommonAssemblyInfo.cs + + + DesktopFileSystem.cs + + + FileSystemFile.cs + + + FileSystemFolder.cs + + + AwaitExtensions.cs + + + Exceptions\PCLStorageExceptions.cs + + + FileSystem.cs + + + PortablePath.cs + + + Requires.cs + + + + + + + + + + + + + + {8F4C2E94-B8C5-477B-A315-CA58C70617E4} + PCLStorage.Abstractions.NoSL + + + + --> \ No newline at end of file diff --git a/src/PCLStorage.Android/Resources/Resource.Designer.cs b/src/PCLStorage.Android/Resources/Resource.Designer.cs index 124c172..8d06001 100644 --- a/src/PCLStorage.Android/Resources/Resource.Designer.cs +++ b/src/PCLStorage.Android/Resources/Resource.Designer.cs @@ -1,60 +1,60 @@ -#pragma warning disable 1591 -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.34014 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -[assembly: global::Android.Runtime.ResourceDesignerAttribute("PCLStorage.Resource", IsApplication=false)] - -namespace PCLStorage -{ - - - [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] - public partial class Resource - { - - static Resource() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - public partial class Attribute - { - - static Attribute() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Attribute() - { - } - } - - public partial class String - { - - // aapt resource value: 0x7f020001 - public static int ApplicationName = 2130837505; - - // aapt resource value: 0x7f020000 - public static int Hello = 2130837504; - - static String() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private String() - { - } - } - } -} -#pragma warning restore 1591 +#pragma warning disable 1591 +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34014 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +[assembly: global::Android.Runtime.ResourceDesignerAttribute("PCLStorage.Resource", IsApplication=false)] + +namespace PCLStorage +{ + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] + public partial class Resource + { + + static Resource() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + public partial class Attribute + { + + static Attribute() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Attribute() + { + } + } + + public partial class String + { + + // aapt resource value: 0x7f020001 + public static int ApplicationName = 2130837505; + + // aapt resource value: 0x7f020000 + public static int Hello = 2130837504; + + static String() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private String() + { + } + } + } +} +#pragma warning restore 1591 diff --git a/src/PCLStorage.FileSystem.Desktop/DesktopFileSystem.cs b/src/PCLStorage.FileSystem.Desktop/DesktopFileSystem.cs index efffdc8..76dd989 100644 --- a/src/PCLStorage.FileSystem.Desktop/DesktopFileSystem.cs +++ b/src/PCLStorage.FileSystem.Desktop/DesktopFileSystem.cs @@ -89,6 +89,15 @@ public async Task GetFolderFromPathAsync(string path, CancellationToken } return null; - } + } + + /// + /// Gets a file from the App Bundle. Returns null if the file does not exist. + /// + /// The path to a file, as returned from the property. + /// The cancellation token. + /// A file for the given path, or null if it does not exist. + public abstract Task GetFileFromAppBundleAsync(string path, CancellationToken cancellationToken); + } } diff --git a/src/PCLStorage.IsoStore.SL/IsoStoreFileSystem.cs b/src/PCLStorage.IsoStore.SL/IsoStoreFileSystem.cs index 34a1414..ebbf864 100644 --- a/src/PCLStorage.IsoStore.SL/IsoStoreFileSystem.cs +++ b/src/PCLStorage.IsoStore.SL/IsoStoreFileSystem.cs @@ -83,6 +83,18 @@ public async Task GetFolderFromPathAsync(string path, CancellationToken } return null; - } + } + + /// + /// Gets a file from the App Bundle. Returns null if the file does not exist. + /// + /// The path to a file, as returned from the property. + /// The cancellation token. + /// A file for the given path, or null if it does not exist. + public async Task GetFileFromAppBundleAsync(string path, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + } } diff --git a/src/PCLStorage.WinRT/PCLStorage.WinRT.csproj b/src/PCLStorage.WinRT/PCLStorage.WinRT.csproj index 1b617eb..cd5a284 100644 --- a/src/PCLStorage.WinRT/PCLStorage.WinRT.csproj +++ b/src/PCLStorage.WinRT/PCLStorage.WinRT.csproj @@ -1,153 +1,156 @@ - - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {AAC0913D-649A-49DD-834B-EF23D092D72B} - Library - Properties - PCLStorage - PCLStorage - en-US - 512 - {BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - ..\..\ - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE;NETFX_CORE - prompt - 4 - bin\Debug\PCLStorage.XML - - - pdbonly - true - bin\Release\ - TRACE;NETFX_CORE - prompt - 4 - bin\Release\PCLStorage.XML - - - true - bin\ARM\Debug\ - DEBUG;TRACE;NETFX_CORE - ;2008 - full - ARM - false - prompt - true - - - bin\ARM\Release\ - TRACE;NETFX_CORE - true - ;2008 - pdbonly - ARM - false - prompt - true - - - true - bin\x64\Debug\ - DEBUG;TRACE;NETFX_CORE - ;2008 - full - x64 - false - prompt - true - - - bin\x64\Release\ - TRACE;NETFX_CORE - true - ;2008 - pdbonly - x64 - false - prompt - true - - - true - bin\x86\Debug\ - DEBUG;TRACE;NETFX_CORE - ;2008 - full - x86 - false - prompt - true - - - bin\x86\Release\ - TRACE;NETFX_CORE - true - ;2008 - pdbonly - x86 - false - prompt - true - - - - Properties\CommonAssemblyInfo.cs - - - AwaitExtensions.cs - - - Exceptions\PCLStorageExceptions.cs - - - FileSystem.cs - - - PortablePath.cs - - - Requires.cs - - - - - - - - - - {8f4c2e94-b8c5-477b-a315-ca58c70617e4} - PCLStorage.Abstractions.NoSL - - - - 11.0 - - - true - - - ..\..\common\strongnamekey.snk - - + + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {AAC0913D-649A-49DD-834B-EF23D092D72B} + Library + Properties + PCLStorage + PCLStorage + en-US + 512 + {BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + true + 8.1 + 12 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE;NETFX_CORE + prompt + 4 + bin\Debug\PCLStorage.XML + + + pdbonly + true + bin\Release\ + TRACE;NETFX_CORE + prompt + 4 + bin\Release\PCLStorage.XML + + + true + bin\ARM\Debug\ + DEBUG;TRACE;NETFX_CORE + ;2008 + full + ARM + false + prompt + true + + + bin\ARM\Release\ + TRACE;NETFX_CORE + true + ;2008 + pdbonly + ARM + false + prompt + true + + + true + bin\x64\Debug\ + DEBUG;TRACE;NETFX_CORE + ;2008 + full + x64 + false + prompt + true + + + bin\x64\Release\ + TRACE;NETFX_CORE + true + ;2008 + pdbonly + x64 + false + prompt + true + + + true + bin\x86\Debug\ + DEBUG;TRACE;NETFX_CORE + ;2008 + full + x86 + false + prompt + true + + + bin\x86\Release\ + TRACE;NETFX_CORE + true + ;2008 + pdbonly + x86 + false + prompt + true + + + + Properties\CommonAssemblyInfo.cs + + + AwaitExtensions.cs + + + Exceptions\PCLStorageExceptions.cs + + + FileSystem.cs + + + PortablePath.cs + + + Requires.cs + + + + + + + + + + {8f4c2e94-b8c5-477b-a315-ca58c70617e4} + PCLStorage.Abstractions.NoSL + + + + 12.0 + + + true + + + ..\..\common\strongnamekey.snk + + + --> \ No newline at end of file diff --git a/src/PCLStorage.WinRT/WinRTFileSystem.cs b/src/PCLStorage.WinRT/WinRTFileSystem.cs index 7b13532..f9bd285 100644 --- a/src/PCLStorage.WinRT/WinRTFileSystem.cs +++ b/src/PCLStorage.WinRT/WinRTFileSystem.cs @@ -93,6 +93,31 @@ public async Task GetFolderFromPathAsync(string path, CancellationToken } return new WinRTFolder(storageFolder); + } + + /// + /// Gets a file from the App Bundle. Returns null if the file does not exist. + /// + /// The path to a file, as returned from the property. + /// The cancellation token. + /// A file for the given path, or null if it does not exist. + public async Task GetFileFromAppBundleAsync(string path, CancellationToken cancellationToken) + { + Requires.NotNullOrEmpty(path, "path"); + + StorageFile storageFile; + try + { + storageFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///" + path)).AsTask(cancellationToken).ConfigureAwait(false); + } + catch (FileNotFoundException) + { + return null; + } + + return new WinRTFile(storageFile); } + + } } diff --git a/src/PCLStorage.iOS/PCLStorage.iOS.csproj b/src/PCLStorage.iOS/PCLStorage.iOS.csproj index 6c7c058..09097a0 100644 --- a/src/PCLStorage.iOS/PCLStorage.iOS.csproj +++ b/src/PCLStorage.iOS/PCLStorage.iOS.csproj @@ -1,85 +1,86 @@ - - - - Debug - iPhoneSimulator - 8.0.30703 - 2.0 - {27A782B4-6683-4849-B951-601289C23F73} - {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Library - PCLStorage - Resources - PCLStorage - - - true - full - false - bin\iPhone\Debug - DEBUG;__IOS__;__MOBILE__;IOS;XAMARIN;FILE_SYSTEM - prompt - 4 - false - true - iPhone Developer - bin\iPhone\Debug\PCLStorage.XML - - - none - true - bin\iPhone\Release - prompt - 4 - false - iPhone Developer - __IOS__;__MOBILE__;IOS;XAMARIN;FILE_SYSTEM - bin\iPhone\Release\PCLStorage.XML - - - - Properties\CommonAssemblyInfo.cs - - - DesktopFileSystem.cs - - - FileSystemFile.cs - - - FileSystemFolder.cs - - - AwaitExtensions.cs - - - Exceptions\PCLStorageExceptions.cs - - - FileSystem.cs - - - PortablePath.cs - - - Requires.cs - - - - - - - - - - - - - - - {8F4C2E94-B8C5-477B-A315-CA58C70617E4} - PCLStorage.Abstractions.NoSL - - - + + + + Debug + iPhoneSimulator + 8.0.30703 + 2.0 + {27A782B4-6683-4849-B951-601289C23F73} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + PCLStorage + Resources + PCLStorage + + + true + full + false + bin\iPhone\Debug + DEBUG;__IOS__;__MOBILE__;IOS;XAMARIN;FILE_SYSTEM + prompt + 4 + false + true + iPhone Developer + bin\iPhone\Debug\PCLStorage.XML + + + none + true + bin\iPhone\Release + prompt + 4 + false + iPhone Developer + __IOS__;__MOBILE__;IOS;XAMARIN;FILE_SYSTEM + bin\iPhone\Release\PCLStorage.XML + + + + Properties\CommonAssemblyInfo.cs + + + DesktopFileSystem.cs + + + FileSystemFile.cs + + + FileSystemFolder.cs + + + AwaitExtensions.cs + + + Exceptions\PCLStorageExceptions.cs + + + FileSystem.cs + + + PortablePath.cs + + + Requires.cs + + + + + + + + + + + + + + + + {8F4C2E94-B8C5-477B-A315-CA58C70617E4} + PCLStorage.Abstractions.NoSL + + + \ No newline at end of file diff --git a/src/PCLStorage.iOS/iOSFileSystem.cs b/src/PCLStorage.iOS/iOSFileSystem.cs new file mode 100644 index 0000000..b2e9710 --- /dev/null +++ b/src/PCLStorage.iOS/iOSFileSystem.cs @@ -0,0 +1,43 @@ +using MonoTouch.Foundation; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace PCLStorage +{ + /// + /// Implementation of over classic .NET file I/O APIs + /// + public abstract class iOSFileSystem + { + /// + /// Gets a file from the App Bundle. Returns null if the file does not exist. + /// + /// The path to a file, as returned from the property. + /// The cancellation token. + /// A file for the given path, or null if it does not exist. + public async Task GetFileFromAppBundleAsync(string path, CancellationToken cancellationToken) + { + Requires.NotNullOrEmpty(path, "path"); + + await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken); + + var extension = new NSString(path).PathExtension; + var filename = new NSString(path).LastPathComponent.DeletePathExtension(); + var bundlePath = NSBundle.MainBundle.PathForResource(filename, extension); + + if (File.Exists(bundlePath)) + { + return new FileSystemFile(bundlePath); + } + + return null; + + } + + } +} diff --git a/test/PCLStorage.Test.Android/PCLStorage.Test.Android.csproj b/test/PCLStorage.Test.Android/PCLStorage.Test.Android.csproj index a4c09d6..3a88aec 100644 --- a/test/PCLStorage.Test.Android/PCLStorage.Test.Android.csproj +++ b/test/PCLStorage.Test.Android/PCLStorage.Test.Android.csproj @@ -1,114 +1,115 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {32922221-A523-4673-9C77-DE6B01C91F3D} - {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Library - Properties - PCLStorage.Test.Android - PCLStorage.Test.Android - 512 - true - Resources\Resource.Designer.cs - Off - v3.1 - Properties\AndroidManifest.xml - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - True - None - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - False - SdkOnly - - - - False - ..\..\packages\Microsoft.Bcl.Async.1.0.165\lib\portable-net45+win8\Microsoft.Threading.Tasks.dll - - - False - ..\..\packages\Microsoft.Bcl.Async.1.0.165\lib\portable-net45+win8\Microsoft.Threading.Tasks.Extensions.dll - - - - - ..\..\packages\PCLTesting.0.1.1\lib\portable-net45+sl5+wp8+win8+monoandroid+monotouch\PCLTesting.dll - - - ..\..\packages\PCLTesting.0.1.1\lib\portable-net45+sl5+wp8+win8+monoandroid+monotouch\PCLTesting.Portable.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {eebb53f3-ebdf-4dd0-82e5-ff9a2c8dbd72} - PCLStorage.Abstractions - - - {d813c9d8-d6d1-4d2b-af04-0d877656f47e} - PCLStorage.Android - - - {28668411-c26f-434f-88b1-b7e5f8d39c61} - PCLStorage.Test - - - - - - - - + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {32922221-A523-4673-9C77-DE6B01C91F3D} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + Properties + PCLStorage.Test.Android + PCLStorage.Test.Android + 512 + true + Resources\Resource.Designer.cs + Off + v5.0 + Properties\AndroidManifest.xml + True + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + True + None + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + False + SdkOnly + + + + False + ..\..\packages\Microsoft.Bcl.Async.1.0.165\lib\portable-net45+win8\Microsoft.Threading.Tasks.dll + + + False + ..\..\packages\Microsoft.Bcl.Async.1.0.165\lib\portable-net45+win8\Microsoft.Threading.Tasks.Extensions.dll + + + + + ..\..\packages\PCLTesting.0.1.1\lib\portable-net45+sl5+wp8+win8+monoandroid+monotouch\PCLTesting.dll + + + ..\..\packages\PCLTesting.0.1.1\lib\portable-net45+sl5+wp8+win8+monoandroid+monotouch\PCLTesting.Portable.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {eebb53f3-ebdf-4dd0-82e5-ff9a2c8dbd72} + PCLStorage.Abstractions + + + {d813c9d8-d6d1-4d2b-af04-0d877656f47e} + PCLStorage.Android + + + {28668411-c26f-434f-88b1-b7e5f8d39c61} + PCLStorage.Test + + + + + + + + + --> \ No newline at end of file diff --git a/test/PCLStorage.Test.Android/Properties/AndroidManifest.xml b/test/PCLStorage.Test.Android/Properties/AndroidManifest.xml index 409ac18..66b9fbe 100644 --- a/test/PCLStorage.Test.Android/Properties/AndroidManifest.xml +++ b/test/PCLStorage.Test.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/test/PCLStorage.Test.Android/Resources/Resource.Designer.cs b/test/PCLStorage.Test.Android/Resources/Resource.Designer.cs index bbe8ac5..1245909 100644 --- a/test/PCLStorage.Test.Android/Resources/Resource.Designer.cs +++ b/test/PCLStorage.Test.Android/Resources/Resource.Designer.cs @@ -1,120 +1,120 @@ -#pragma warning disable 1591 -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.34014 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -[assembly: global::Android.Runtime.ResourceDesignerAttribute("PCLStorage.Test.Android.Resource", IsApplication=true)] - -namespace PCLStorage.Test.Android -{ - - - [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] - public partial class Resource - { - - static Resource() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - public static void UpdateIdValues() - { - global::PCLStorage.Resource.String.ApplicationName = global::PCLStorage.Test.Android.Resource.String.ApplicationName; - global::PCLStorage.Resource.String.Hello = global::PCLStorage.Test.Android.Resource.String.Hello; - } - - public partial class Attribute - { - - static Attribute() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Attribute() - { - } - } - - public partial class Drawable - { - - // aapt resource value: 0x7f020000 - public const int Icon = 2130837504; - - static Drawable() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Drawable() - { - } - } - - public partial class Id - { - - // aapt resource value: 0x7f050001 - public const int ClearStorage = 2131034113; - - // aapt resource value: 0x7f050002 - public const int ResultsTextView = 2131034114; - - // aapt resource value: 0x7f050000 - public const int RunTests = 2131034112; - - static Id() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Id() - { - } - } - - public partial class Layout - { - - // aapt resource value: 0x7f030000 - public const int Main = 2130903040; - - static Layout() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Layout() - { - } - } - - public partial class String - { - - // aapt resource value: 0x7f040001 - public const int ApplicationName = 2130968577; - - // aapt resource value: 0x7f040000 - public const int Hello = 2130968576; - - static String() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private String() - { - } - } - } -} -#pragma warning restore 1591 +#pragma warning disable 1591 +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34014 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +[assembly: global::Android.Runtime.ResourceDesignerAttribute("PCLStorage.Test.Android.Resource", IsApplication=true)] + +namespace PCLStorage.Test.Android +{ + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] + public partial class Resource + { + + static Resource() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + public static void UpdateIdValues() + { + global::PCLStorage.Resource.String.ApplicationName = global::PCLStorage.Test.Android.Resource.String.ApplicationName; + global::PCLStorage.Resource.String.Hello = global::PCLStorage.Test.Android.Resource.String.Hello; + } + + public partial class Attribute + { + + static Attribute() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Attribute() + { + } + } + + public partial class Drawable + { + + // aapt resource value: 0x7f020000 + public const int Icon = 2130837504; + + static Drawable() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Drawable() + { + } + } + + public partial class Id + { + + // aapt resource value: 0x7f050001 + public const int ClearStorage = 2131034113; + + // aapt resource value: 0x7f050002 + public const int ResultsTextView = 2131034114; + + // aapt resource value: 0x7f050000 + public const int RunTests = 2131034112; + + static Id() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Id() + { + } + } + + public partial class Layout + { + + // aapt resource value: 0x7f030000 + public const int Main = 2130903040; + + static Layout() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Layout() + { + } + } + + public partial class String + { + + // aapt resource value: 0x7f040001 + public const int ApplicationName = 2130968577; + + // aapt resource value: 0x7f040000 + public const int Hello = 2130968576; + + static String() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private String() + { + } + } + } +} +#pragma warning restore 1591 diff --git a/test/PCLStorage.Test.WinRT/PCLStorage.Test.WinRT.csproj b/test/PCLStorage.Test.WinRT/PCLStorage.Test.WinRT.csproj index 4b47403..d9074c9 100644 --- a/test/PCLStorage.Test.WinRT/PCLStorage.Test.WinRT.csproj +++ b/test/PCLStorage.Test.WinRT/PCLStorage.Test.WinRT.csproj @@ -1,190 +1,194 @@ - - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812} - Library - Properties - PCLStorage.Test.WinRT - PCLStorage.Test.WinRT - en-US - 512 - {BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - PCLStorage.Test.WinRT_TemporaryKey.pfx - E981B30FB12863F00C468F6DBAFFF71A1DAFD429 - ..\..\ - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE;NETFX_CORE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE;NETFX_CORE - prompt - 4 - - - true - bin\ARM\Debug\ - DEBUG;TRACE;NETFX_CORE - ;2008 - full - ARM - false - prompt - true - - - bin\ARM\Release\ - TRACE;NETFX_CORE - true - ;2008 - pdbonly - ARM - false - prompt - true - - - true - bin\x64\Debug\ - DEBUG;TRACE;NETFX_CORE - ;2008 - full - x64 - false - prompt - true - - - bin\x64\Release\ - TRACE;NETFX_CORE - true - ;2008 - pdbonly - x64 - false - prompt - true - - - true - bin\x86\Debug\ - DEBUG;TRACE;NETFX_CORE - ;2008 - full - x86 - false - prompt - true - - - bin\x86\Release\ - TRACE;NETFX_CORE - true - ;2008 - pdbonly - x86 - false - prompt - true - - - True - true - - - - - - - - - UIDispatcherMock.cs - - - FileSystemTests.cs - - - FileTests.cs - - - FolderTests.cs - - - - - - - Designer - - - - - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - - - {8f4c2e94-b8c5-477b-a315-ca58c70617e4} - PCLStorage.Abstractions.NoSL - - - {aac0913d-649a-49dd-834b-ef23d092d72b} - PCLStorage.WinRT - - - - - False - ..\..\packages\Microsoft.Bcl.Async.1.0.165\lib\win8\Microsoft.Threading.Tasks.dll - - - False - ..\..\packages\Microsoft.Bcl.Async.1.0.165\lib\win8\Microsoft.Threading.Tasks.Extensions.dll - - - ..\..\packages\PCLTesting.0.1.1\lib\win8\PCLTesting.dll - - - - 11.0 - - - - - - - + + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812} + Library + Properties + PCLStorage.Test.WinRT + PCLStorage.Test.WinRT + en-US + 512 + {BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + PCLStorage.Test.WinRT_TemporaryKey.pfx + E981B30FB12863F00C468F6DBAFFF71A1DAFD429 + ..\..\ + true + 8.1 + 12 + + Never + + + true + full + false + bin\Debug\ + DEBUG;TRACE;NETFX_CORE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE;NETFX_CORE + prompt + 4 + + + true + bin\ARM\Debug\ + DEBUG;TRACE;NETFX_CORE + ;2008 + full + ARM + false + prompt + true + + + bin\ARM\Release\ + TRACE;NETFX_CORE + true + ;2008 + pdbonly + ARM + false + prompt + true + + + true + bin\x64\Debug\ + DEBUG;TRACE;NETFX_CORE + ;2008 + full + x64 + false + prompt + true + + + bin\x64\Release\ + TRACE;NETFX_CORE + true + ;2008 + pdbonly + x64 + false + prompt + true + + + true + bin\x86\Debug\ + DEBUG;TRACE;NETFX_CORE + ;2008 + full + x86 + false + prompt + true + + + bin\x86\Release\ + TRACE;NETFX_CORE + true + ;2008 + pdbonly + x86 + false + prompt + true + + + True + true + + + + + + + + + UIDispatcherMock.cs + + + FileSystemTests.cs + + + FileTests.cs + + + FolderTests.cs + + + + + + + Designer + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + + {8f4c2e94-b8c5-477b-a315-ca58c70617e4} + PCLStorage.Abstractions.NoSL + + + {aac0913d-649a-49dd-834b-ef23d092d72b} + PCLStorage.WinRT + + + + + False + ..\..\packages\Microsoft.Bcl.Async.1.0.165\lib\win8\Microsoft.Threading.Tasks.dll + + + False + ..\..\packages\Microsoft.Bcl.Async.1.0.165\lib\win8\Microsoft.Threading.Tasks.Extensions.dll + + + ..\..\packages\PCLTesting.0.1.1\lib\win8\PCLTesting.dll + + + + 12.0 + + + + + + + + --> \ No newline at end of file diff --git a/test/PCLStorage.Test.WinRT/Package.appxmanifest b/test/PCLStorage.Test.WinRT/Package.appxmanifest index b5a12c3..cc6cf66 100644 --- a/test/PCLStorage.Test.WinRT/Package.appxmanifest +++ b/test/PCLStorage.Test.WinRT/Package.appxmanifest @@ -1,33 +1,32 @@ - - - - - PCLStorage.Test.WinRT - Daniel - Images\UnitTestStoreLogo.png - PCLStorage.Test.WinRT - - - 6.2.1 - 6.2.1 - - - - - - - - - - - - - - - - - - - - + + + + + PCLStorage.Test.WinRT + Daniel + Images\UnitTestStoreLogo.png + PCLStorage.Test.WinRT + + + 6.3.0 + 6.3.0 + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 2a971da69f636da57b0ccacb488549333ead9000 Mon Sep 17 00:00:00 2001 From: Juergen Koller Date: Sun, 31 May 2015 13:33:56 +0200 Subject: [PATCH 2/9] Zip abstraction test --- PCLStorage.sln | 592 +++++++------- build/build.proj | 2 +- common/CommonAssemblyInfo.cs | 4 +- src/PCLStorage.Abstractions/IFile.cs | 29 +- .../PCLStorage.Abstractions.csproj | 166 ++-- .../PCLStorage.Android.csproj | 3 + .../DesktopFileSystem.cs | 7 +- .../FileSystemFile.cs | 67 +- .../PCLStorage.FileSystem.Desktop.csproj | 175 ++-- src/PCLStorage.IsoStore.SL/IsoStoreFile.cs | 8 +- src/PCLStorage.WinRT/WinRTFile.cs | 56 +- .../PCLStorage.WindowsPhone.csproj | 292 +++---- .../PCLStorage.iOS-Unified.csproj | 167 ++-- src/PCLStorage.iOS/PCLStorage.iOS.csproj | 3 + src/Zip/ZipStorer.cs | 773 ++++++++++++++++++ 15 files changed, 1618 insertions(+), 726 deletions(-) create mode 100644 src/Zip/ZipStorer.cs diff --git a/PCLStorage.sln b/PCLStorage.sln index 480072e..7f78688 100644 --- a/PCLStorage.sln +++ b/PCLStorage.sln @@ -1,295 +1,297 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22310.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{70760DD8-A408-4274-AAFE-0E06BC98DEDB}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.Test", "test\PCLStorage.Test\PCLStorage.Test.csproj", "{28668411-C26F-434F-88B1-B7E5F8D39C61}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.Test.SL", "test\PCLStorage.Test.SL\PCLStorage.Test.SL.csproj", "{5568B9DA-132A-4031-9457-01C003FA5CB4}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{2318AF06-489F-4509-BC7E-84067C903AAD}" - ProjectSection(SolutionItems) = preProject - .nuget\NuGet.Config = .nuget\NuGet.Config - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.Test.WindowsPhone", "test\PCLStorage.Test.WindowsPhone\PCLStorage.Test.WindowsPhone.csproj", "{A49660EE-789F-4EFF-A946-10532D3EA7E6}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.Test.Desktop", "test\PCLStorage.Test.Desktop\PCLStorage.Test.Desktop.csproj", "{13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.Test.WinRT", "test\PCLStorage.Test.WinRT\PCLStorage.Test.WinRT.csproj", "{220CC1AA-AEEC-4DF7-94E6-9BBF23486812}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{1E53EE83-AD17-4F75-A77D-B0A12961A232}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage", "src\PCLStorage\PCLStorage.csproj", "{31F6B895-4FF7-481B-B483-E0E6B63CC312}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.NoSL", "src\PCLStorage.NoSL\PCLStorage.NoSL.csproj", "{F878EC6F-6C59-4860-A2D1-0CD2C97760A7}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.FileSystem.Desktop", "src\PCLStorage.FileSystem.Desktop\PCLStorage.FileSystem.Desktop.csproj", "{9D3F208D-8BB4-47A9-8323-4CFD24314341}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.IsoStore.SL", "src\PCLStorage.IsoStore.SL\PCLStorage.IsoStore.SL.csproj", "{793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.WinRT", "src\PCLStorage.WinRT\PCLStorage.WinRT.csproj", "{AAC0913D-649A-49DD-834B-EF23D092D72B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.Abstractions", "src\PCLStorage.Abstractions\PCLStorage.Abstractions.csproj", "{EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.Abstractions.NoSL", "src\PCLStorage.Abstractions.NoSL\PCLStorage.Abstractions.NoSL.csproj", "{8F4C2E94-B8C5-477B-A315-CA58C70617E4}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.WindowsPhone", "src\PCLStorage.WindowsPhone\PCLStorage.WindowsPhone.csproj", "{D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.Android", "src\PCLStorage.Android\PCLStorage.Android.csproj", "{D813C9D8-D6D1-4D2B-AF04-0D877656F47E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.Test.Android", "test\PCLStorage.Test.Android\PCLStorage.Test.Android.csproj", "{32922221-A523-4673-9C77-DE6B01C91F3D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.iOS", "src\PCLStorage.iOS\PCLStorage.iOS.csproj", "{27A782B4-6683-4849-B951-601289C23F73}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{A5AE3457-DDFF-432A-90D6-8462B560603C}" - ProjectSection(SolutionItems) = preProject - build\build.proj = build\build.proj - common\CommonAssemblyInfo.cs = common\CommonAssemblyInfo.cs - common\PCLStorage.nuspec = common\PCLStorage.nuspec - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.iOS-Unified", "src\PCLStorage.iOS-Unified\PCLStorage.iOS-Unified.csproj", "{3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|ARM = Debug|ARM - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|ARM = Release|ARM - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {28668411-C26F-434F-88B1-B7E5F8D39C61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {28668411-C26F-434F-88B1-B7E5F8D39C61}.Debug|Any CPU.Build.0 = Debug|Any CPU - {28668411-C26F-434F-88B1-B7E5F8D39C61}.Debug|ARM.ActiveCfg = Debug|Any CPU - {28668411-C26F-434F-88B1-B7E5F8D39C61}.Debug|x64.ActiveCfg = Debug|Any CPU - {28668411-C26F-434F-88B1-B7E5F8D39C61}.Debug|x86.ActiveCfg = Debug|Any CPU - {28668411-C26F-434F-88B1-B7E5F8D39C61}.Release|Any CPU.ActiveCfg = Release|Any CPU - {28668411-C26F-434F-88B1-B7E5F8D39C61}.Release|Any CPU.Build.0 = Release|Any CPU - {28668411-C26F-434F-88B1-B7E5F8D39C61}.Release|ARM.ActiveCfg = Release|Any CPU - {28668411-C26F-434F-88B1-B7E5F8D39C61}.Release|x64.ActiveCfg = Release|Any CPU - {28668411-C26F-434F-88B1-B7E5F8D39C61}.Release|x86.ActiveCfg = Release|Any CPU - {5568B9DA-132A-4031-9457-01C003FA5CB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5568B9DA-132A-4031-9457-01C003FA5CB4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5568B9DA-132A-4031-9457-01C003FA5CB4}.Debug|ARM.ActiveCfg = Debug|Any CPU - {5568B9DA-132A-4031-9457-01C003FA5CB4}.Debug|x64.ActiveCfg = Debug|Any CPU - {5568B9DA-132A-4031-9457-01C003FA5CB4}.Debug|x86.ActiveCfg = Debug|Any CPU - {5568B9DA-132A-4031-9457-01C003FA5CB4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5568B9DA-132A-4031-9457-01C003FA5CB4}.Release|Any CPU.Build.0 = Release|Any CPU - {5568B9DA-132A-4031-9457-01C003FA5CB4}.Release|ARM.ActiveCfg = Release|Any CPU - {5568B9DA-132A-4031-9457-01C003FA5CB4}.Release|x64.ActiveCfg = Release|Any CPU - {5568B9DA-132A-4031-9457-01C003FA5CB4}.Release|x86.ActiveCfg = Release|Any CPU - {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Debug|ARM.ActiveCfg = Debug|Any CPU - {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Debug|x64.ActiveCfg = Debug|Any CPU - {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Debug|x86.ActiveCfg = Debug|Any CPU - {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Release|Any CPU.Build.0 = Release|Any CPU - {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Release|Any CPU.Deploy.0 = Release|Any CPU - {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Release|ARM.ActiveCfg = Release|Any CPU - {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Release|x64.ActiveCfg = Release|Any CPU - {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Release|x86.ActiveCfg = Release|Any CPU - {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}.Debug|Any CPU.Build.0 = Debug|Any CPU - {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}.Debug|ARM.ActiveCfg = Debug|Any CPU - {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}.Debug|x64.ActiveCfg = Debug|Any CPU - {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}.Debug|x86.ActiveCfg = Debug|Any CPU - {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}.Release|Any CPU.ActiveCfg = Release|Any CPU - {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}.Release|Any CPU.Build.0 = Release|Any CPU - {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}.Release|ARM.ActiveCfg = Release|Any CPU - {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}.Release|x64.ActiveCfg = Release|Any CPU - {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}.Release|x86.ActiveCfg = Release|Any CPU - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|Any CPU.Build.0 = Debug|Any CPU - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|ARM.ActiveCfg = Debug|ARM - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|ARM.Build.0 = Debug|ARM - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|ARM.Deploy.0 = Debug|ARM - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|x64.ActiveCfg = Debug|x64 - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|x64.Build.0 = Debug|x64 - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|x64.Deploy.0 = Debug|x64 - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|x86.ActiveCfg = Debug|x86 - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|x86.Build.0 = Debug|x86 - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|x86.Deploy.0 = Debug|x86 - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|Any CPU.ActiveCfg = Release|Any CPU - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|Any CPU.Build.0 = Release|Any CPU - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|Any CPU.Deploy.0 = Release|Any CPU - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|ARM.ActiveCfg = Release|ARM - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|ARM.Build.0 = Release|ARM - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|ARM.Deploy.0 = Release|ARM - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|x64.ActiveCfg = Release|x64 - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|x64.Build.0 = Release|x64 - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|x64.Deploy.0 = Release|x64 - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|x86.ActiveCfg = Release|x86 - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|x86.Build.0 = Release|x86 - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|x86.Deploy.0 = Release|x86 - {31F6B895-4FF7-481B-B483-E0E6B63CC312}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {31F6B895-4FF7-481B-B483-E0E6B63CC312}.Debug|Any CPU.Build.0 = Debug|Any CPU - {31F6B895-4FF7-481B-B483-E0E6B63CC312}.Debug|ARM.ActiveCfg = Debug|Any CPU - {31F6B895-4FF7-481B-B483-E0E6B63CC312}.Debug|x64.ActiveCfg = Debug|Any CPU - {31F6B895-4FF7-481B-B483-E0E6B63CC312}.Debug|x86.ActiveCfg = Debug|Any CPU - {31F6B895-4FF7-481B-B483-E0E6B63CC312}.Release|Any CPU.ActiveCfg = Release|Any CPU - {31F6B895-4FF7-481B-B483-E0E6B63CC312}.Release|Any CPU.Build.0 = Release|Any CPU - {31F6B895-4FF7-481B-B483-E0E6B63CC312}.Release|ARM.ActiveCfg = Release|Any CPU - {31F6B895-4FF7-481B-B483-E0E6B63CC312}.Release|x64.ActiveCfg = Release|Any CPU - {31F6B895-4FF7-481B-B483-E0E6B63CC312}.Release|x86.ActiveCfg = Release|Any CPU - {F878EC6F-6C59-4860-A2D1-0CD2C97760A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F878EC6F-6C59-4860-A2D1-0CD2C97760A7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F878EC6F-6C59-4860-A2D1-0CD2C97760A7}.Debug|ARM.ActiveCfg = Debug|Any CPU - {F878EC6F-6C59-4860-A2D1-0CD2C97760A7}.Debug|x64.ActiveCfg = Debug|Any CPU - {F878EC6F-6C59-4860-A2D1-0CD2C97760A7}.Debug|x86.ActiveCfg = Debug|Any CPU - {F878EC6F-6C59-4860-A2D1-0CD2C97760A7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F878EC6F-6C59-4860-A2D1-0CD2C97760A7}.Release|Any CPU.Build.0 = Release|Any CPU - {F878EC6F-6C59-4860-A2D1-0CD2C97760A7}.Release|ARM.ActiveCfg = Release|Any CPU - {F878EC6F-6C59-4860-A2D1-0CD2C97760A7}.Release|x64.ActiveCfg = Release|Any CPU - {F878EC6F-6C59-4860-A2D1-0CD2C97760A7}.Release|x86.ActiveCfg = Release|Any CPU - {9D3F208D-8BB4-47A9-8323-4CFD24314341}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9D3F208D-8BB4-47A9-8323-4CFD24314341}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9D3F208D-8BB4-47A9-8323-4CFD24314341}.Debug|ARM.ActiveCfg = Debug|Any CPU - {9D3F208D-8BB4-47A9-8323-4CFD24314341}.Debug|x64.ActiveCfg = Debug|Any CPU - {9D3F208D-8BB4-47A9-8323-4CFD24314341}.Debug|x86.ActiveCfg = Debug|Any CPU - {9D3F208D-8BB4-47A9-8323-4CFD24314341}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9D3F208D-8BB4-47A9-8323-4CFD24314341}.Release|Any CPU.Build.0 = Release|Any CPU - {9D3F208D-8BB4-47A9-8323-4CFD24314341}.Release|ARM.ActiveCfg = Release|Any CPU - {9D3F208D-8BB4-47A9-8323-4CFD24314341}.Release|x64.ActiveCfg = Release|Any CPU - {9D3F208D-8BB4-47A9-8323-4CFD24314341}.Release|x86.ActiveCfg = Release|Any CPU - {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}.Debug|ARM.ActiveCfg = Debug|Any CPU - {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}.Debug|x64.ActiveCfg = Debug|Any CPU - {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}.Debug|x86.ActiveCfg = Debug|Any CPU - {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}.Release|Any CPU.Build.0 = Release|Any CPU - {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}.Release|ARM.ActiveCfg = Release|Any CPU - {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}.Release|x64.ActiveCfg = Release|Any CPU - {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}.Release|x86.ActiveCfg = Release|Any CPU - {AAC0913D-649A-49DD-834B-EF23D092D72B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AAC0913D-649A-49DD-834B-EF23D092D72B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AAC0913D-649A-49DD-834B-EF23D092D72B}.Debug|ARM.ActiveCfg = Debug|ARM - {AAC0913D-649A-49DD-834B-EF23D092D72B}.Debug|ARM.Build.0 = Debug|ARM - {AAC0913D-649A-49DD-834B-EF23D092D72B}.Debug|x64.ActiveCfg = Debug|x64 - {AAC0913D-649A-49DD-834B-EF23D092D72B}.Debug|x64.Build.0 = Debug|x64 - {AAC0913D-649A-49DD-834B-EF23D092D72B}.Debug|x86.ActiveCfg = Debug|x86 - {AAC0913D-649A-49DD-834B-EF23D092D72B}.Debug|x86.Build.0 = Debug|x86 - {AAC0913D-649A-49DD-834B-EF23D092D72B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AAC0913D-649A-49DD-834B-EF23D092D72B}.Release|Any CPU.Build.0 = Release|Any CPU - {AAC0913D-649A-49DD-834B-EF23D092D72B}.Release|ARM.ActiveCfg = Release|ARM - {AAC0913D-649A-49DD-834B-EF23D092D72B}.Release|ARM.Build.0 = Release|ARM - {AAC0913D-649A-49DD-834B-EF23D092D72B}.Release|x64.ActiveCfg = Release|x64 - {AAC0913D-649A-49DD-834B-EF23D092D72B}.Release|x64.Build.0 = Release|x64 - {AAC0913D-649A-49DD-834B-EF23D092D72B}.Release|x86.ActiveCfg = Release|x86 - {AAC0913D-649A-49DD-834B-EF23D092D72B}.Release|x86.Build.0 = Release|x86 - {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}.Debug|ARM.ActiveCfg = Debug|Any CPU - {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}.Debug|x64.ActiveCfg = Debug|Any CPU - {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}.Debug|x86.ActiveCfg = Debug|Any CPU - {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}.Release|Any CPU.Build.0 = Release|Any CPU - {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}.Release|ARM.ActiveCfg = Release|Any CPU - {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}.Release|x64.ActiveCfg = Release|Any CPU - {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}.Release|x86.ActiveCfg = Release|Any CPU - {8F4C2E94-B8C5-477B-A315-CA58C70617E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8F4C2E94-B8C5-477B-A315-CA58C70617E4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8F4C2E94-B8C5-477B-A315-CA58C70617E4}.Debug|ARM.ActiveCfg = Debug|Any CPU - {8F4C2E94-B8C5-477B-A315-CA58C70617E4}.Debug|x64.ActiveCfg = Debug|Any CPU - {8F4C2E94-B8C5-477B-A315-CA58C70617E4}.Debug|x86.ActiveCfg = Debug|Any CPU - {8F4C2E94-B8C5-477B-A315-CA58C70617E4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8F4C2E94-B8C5-477B-A315-CA58C70617E4}.Release|Any CPU.Build.0 = Release|Any CPU - {8F4C2E94-B8C5-477B-A315-CA58C70617E4}.Release|ARM.ActiveCfg = Release|Any CPU - {8F4C2E94-B8C5-477B-A315-CA58C70617E4}.Release|x64.ActiveCfg = Release|Any CPU - {8F4C2E94-B8C5-477B-A315-CA58C70617E4}.Release|x86.ActiveCfg = Release|Any CPU - {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Debug|ARM.ActiveCfg = Debug|ARM - {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Debug|ARM.Build.0 = Debug|ARM - {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Debug|x64.ActiveCfg = Debug|Any CPU - {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Debug|x86.ActiveCfg = Debug|x86 - {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Debug|x86.Build.0 = Debug|x86 - {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Release|Any CPU.Build.0 = Release|Any CPU - {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Release|ARM.ActiveCfg = Release|ARM - {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Release|ARM.Build.0 = Release|ARM - {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Release|x64.ActiveCfg = Release|Any CPU - {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Release|x86.ActiveCfg = Release|x86 - {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Release|x86.Build.0 = Release|x86 - {D813C9D8-D6D1-4D2B-AF04-0D877656F47E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D813C9D8-D6D1-4D2B-AF04-0D877656F47E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D813C9D8-D6D1-4D2B-AF04-0D877656F47E}.Debug|ARM.ActiveCfg = Debug|Any CPU - {D813C9D8-D6D1-4D2B-AF04-0D877656F47E}.Debug|x64.ActiveCfg = Debug|Any CPU - {D813C9D8-D6D1-4D2B-AF04-0D877656F47E}.Debug|x86.ActiveCfg = Debug|Any CPU - {D813C9D8-D6D1-4D2B-AF04-0D877656F47E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D813C9D8-D6D1-4D2B-AF04-0D877656F47E}.Release|Any CPU.Build.0 = Release|Any CPU - {D813C9D8-D6D1-4D2B-AF04-0D877656F47E}.Release|ARM.ActiveCfg = Release|Any CPU - {D813C9D8-D6D1-4D2B-AF04-0D877656F47E}.Release|x64.ActiveCfg = Release|Any CPU - {D813C9D8-D6D1-4D2B-AF04-0D877656F47E}.Release|x86.ActiveCfg = Release|Any CPU - {32922221-A523-4673-9C77-DE6B01C91F3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {32922221-A523-4673-9C77-DE6B01C91F3D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {32922221-A523-4673-9C77-DE6B01C91F3D}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {32922221-A523-4673-9C77-DE6B01C91F3D}.Debug|ARM.ActiveCfg = Debug|Any CPU - {32922221-A523-4673-9C77-DE6B01C91F3D}.Debug|x64.ActiveCfg = Debug|Any CPU - {32922221-A523-4673-9C77-DE6B01C91F3D}.Debug|x86.ActiveCfg = Debug|Any CPU - {32922221-A523-4673-9C77-DE6B01C91F3D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {32922221-A523-4673-9C77-DE6B01C91F3D}.Release|Any CPU.Build.0 = Release|Any CPU - {32922221-A523-4673-9C77-DE6B01C91F3D}.Release|Any CPU.Deploy.0 = Release|Any CPU - {32922221-A523-4673-9C77-DE6B01C91F3D}.Release|ARM.ActiveCfg = Release|Any CPU - {32922221-A523-4673-9C77-DE6B01C91F3D}.Release|x64.ActiveCfg = Release|Any CPU - {32922221-A523-4673-9C77-DE6B01C91F3D}.Release|x86.ActiveCfg = Release|Any CPU - {27A782B4-6683-4849-B951-601289C23F73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {27A782B4-6683-4849-B951-601289C23F73}.Debug|Any CPU.Build.0 = Debug|Any CPU - {27A782B4-6683-4849-B951-601289C23F73}.Debug|ARM.ActiveCfg = Debug|Any CPU - {27A782B4-6683-4849-B951-601289C23F73}.Debug|x64.ActiveCfg = Debug|Any CPU - {27A782B4-6683-4849-B951-601289C23F73}.Debug|x86.ActiveCfg = Debug|Any CPU - {27A782B4-6683-4849-B951-601289C23F73}.Release|Any CPU.ActiveCfg = Release|Any CPU - {27A782B4-6683-4849-B951-601289C23F73}.Release|Any CPU.Build.0 = Release|Any CPU - {27A782B4-6683-4849-B951-601289C23F73}.Release|ARM.ActiveCfg = Release|Any CPU - {27A782B4-6683-4849-B951-601289C23F73}.Release|x64.ActiveCfg = Release|Any CPU - {27A782B4-6683-4849-B951-601289C23F73}.Release|x86.ActiveCfg = Release|Any CPU - {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Debug|ARM.ActiveCfg = Debug|Any CPU - {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Debug|ARM.Build.0 = Debug|Any CPU - {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Debug|x64.ActiveCfg = Debug|Any CPU - {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Debug|x64.Build.0 = Debug|Any CPU - {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Debug|x86.ActiveCfg = Debug|Any CPU - {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Debug|x86.Build.0 = Debug|Any CPU - {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Release|Any CPU.Build.0 = Release|Any CPU - {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Release|ARM.ActiveCfg = Release|Any CPU - {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Release|ARM.Build.0 = Release|Any CPU - {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Release|x64.ActiveCfg = Release|Any CPU - {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Release|x64.Build.0 = Release|Any CPU - {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Release|x86.ActiveCfg = Release|Any CPU - {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {28668411-C26F-434F-88B1-B7E5F8D39C61} = {70760DD8-A408-4274-AAFE-0E06BC98DEDB} - {5568B9DA-132A-4031-9457-01C003FA5CB4} = {70760DD8-A408-4274-AAFE-0E06BC98DEDB} - {A49660EE-789F-4EFF-A946-10532D3EA7E6} = {70760DD8-A408-4274-AAFE-0E06BC98DEDB} - {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66} = {70760DD8-A408-4274-AAFE-0E06BC98DEDB} - {220CC1AA-AEEC-4DF7-94E6-9BBF23486812} = {70760DD8-A408-4274-AAFE-0E06BC98DEDB} - {31F6B895-4FF7-481B-B483-E0E6B63CC312} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} - {F878EC6F-6C59-4860-A2D1-0CD2C97760A7} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} - {9D3F208D-8BB4-47A9-8323-4CFD24314341} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} - {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} - {AAC0913D-649A-49DD-834B-EF23D092D72B} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} - {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} - {8F4C2E94-B8C5-477B-A315-CA58C70617E4} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} - {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} - {D813C9D8-D6D1-4D2B-AF04-0D877656F47E} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} - {32922221-A523-4673-9C77-DE6B01C91F3D} = {70760DD8-A408-4274-AAFE-0E06BC98DEDB} - {27A782B4-6683-4849-B951-601289C23F73} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} - {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.31101.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{70760DD8-A408-4274-AAFE-0E06BC98DEDB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.Test", "test\PCLStorage.Test\PCLStorage.Test.csproj", "{28668411-C26F-434F-88B1-B7E5F8D39C61}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.Test.SL", "test\PCLStorage.Test.SL\PCLStorage.Test.SL.csproj", "{5568B9DA-132A-4031-9457-01C003FA5CB4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{2318AF06-489F-4509-BC7E-84067C903AAD}" + ProjectSection(SolutionItems) = preProject + .nuget\NuGet.Config = .nuget\NuGet.Config + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.Test.WindowsPhone", "test\PCLStorage.Test.WindowsPhone\PCLStorage.Test.WindowsPhone.csproj", "{A49660EE-789F-4EFF-A946-10532D3EA7E6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.Test.Desktop", "test\PCLStorage.Test.Desktop\PCLStorage.Test.Desktop.csproj", "{13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.Test.WinRT", "test\PCLStorage.Test.WinRT\PCLStorage.Test.WinRT.csproj", "{220CC1AA-AEEC-4DF7-94E6-9BBF23486812}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{1E53EE83-AD17-4F75-A77D-B0A12961A232}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage", "src\PCLStorage\PCLStorage.csproj", "{31F6B895-4FF7-481B-B483-E0E6B63CC312}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.NoSL", "src\PCLStorage.NoSL\PCLStorage.NoSL.csproj", "{F878EC6F-6C59-4860-A2D1-0CD2C97760A7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.FileSystem.Desktop", "src\PCLStorage.FileSystem.Desktop\PCLStorage.FileSystem.Desktop.csproj", "{9D3F208D-8BB4-47A9-8323-4CFD24314341}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.IsoStore.SL", "src\PCLStorage.IsoStore.SL\PCLStorage.IsoStore.SL.csproj", "{793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.WinRT", "src\PCLStorage.WinRT\PCLStorage.WinRT.csproj", "{AAC0913D-649A-49DD-834B-EF23D092D72B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.Abstractions", "src\PCLStorage.Abstractions\PCLStorage.Abstractions.csproj", "{EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.Abstractions.NoSL", "src\PCLStorage.Abstractions.NoSL\PCLStorage.Abstractions.NoSL.csproj", "{8F4C2E94-B8C5-477B-A315-CA58C70617E4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.WindowsPhone", "src\PCLStorage.WindowsPhone\PCLStorage.WindowsPhone.csproj", "{D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.Android", "src\PCLStorage.Android\PCLStorage.Android.csproj", "{D813C9D8-D6D1-4D2B-AF04-0D877656F47E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.Test.Android", "test\PCLStorage.Test.Android\PCLStorage.Test.Android.csproj", "{32922221-A523-4673-9C77-DE6B01C91F3D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.iOS", "src\PCLStorage.iOS\PCLStorage.iOS.csproj", "{27A782B4-6683-4849-B951-601289C23F73}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{A5AE3457-DDFF-432A-90D6-8462B560603C}" + ProjectSection(SolutionItems) = preProject + build\build.proj = build\build.proj + common\CommonAssemblyInfo.cs = common\CommonAssemblyInfo.cs + common\PCLStorage.nuspec = common\PCLStorage.nuspec + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.iOS-Unified", "src\PCLStorage.iOS-Unified\PCLStorage.iOS-Unified.csproj", "{3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "fsdfsfd", "fsdfsfd", "{C68BF2D5-548D-4318-9831-0B30646ACF15}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {28668411-C26F-434F-88B1-B7E5F8D39C61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {28668411-C26F-434F-88B1-B7E5F8D39C61}.Debug|Any CPU.Build.0 = Debug|Any CPU + {28668411-C26F-434F-88B1-B7E5F8D39C61}.Debug|ARM.ActiveCfg = Debug|Any CPU + {28668411-C26F-434F-88B1-B7E5F8D39C61}.Debug|x64.ActiveCfg = Debug|Any CPU + {28668411-C26F-434F-88B1-B7E5F8D39C61}.Debug|x86.ActiveCfg = Debug|Any CPU + {28668411-C26F-434F-88B1-B7E5F8D39C61}.Release|Any CPU.ActiveCfg = Release|Any CPU + {28668411-C26F-434F-88B1-B7E5F8D39C61}.Release|Any CPU.Build.0 = Release|Any CPU + {28668411-C26F-434F-88B1-B7E5F8D39C61}.Release|ARM.ActiveCfg = Release|Any CPU + {28668411-C26F-434F-88B1-B7E5F8D39C61}.Release|x64.ActiveCfg = Release|Any CPU + {28668411-C26F-434F-88B1-B7E5F8D39C61}.Release|x86.ActiveCfg = Release|Any CPU + {5568B9DA-132A-4031-9457-01C003FA5CB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5568B9DA-132A-4031-9457-01C003FA5CB4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5568B9DA-132A-4031-9457-01C003FA5CB4}.Debug|ARM.ActiveCfg = Debug|Any CPU + {5568B9DA-132A-4031-9457-01C003FA5CB4}.Debug|x64.ActiveCfg = Debug|Any CPU + {5568B9DA-132A-4031-9457-01C003FA5CB4}.Debug|x86.ActiveCfg = Debug|Any CPU + {5568B9DA-132A-4031-9457-01C003FA5CB4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5568B9DA-132A-4031-9457-01C003FA5CB4}.Release|Any CPU.Build.0 = Release|Any CPU + {5568B9DA-132A-4031-9457-01C003FA5CB4}.Release|ARM.ActiveCfg = Release|Any CPU + {5568B9DA-132A-4031-9457-01C003FA5CB4}.Release|x64.ActiveCfg = Release|Any CPU + {5568B9DA-132A-4031-9457-01C003FA5CB4}.Release|x86.ActiveCfg = Release|Any CPU + {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Debug|ARM.ActiveCfg = Debug|Any CPU + {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Debug|x64.ActiveCfg = Debug|Any CPU + {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Debug|x86.ActiveCfg = Debug|Any CPU + {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Release|Any CPU.Build.0 = Release|Any CPU + {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Release|Any CPU.Deploy.0 = Release|Any CPU + {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Release|ARM.ActiveCfg = Release|Any CPU + {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Release|x64.ActiveCfg = Release|Any CPU + {A49660EE-789F-4EFF-A946-10532D3EA7E6}.Release|x86.ActiveCfg = Release|Any CPU + {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}.Debug|Any CPU.Build.0 = Debug|Any CPU + {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}.Debug|ARM.ActiveCfg = Debug|Any CPU + {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}.Debug|x64.ActiveCfg = Debug|Any CPU + {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}.Debug|x86.ActiveCfg = Debug|Any CPU + {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}.Release|Any CPU.ActiveCfg = Release|Any CPU + {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}.Release|Any CPU.Build.0 = Release|Any CPU + {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}.Release|ARM.ActiveCfg = Release|Any CPU + {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}.Release|x64.ActiveCfg = Release|Any CPU + {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66}.Release|x86.ActiveCfg = Release|Any CPU + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|Any CPU.Build.0 = Debug|Any CPU + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|ARM.ActiveCfg = Debug|ARM + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|ARM.Build.0 = Debug|ARM + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|ARM.Deploy.0 = Debug|ARM + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|x64.ActiveCfg = Debug|x64 + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|x64.Build.0 = Debug|x64 + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|x64.Deploy.0 = Debug|x64 + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|x86.ActiveCfg = Debug|x86 + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|x86.Build.0 = Debug|x86 + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Debug|x86.Deploy.0 = Debug|x86 + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|Any CPU.ActiveCfg = Release|Any CPU + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|Any CPU.Build.0 = Release|Any CPU + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|Any CPU.Deploy.0 = Release|Any CPU + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|ARM.ActiveCfg = Release|ARM + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|ARM.Build.0 = Release|ARM + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|ARM.Deploy.0 = Release|ARM + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|x64.ActiveCfg = Release|x64 + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|x64.Build.0 = Release|x64 + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|x64.Deploy.0 = Release|x64 + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|x86.ActiveCfg = Release|x86 + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|x86.Build.0 = Release|x86 + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812}.Release|x86.Deploy.0 = Release|x86 + {31F6B895-4FF7-481B-B483-E0E6B63CC312}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {31F6B895-4FF7-481B-B483-E0E6B63CC312}.Debug|Any CPU.Build.0 = Debug|Any CPU + {31F6B895-4FF7-481B-B483-E0E6B63CC312}.Debug|ARM.ActiveCfg = Debug|Any CPU + {31F6B895-4FF7-481B-B483-E0E6B63CC312}.Debug|x64.ActiveCfg = Debug|Any CPU + {31F6B895-4FF7-481B-B483-E0E6B63CC312}.Debug|x86.ActiveCfg = Debug|Any CPU + {31F6B895-4FF7-481B-B483-E0E6B63CC312}.Release|Any CPU.ActiveCfg = Release|Any CPU + {31F6B895-4FF7-481B-B483-E0E6B63CC312}.Release|Any CPU.Build.0 = Release|Any CPU + {31F6B895-4FF7-481B-B483-E0E6B63CC312}.Release|ARM.ActiveCfg = Release|Any CPU + {31F6B895-4FF7-481B-B483-E0E6B63CC312}.Release|x64.ActiveCfg = Release|Any CPU + {31F6B895-4FF7-481B-B483-E0E6B63CC312}.Release|x86.ActiveCfg = Release|Any CPU + {F878EC6F-6C59-4860-A2D1-0CD2C97760A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F878EC6F-6C59-4860-A2D1-0CD2C97760A7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F878EC6F-6C59-4860-A2D1-0CD2C97760A7}.Debug|ARM.ActiveCfg = Debug|Any CPU + {F878EC6F-6C59-4860-A2D1-0CD2C97760A7}.Debug|x64.ActiveCfg = Debug|Any CPU + {F878EC6F-6C59-4860-A2D1-0CD2C97760A7}.Debug|x86.ActiveCfg = Debug|Any CPU + {F878EC6F-6C59-4860-A2D1-0CD2C97760A7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F878EC6F-6C59-4860-A2D1-0CD2C97760A7}.Release|Any CPU.Build.0 = Release|Any CPU + {F878EC6F-6C59-4860-A2D1-0CD2C97760A7}.Release|ARM.ActiveCfg = Release|Any CPU + {F878EC6F-6C59-4860-A2D1-0CD2C97760A7}.Release|x64.ActiveCfg = Release|Any CPU + {F878EC6F-6C59-4860-A2D1-0CD2C97760A7}.Release|x86.ActiveCfg = Release|Any CPU + {9D3F208D-8BB4-47A9-8323-4CFD24314341}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9D3F208D-8BB4-47A9-8323-4CFD24314341}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9D3F208D-8BB4-47A9-8323-4CFD24314341}.Debug|ARM.ActiveCfg = Debug|Any CPU + {9D3F208D-8BB4-47A9-8323-4CFD24314341}.Debug|x64.ActiveCfg = Debug|Any CPU + {9D3F208D-8BB4-47A9-8323-4CFD24314341}.Debug|x86.ActiveCfg = Debug|Any CPU + {9D3F208D-8BB4-47A9-8323-4CFD24314341}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9D3F208D-8BB4-47A9-8323-4CFD24314341}.Release|Any CPU.Build.0 = Release|Any CPU + {9D3F208D-8BB4-47A9-8323-4CFD24314341}.Release|ARM.ActiveCfg = Release|Any CPU + {9D3F208D-8BB4-47A9-8323-4CFD24314341}.Release|x64.ActiveCfg = Release|Any CPU + {9D3F208D-8BB4-47A9-8323-4CFD24314341}.Release|x86.ActiveCfg = Release|Any CPU + {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}.Debug|ARM.ActiveCfg = Debug|Any CPU + {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}.Debug|x64.ActiveCfg = Debug|Any CPU + {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}.Debug|x86.ActiveCfg = Debug|Any CPU + {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}.Release|Any CPU.Build.0 = Release|Any CPU + {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}.Release|ARM.ActiveCfg = Release|Any CPU + {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}.Release|x64.ActiveCfg = Release|Any CPU + {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC}.Release|x86.ActiveCfg = Release|Any CPU + {AAC0913D-649A-49DD-834B-EF23D092D72B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AAC0913D-649A-49DD-834B-EF23D092D72B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AAC0913D-649A-49DD-834B-EF23D092D72B}.Debug|ARM.ActiveCfg = Debug|ARM + {AAC0913D-649A-49DD-834B-EF23D092D72B}.Debug|ARM.Build.0 = Debug|ARM + {AAC0913D-649A-49DD-834B-EF23D092D72B}.Debug|x64.ActiveCfg = Debug|x64 + {AAC0913D-649A-49DD-834B-EF23D092D72B}.Debug|x64.Build.0 = Debug|x64 + {AAC0913D-649A-49DD-834B-EF23D092D72B}.Debug|x86.ActiveCfg = Debug|x86 + {AAC0913D-649A-49DD-834B-EF23D092D72B}.Debug|x86.Build.0 = Debug|x86 + {AAC0913D-649A-49DD-834B-EF23D092D72B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AAC0913D-649A-49DD-834B-EF23D092D72B}.Release|Any CPU.Build.0 = Release|Any CPU + {AAC0913D-649A-49DD-834B-EF23D092D72B}.Release|ARM.ActiveCfg = Release|ARM + {AAC0913D-649A-49DD-834B-EF23D092D72B}.Release|ARM.Build.0 = Release|ARM + {AAC0913D-649A-49DD-834B-EF23D092D72B}.Release|x64.ActiveCfg = Release|x64 + {AAC0913D-649A-49DD-834B-EF23D092D72B}.Release|x64.Build.0 = Release|x64 + {AAC0913D-649A-49DD-834B-EF23D092D72B}.Release|x86.ActiveCfg = Release|x86 + {AAC0913D-649A-49DD-834B-EF23D092D72B}.Release|x86.Build.0 = Release|x86 + {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}.Debug|ARM.ActiveCfg = Debug|Any CPU + {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}.Debug|x64.ActiveCfg = Debug|Any CPU + {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}.Debug|x86.ActiveCfg = Debug|Any CPU + {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}.Release|Any CPU.Build.0 = Release|Any CPU + {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}.Release|ARM.ActiveCfg = Release|Any CPU + {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}.Release|x64.ActiveCfg = Release|Any CPU + {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72}.Release|x86.ActiveCfg = Release|Any CPU + {8F4C2E94-B8C5-477B-A315-CA58C70617E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8F4C2E94-B8C5-477B-A315-CA58C70617E4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8F4C2E94-B8C5-477B-A315-CA58C70617E4}.Debug|ARM.ActiveCfg = Debug|Any CPU + {8F4C2E94-B8C5-477B-A315-CA58C70617E4}.Debug|x64.ActiveCfg = Debug|Any CPU + {8F4C2E94-B8C5-477B-A315-CA58C70617E4}.Debug|x86.ActiveCfg = Debug|Any CPU + {8F4C2E94-B8C5-477B-A315-CA58C70617E4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8F4C2E94-B8C5-477B-A315-CA58C70617E4}.Release|Any CPU.Build.0 = Release|Any CPU + {8F4C2E94-B8C5-477B-A315-CA58C70617E4}.Release|ARM.ActiveCfg = Release|Any CPU + {8F4C2E94-B8C5-477B-A315-CA58C70617E4}.Release|x64.ActiveCfg = Release|Any CPU + {8F4C2E94-B8C5-477B-A315-CA58C70617E4}.Release|x86.ActiveCfg = Release|Any CPU + {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Debug|ARM.ActiveCfg = Debug|ARM + {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Debug|ARM.Build.0 = Debug|ARM + {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Debug|x64.ActiveCfg = Debug|Any CPU + {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Debug|x86.ActiveCfg = Debug|x86 + {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Debug|x86.Build.0 = Debug|x86 + {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Release|Any CPU.Build.0 = Release|Any CPU + {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Release|ARM.ActiveCfg = Release|ARM + {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Release|ARM.Build.0 = Release|ARM + {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Release|x64.ActiveCfg = Release|Any CPU + {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Release|x86.ActiveCfg = Release|x86 + {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA}.Release|x86.Build.0 = Release|x86 + {D813C9D8-D6D1-4D2B-AF04-0D877656F47E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D813C9D8-D6D1-4D2B-AF04-0D877656F47E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D813C9D8-D6D1-4D2B-AF04-0D877656F47E}.Debug|ARM.ActiveCfg = Debug|Any CPU + {D813C9D8-D6D1-4D2B-AF04-0D877656F47E}.Debug|x64.ActiveCfg = Debug|Any CPU + {D813C9D8-D6D1-4D2B-AF04-0D877656F47E}.Debug|x86.ActiveCfg = Debug|Any CPU + {D813C9D8-D6D1-4D2B-AF04-0D877656F47E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D813C9D8-D6D1-4D2B-AF04-0D877656F47E}.Release|Any CPU.Build.0 = Release|Any CPU + {D813C9D8-D6D1-4D2B-AF04-0D877656F47E}.Release|ARM.ActiveCfg = Release|Any CPU + {D813C9D8-D6D1-4D2B-AF04-0D877656F47E}.Release|x64.ActiveCfg = Release|Any CPU + {D813C9D8-D6D1-4D2B-AF04-0D877656F47E}.Release|x86.ActiveCfg = Release|Any CPU + {32922221-A523-4673-9C77-DE6B01C91F3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {32922221-A523-4673-9C77-DE6B01C91F3D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {32922221-A523-4673-9C77-DE6B01C91F3D}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {32922221-A523-4673-9C77-DE6B01C91F3D}.Debug|ARM.ActiveCfg = Debug|Any CPU + {32922221-A523-4673-9C77-DE6B01C91F3D}.Debug|x64.ActiveCfg = Debug|Any CPU + {32922221-A523-4673-9C77-DE6B01C91F3D}.Debug|x86.ActiveCfg = Debug|Any CPU + {32922221-A523-4673-9C77-DE6B01C91F3D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {32922221-A523-4673-9C77-DE6B01C91F3D}.Release|Any CPU.Build.0 = Release|Any CPU + {32922221-A523-4673-9C77-DE6B01C91F3D}.Release|Any CPU.Deploy.0 = Release|Any CPU + {32922221-A523-4673-9C77-DE6B01C91F3D}.Release|ARM.ActiveCfg = Release|Any CPU + {32922221-A523-4673-9C77-DE6B01C91F3D}.Release|x64.ActiveCfg = Release|Any CPU + {32922221-A523-4673-9C77-DE6B01C91F3D}.Release|x86.ActiveCfg = Release|Any CPU + {27A782B4-6683-4849-B951-601289C23F73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {27A782B4-6683-4849-B951-601289C23F73}.Debug|Any CPU.Build.0 = Debug|Any CPU + {27A782B4-6683-4849-B951-601289C23F73}.Debug|ARM.ActiveCfg = Debug|Any CPU + {27A782B4-6683-4849-B951-601289C23F73}.Debug|x64.ActiveCfg = Debug|Any CPU + {27A782B4-6683-4849-B951-601289C23F73}.Debug|x86.ActiveCfg = Debug|Any CPU + {27A782B4-6683-4849-B951-601289C23F73}.Release|Any CPU.ActiveCfg = Release|Any CPU + {27A782B4-6683-4849-B951-601289C23F73}.Release|Any CPU.Build.0 = Release|Any CPU + {27A782B4-6683-4849-B951-601289C23F73}.Release|ARM.ActiveCfg = Release|Any CPU + {27A782B4-6683-4849-B951-601289C23F73}.Release|x64.ActiveCfg = Release|Any CPU + {27A782B4-6683-4849-B951-601289C23F73}.Release|x86.ActiveCfg = Release|Any CPU + {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Debug|ARM.ActiveCfg = Debug|Any CPU + {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Debug|ARM.Build.0 = Debug|Any CPU + {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Debug|x64.ActiveCfg = Debug|Any CPU + {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Debug|x64.Build.0 = Debug|Any CPU + {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Debug|x86.ActiveCfg = Debug|Any CPU + {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Debug|x86.Build.0 = Debug|Any CPU + {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Release|Any CPU.Build.0 = Release|Any CPU + {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Release|ARM.ActiveCfg = Release|Any CPU + {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Release|ARM.Build.0 = Release|Any CPU + {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Release|x64.ActiveCfg = Release|Any CPU + {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Release|x64.Build.0 = Release|Any CPU + {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Release|x86.ActiveCfg = Release|Any CPU + {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {28668411-C26F-434F-88B1-B7E5F8D39C61} = {70760DD8-A408-4274-AAFE-0E06BC98DEDB} + {5568B9DA-132A-4031-9457-01C003FA5CB4} = {70760DD8-A408-4274-AAFE-0E06BC98DEDB} + {A49660EE-789F-4EFF-A946-10532D3EA7E6} = {70760DD8-A408-4274-AAFE-0E06BC98DEDB} + {13DFCDB2-D6D5-40FF-B8F2-2AE7970E3B66} = {70760DD8-A408-4274-AAFE-0E06BC98DEDB} + {220CC1AA-AEEC-4DF7-94E6-9BBF23486812} = {70760DD8-A408-4274-AAFE-0E06BC98DEDB} + {31F6B895-4FF7-481B-B483-E0E6B63CC312} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} + {F878EC6F-6C59-4860-A2D1-0CD2C97760A7} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} + {9D3F208D-8BB4-47A9-8323-4CFD24314341} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} + {793B3B5B-060E-47FD-8928-8EDF8AD0D6EC} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} + {AAC0913D-649A-49DD-834B-EF23D092D72B} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} + {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} + {8F4C2E94-B8C5-477B-A315-CA58C70617E4} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} + {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} + {D813C9D8-D6D1-4D2B-AF04-0D877656F47E} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} + {32922221-A523-4673-9C77-DE6B01C91F3D} = {70760DD8-A408-4274-AAFE-0E06BC98DEDB} + {27A782B4-6683-4849-B951-601289C23F73} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} + {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01} = {1E53EE83-AD17-4F75-A77D-B0A12961A232} + EndGlobalSection +EndGlobal diff --git a/build/build.proj b/build/build.proj index 4a35bea..306f5e6 100644 --- a/build/build.proj +++ b/build/build.proj @@ -11,7 +11,7 @@ 1 0 - 4 + 5 0 diff --git a/common/CommonAssemblyInfo.cs b/common/CommonAssemblyInfo.cs index 89849d2..49e5280 100644 --- a/common/CommonAssemblyInfo.cs +++ b/common/CommonAssemblyInfo.cs @@ -26,5 +26,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.4.0")] -[assembly: AssemblyFileVersion("1.0.4.0")] +[assembly: AssemblyVersion("1.0.5.0")] +[assembly: AssemblyFileVersion("1.0.5.0")] diff --git a/src/PCLStorage.Abstractions/IFile.cs b/src/PCLStorage.Abstractions/IFile.cs index b706faf..0b7d606 100644 --- a/src/PCLStorage.Abstractions/IFile.cs +++ b/src/PCLStorage.Abstractions/IFile.cs @@ -63,15 +63,24 @@ public interface IFile /// /// A task which will complete after the file is renamed. /// - Task RenameAsync(string newName, NameCollisionOption collisionOption = NameCollisionOption.FailIfExists, CancellationToken cancellationToken = default(CancellationToken)); - - /// - /// Moves a file. - /// - /// The new full path of the file. - /// How to deal with collisions with existing files. - /// The cancellation token. - /// A task which will complete after the file is moved. - Task MoveAsync(string newPath, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)); + Task RenameAsync(string newName, NameCollisionOption collisionOption = NameCollisionOption.FailIfExists, CancellationToken cancellationToken = default(CancellationToken)); + + /// + /// Moves a file. + /// + /// The new full path of the file. + /// How to deal with collisions with existing files. + /// The cancellation token. + /// A task which will complete after the file is moved. + Task MoveAsync(string newPath, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)); + + /// + /// Extract a zip file. + /// + /// The destination folder for zip file extraction + /// How to deal with collisions with existing files. + /// The cancellation token. + /// A task which will complete after the file is moved. + Task> ExtractZip(string desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)); } } diff --git a/src/PCLStorage.Abstractions/PCLStorage.Abstractions.csproj b/src/PCLStorage.Abstractions/PCLStorage.Abstractions.csproj index a1e09ac..de475b0 100644 --- a/src/PCLStorage.Abstractions/PCLStorage.Abstractions.csproj +++ b/src/PCLStorage.Abstractions/PCLStorage.Abstractions.csproj @@ -1,90 +1,90 @@ - - - - - 10.0 - Debug - AnyCPU - {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72} - Library - Properties - PCLStorage - PCLStorage.Abstractions - v4.0 - Profile158 - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - ..\..\ - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - bin\Debug\PCLStorage.Abstractions.XML - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\PCLStorage.Abstractions.XML - - - true - - - ..\..\common\strongnamekey.snk - - - - Properties\CommonAssemblyInfo.cs - - - - - - - - - - - - - - - ..\..\packages\Microsoft.Bcl.Async.1.0.165\lib\portable-net40+sl4+win8+wp71\Microsoft.Threading.Tasks.dll - - - ..\..\packages\Microsoft.Bcl.Async.1.0.165\lib\portable-net40+sl4+win8+wp71\Microsoft.Threading.Tasks.Extensions.dll - - - ..\..\packages\Microsoft.Bcl.1.1.6\lib\portable-net40+sl5+win8+wp8\System.IO.dll - - - ..\..\packages\Microsoft.Bcl.1.1.6\lib\portable-net40+sl5+win8+wp8\System.Runtime.dll - - - ..\..\packages\Microsoft.Bcl.1.1.6\lib\portable-net40+sl5+win8+wp8\System.Threading.Tasks.dll - - - - - - - - + + + + + 10.0 + Debug + AnyCPU + {EEBB53F3-EBDF-4DD0-82E5-FF9A2C8DBD72} + Library + Properties + PCLStorage + PCLStorage.Abstractions + v4.0 + Profile158 + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + bin\Debug\PCLStorage.Abstractions.XML + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + bin\Release\PCLStorage.Abstractions.XML + + + true + + + ..\..\common\strongnamekey.snk + + + + Properties\CommonAssemblyInfo.cs + + + + + + + + + + + + + + + ..\..\packages\Microsoft.Bcl.Async.1.0.165\lib\portable-net40+sl4+win8+wp71\Microsoft.Threading.Tasks.dll + + + ..\..\packages\Microsoft.Bcl.Async.1.0.165\lib\portable-net40+sl4+win8+wp71\Microsoft.Threading.Tasks.Extensions.dll + + + ..\..\packages\Microsoft.Bcl.1.1.6\lib\portable-net40+sl5+win8+wp8\System.IO.dll + + + ..\..\packages\Microsoft.Bcl.1.1.6\lib\portable-net40+sl5+win8+wp8\System.Runtime.dll + + + ..\..\packages\Microsoft.Bcl.1.1.6\lib\portable-net40+sl5+win8+wp8\System.Threading.Tasks.dll + + + + + + + + + --> \ No newline at end of file diff --git a/src/PCLStorage.Android/PCLStorage.Android.csproj b/src/PCLStorage.Android/PCLStorage.Android.csproj index ed7cccc..5a747a5 100644 --- a/src/PCLStorage.Android/PCLStorage.Android.csproj +++ b/src/PCLStorage.Android/PCLStorage.Android.csproj @@ -72,6 +72,9 @@ Requires.cs + + ZipStorer.cs + diff --git a/src/PCLStorage.FileSystem.Desktop/DesktopFileSystem.cs b/src/PCLStorage.FileSystem.Desktop/DesktopFileSystem.cs index 76dd989..03d1fd7 100644 --- a/src/PCLStorage.FileSystem.Desktop/DesktopFileSystem.cs +++ b/src/PCLStorage.FileSystem.Desktop/DesktopFileSystem.cs @@ -97,7 +97,10 @@ public async Task GetFolderFromPathAsync(string path, CancellationToken /// The path to a file, as returned from the property. /// The cancellation token. /// A file for the given path, or null if it does not exist. - public abstract Task GetFileFromAppBundleAsync(string path, CancellationToken cancellationToken); - + //public partial Task GetFileFromAppBundleAsync(string path, CancellationToken cancellationToken); + public Task GetFileFromAppBundleAsync(string path, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } } } diff --git a/src/PCLStorage.FileSystem.Desktop/FileSystemFile.cs b/src/PCLStorage.FileSystem.Desktop/FileSystemFile.cs index 720316e..6e64563 100644 --- a/src/PCLStorage.FileSystem.Desktop/FileSystemFile.cs +++ b/src/PCLStorage.FileSystem.Desktop/FileSystemFile.cs @@ -1,11 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Text; +using System.Threading; using System.Threading.Tasks; namespace PCLStorage @@ -154,6 +155,54 @@ public async Task MoveAsync(string newPath, NameCollisionOption collisionOption, _name = candidateName; return; } - } + } + + + /// + /// Extract a zip file. + /// + /// The destination folder for zip file extraction + /// How to deal with collisions with existing files. + /// The cancellation token. + /// A task with a List of strings containing the names of extracted files from the zip archive. + public async Task> ExtractZip(string desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) + { + var extractedFilenames = new List(); + await Task.Factory.StartNew(() => + { + ZipStorer zip = ZipStorer.Open(_path, System.IO.FileAccess.Read); + //// Read all directory contents + List dir = zip.ReadCentralDir(); + //// Extract all files in target directory + foreach (ZipStorer.ZipFileEntry entry in dir) + { + bool result = false; + extractedFilenames.Add(entry.FilenameInZip); + var path = System.IO.Path.Combine(desinationFolder, System.IO.Path.GetFileName(entry.FilenameInZip)); + if (System.IO.File.Exists(path)) + { + if (collisionOption == NameCollisionOption.ReplaceExisting) + { + System.IO.File.Delete(path); + result = zip.ExtractFile(entry, path); + } + } + else + { + result = zip.ExtractFile(entry, path); + } + if (result) + { + extractedFilenames.Add(System.IO.Path.GetFileName(entry.FilenameInZip)); + } + if (cancellationToken.IsCancellationRequested) + { + break; + } + } + zip.Close(); + }, cancellationToken); + return extractedFilenames; + } } } diff --git a/src/PCLStorage.FileSystem.Desktop/PCLStorage.FileSystem.Desktop.csproj b/src/PCLStorage.FileSystem.Desktop/PCLStorage.FileSystem.Desktop.csproj index e5186db..755070b 100644 --- a/src/PCLStorage.FileSystem.Desktop/PCLStorage.FileSystem.Desktop.csproj +++ b/src/PCLStorage.FileSystem.Desktop/PCLStorage.FileSystem.Desktop.csproj @@ -1,93 +1,96 @@ - - - - - Debug - AnyCPU - {9D3F208D-8BB4-47A9-8323-4CFD24314341} - Library - Properties - PCLStorage - PCLStorage - v4.5 - 512 - - ..\..\ - true - - - true - full - false - bin\Debug\ - FILE_SYSTEM;DEBUG;TRACE - prompt - 4 - false - bin\Debug\PCLStorage.XML - - - pdbonly - true - bin\Release\ - FILE_SYSTEM;TRACE - prompt - 4 - false - bin\Release\PCLStorage.XML - - - true - - - ..\..\common\strongnamekey.snk - - - - - - - - - - - - - - Properties\CommonAssemblyInfo.cs - - - AwaitExtensions.cs - - - Exceptions\PCLStorageExceptions.cs - - - FileSystem.cs - - - PortablePath.cs - - - Requires.cs - - - - - - - - - {8f4c2e94-b8c5-477b-a315-ca58c70617e4} - PCLStorage.Abstractions.NoSL - - - + + + + + Debug + AnyCPU + {9D3F208D-8BB4-47A9-8323-4CFD24314341} + Library + Properties + PCLStorage + PCLStorage + v4.5 + 512 + + ..\..\ + true + + + true + full + false + bin\Debug\ + FILE_SYSTEM;DEBUG;TRACE + prompt + 4 + false + bin\Debug\PCLStorage.XML + + + pdbonly + true + bin\Release\ + FILE_SYSTEM;TRACE + prompt + 4 + false + bin\Release\PCLStorage.XML + + + true + + + ..\..\common\strongnamekey.snk + + + + + + + + + + + + + + Properties\CommonAssemblyInfo.cs + + + AwaitExtensions.cs + + + Exceptions\PCLStorageExceptions.cs + + + FileSystem.cs + + + PortablePath.cs + + + Requires.cs + + + ZipStorer.cs + + + + + + + + + {8f4c2e94-b8c5-477b-a315-ca58c70617e4} + PCLStorage.Abstractions.NoSL + + + + --> \ No newline at end of file diff --git a/src/PCLStorage.IsoStore.SL/IsoStoreFile.cs b/src/PCLStorage.IsoStore.SL/IsoStoreFile.cs index 9b3d814..8a58acb 100644 --- a/src/PCLStorage.IsoStore.SL/IsoStoreFile.cs +++ b/src/PCLStorage.IsoStore.SL/IsoStoreFile.cs @@ -233,6 +233,12 @@ public async Task MoveAsync(string newPath, NameCollisionOption collisionOption, _name = candidateName; return; } - } + } + + + public Task> ExtractZip(string desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) + { + throw new NotImplementedException(); + } } } diff --git a/src/PCLStorage.WinRT/WinRTFile.cs b/src/PCLStorage.WinRT/WinRTFile.cs index e93ff9a..8e53c8b 100644 --- a/src/PCLStorage.WinRT/WinRTFile.cs +++ b/src/PCLStorage.WinRT/WinRTFile.cs @@ -1,11 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; using Windows.Storage; namespace PCLStorage @@ -141,6 +142,43 @@ public async Task MoveAsync(string newPath, NameCollisionOption collisionOption, throw; } - } + } + + public async Task> ExtractZip(string desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) + { + var zipFiles = new List(); + var zipDataStream = await _wrappedFile.OpenReadAsync();// ReadFileFromDiskAsStream(ZipFilepath); + if (zipDataStream == null) return null; + try + { + ZipArchive zipArchive = new ZipArchive(zipDataStream.AsStream()); + foreach (var zipArchiveEntry in zipArchive.Entries) + { + var zipData = zipArchiveEntry.Open(); + if (zipData == null) + { + JK.JKTools.JKLog("JK#156# zipData == null speichern nicht möglich, " + ZipFilepath + ", " + ZipTargetFolder); + } + else + { + if (zipArchiveEntry.Name == null || zipArchiveEntry.Name.Length == 0) + { + JK.JKTools.JKLog("JK#157# kein gültiger Name für " + zipArchiveEntry.FullName + ", " + ZipFilepath + ", " + ZipTargetFolder); + } + else + { + await WriteFileToDisk(zipData, zipArchiveEntry.Name); + zipFiles.Add(zipArchiveEntry.Name); + } + } + } + + } + catch (Exception e) + { + JK.JKTools.JKLog("JK#91# ZipDecompress " + e.Message); + } + return zipFiles; + } } } diff --git a/src/PCLStorage.WindowsPhone/PCLStorage.WindowsPhone.csproj b/src/PCLStorage.WindowsPhone/PCLStorage.WindowsPhone.csproj index 30eb2b8..aac5baf 100644 --- a/src/PCLStorage.WindowsPhone/PCLStorage.WindowsPhone.csproj +++ b/src/PCLStorage.WindowsPhone/PCLStorage.WindowsPhone.csproj @@ -1,153 +1,153 @@ - - - - Debug - AnyCPU - 10.0.20506 - 2.0 - {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA} - {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - PCLStorage - PCLStorage - v8.0 - - - - - WindowsPhone - false - true - true - ..\ - true - 11.0 - true - ..\..\common\strongnamekey.snk - - - true - full - false - Bin\Debug - DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE - true - true - prompt - 4 - Bin\Debug\PCLStorage.XML - false - - - pdbonly - true - Bin\Release - TRACE;SILVERLIGHT;WINDOWS_PHONE - true - true - prompt - 4 - Bin\Release\PCLStorage.XML - false - - - true - Bin\x86\Debug - DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE - Bin\Debug\PCLStorage.XML - true - full - - - prompt - MinimumRecommendedRules.ruleset - false - - - Bin\x86\Release - TRACE;SILVERLIGHT;WINDOWS_PHONE - Bin\Release\PCLStorage.XML - true - true - pdbonly - - - prompt - MinimumRecommendedRules.ruleset - - - true - Bin\ARM\Debug - DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE - Bin\Debug\PCLStorage.XML - true - full - - - prompt - MinimumRecommendedRules.ruleset - false - - - Bin\ARM\Release - TRACE;SILVERLIGHT;WINDOWS_PHONE - Bin\Release\PCLStorage.XML - true - true - pdbonly - - - prompt - MinimumRecommendedRules.ruleset - - - - Properties\CommonAssemblyInfo.cs - - - AwaitExtensions.WinRT.cs - - - WinRTFile.cs - - - WinRTFileSystem.cs - - - WinRTFolder.cs - - - AwaitExtensions.cs - - - Exceptions\PCLStorageExceptions.cs - - - FileSystem.cs - - - PortablePath.cs - - - Requires.cs - - - - - - {8F4C2E94-B8C5-477B-A315-CA58C70617E4} - PCLStorage.Abstractions.NoSL - - - - - + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {D6BDB17D-1B42-49DA-BADB-B09D7DB4B4EA} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + PCLStorage + PCLStorage + v8.0 + + + + + WindowsPhone + false + true + true + ..\ + true + 11.0 + true + ..\..\common\strongnamekey.snk + + + true + full + false + Bin\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + Bin\Debug\PCLStorage.XML + false + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + Bin\Release\PCLStorage.XML + false + + + true + Bin\x86\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + Bin\Debug\PCLStorage.XML + true + full + + + prompt + MinimumRecommendedRules.ruleset + false + + + Bin\x86\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + Bin\Release\PCLStorage.XML + true + true + pdbonly + + + prompt + MinimumRecommendedRules.ruleset + + + true + Bin\ARM\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + Bin\Debug\PCLStorage.XML + true + full + + + prompt + MinimumRecommendedRules.ruleset + false + + + Bin\ARM\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + Bin\Release\PCLStorage.XML + true + true + pdbonly + + + prompt + MinimumRecommendedRules.ruleset + + + + Properties\CommonAssemblyInfo.cs + + + AwaitExtensions.WinRT.cs + + + WinRTFile.cs + + + WinRTFileSystem.cs + + + WinRTFolder.cs + + + AwaitExtensions.cs + + + Exceptions\PCLStorageExceptions.cs + + + FileSystem.cs + + + PortablePath.cs + + + Requires.cs + + + + + + {8F4C2E94-B8C5-477B-A315-CA58C70617E4} + PCLStorage.Abstractions.NoSL + + + + + + --> \ No newline at end of file diff --git a/src/PCLStorage.iOS-Unified/PCLStorage.iOS-Unified.csproj b/src/PCLStorage.iOS-Unified/PCLStorage.iOS-Unified.csproj index c1f0f0f..07ab1d5 100644 --- a/src/PCLStorage.iOS-Unified/PCLStorage.iOS-Unified.csproj +++ b/src/PCLStorage.iOS-Unified/PCLStorage.iOS-Unified.csproj @@ -1,83 +1,86 @@ - - - - Debug - iPhoneSimulator - 8.0.30703 - 2.0 - {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01} - {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Library - PCLStorage - Resources - PCLStorage - - - true - full - false - bin\iPhone\Debug - DEBUG;__UNIFIED__;__MOBILE__;__IOS__;IOS;XAMARIN;FILE_SYSTEM - prompt - 4 - false - true - iPhone Developer - - - pdbonly - true - bin\iPhone\Release - prompt - 4 - false - iPhone Developer - __UNIFIED__;__MOBILE__;__IOS__;IOS;XAMARIN;FILE_SYSTEM - true - bin\iPhone\Release\PCLStorage.XML - - - - - - - - - - - Properties\CommonAssemblyInfo.cs - - - DesktopFileSystem.cs - - - FileSystemFile.cs - - - FileSystemFolder.cs - - - AwaitExtensions.cs - - - Exceptions\PCLStorageExceptions.cs - - - FileSystem.cs - - - PortablePath.cs - - - Requires.cs - - - - - - {8f4c2e94-b8c5-477b-a315-ca58c70617e4} - PCLStorage.Abstractions.NoSL - - - + + + + Debug + iPhoneSimulator + 8.0.30703 + 2.0 + {3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01} + {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + PCLStorage + Resources + PCLStorage + + + true + full + false + bin\iPhone\Debug + DEBUG;__UNIFIED__;__MOBILE__;__IOS__;IOS;XAMARIN;FILE_SYSTEM + prompt + 4 + false + true + iPhone Developer + + + pdbonly + true + bin\iPhone\Release + prompt + 4 + false + iPhone Developer + __UNIFIED__;__MOBILE__;__IOS__;IOS;XAMARIN;FILE_SYSTEM + true + bin\iPhone\Release\PCLStorage.XML + + + + + + + + + + + Properties\CommonAssemblyInfo.cs + + + DesktopFileSystem.cs + + + FileSystemFile.cs + + + FileSystemFolder.cs + + + AwaitExtensions.cs + + + Exceptions\PCLStorageExceptions.cs + + + FileSystem.cs + + + PortablePath.cs + + + Requires.cs + + + ZipStorer.cs + + + + + + {8f4c2e94-b8c5-477b-a315-ca58c70617e4} + PCLStorage.Abstractions.NoSL + + + \ No newline at end of file diff --git a/src/PCLStorage.iOS/PCLStorage.iOS.csproj b/src/PCLStorage.iOS/PCLStorage.iOS.csproj index 09097a0..8637ce9 100644 --- a/src/PCLStorage.iOS/PCLStorage.iOS.csproj +++ b/src/PCLStorage.iOS/PCLStorage.iOS.csproj @@ -64,6 +64,9 @@ Requires.cs + + ZipStorer.cs + diff --git a/src/Zip/ZipStorer.cs b/src/Zip/ZipStorer.cs new file mode 100644 index 0000000..b583629 --- /dev/null +++ b/src/Zip/ZipStorer.cs @@ -0,0 +1,773 @@ +// ZipStorer, by Jaime Olivares +// Website: zipstorer.codeplex.com +// Version: 2.35 (March 14, 2010) + +//141009 +//Internationalization west must be included + + +using System.Collections.Generic; +using System.Text; + +namespace System.IO.Compression +{ + /// + /// Unique class for compression/decompression file. Represents a Zip file. + /// + public class ZipStorer : IDisposable + { + /// + /// Compression method enumeration + /// + public enum Compression : ushort { + /// Uncompressed storage + Store = 0, + /// Deflate compression method + Deflate = 8 } + + /// + /// Represents an entry in Zip file directory + /// + public struct ZipFileEntry + { + /// Compression method + public Compression Method; + /// Full path and filename as stored in Zip + public string FilenameInZip; + /// Original file size + public uint FileSize; + /// Compressed file size + public uint CompressedSize; + /// Offset of header information inside Zip storage + public uint HeaderOffset; + /// Offset of file inside Zip storage + public uint FileOffset; + /// Size of header information + public uint HeaderSize; + /// 32-bit checksum of entire file + public uint Crc32; + /// Last modification time of file + public DateTime ModifyTime; + /// User comment for file + public string Comment; + /// True if UTF8 encoding for filename and comments, false if default (CP 437) + public bool EncodeUTF8; + + /// Overriden method + /// Filename in Zip + public override string ToString() + { + return this.FilenameInZip; + } + } + + #region Public fields + /// True if UTF8 encoding for filename and comments, false if default (CP 437) + public bool EncodeUTF8 = false; + /// Force deflate algotithm even if it inflates the stored file. Off by default. + public bool ForceDeflating = false; + #endregion + + #region Private fields + // List of files to store + private List Files = new List(); + // Filename of storage file + private string FileName; + // Stream object of storage file + private Stream ZipFileStream; + // General comment + private string Comment = ""; + // Central dir image + private byte[] CentralDirImage = null; + // Existing files in zip + private ushort ExistingFiles = 0; + // File access for Open method + private FileAccess Access; + // Static CRC32 Table + private static UInt32[] CrcTable = null; + // Default filename encoder + //private static Encoding DefaultEncoding = Encoding.GetEncoding(437); + private static Encoding _defaultEncoding = null; + private static Encoding DefaultEncoding + { + get + { + if (_defaultEncoding == null) + { + try + { + _defaultEncoding = Encoding.GetEncoding(437); + + } + finally + { + if (_defaultEncoding == null) + { + throw new NotSupportedException("JK#85# ZipStorer 'west' codeset missing. You need to include the 'west' encoding codeset in your internationalization settings ### Encoding.GetEncoding(437) ### http://stackoverflow.com/questions/20225175/zipstorer-not-creating-any-file-in-android-c-sharp/20298062#20298062"); + } + } + } + return _defaultEncoding; + } + } + + #endregion + + #region Public methods + // Static constructor. Just invoked once in order to create the CRC32 lookup table. + static ZipStorer() + { + // Generate CRC32 table + CrcTable = new UInt32[256]; + for (int i = 0; i < CrcTable.Length; i++) + { + UInt32 c = (UInt32)i; + for (int j = 0; j < 8; j++) + { + if ((c & 1) != 0) + c = 3988292384 ^ (c >> 1); + else + c >>= 1; + } + CrcTable[i] = c; + } + } + /// + /// Method to create a new storage file + /// + /// Full path of Zip file to create + /// General comment for Zip file + /// A valid ZipStorer object + public static ZipStorer Create(string _filename, string _comment) + { + Stream stream = new FileStream(_filename, FileMode.Create, FileAccess.ReadWrite); + + ZipStorer zip = Create(stream, _comment); + zip.Comment = _comment; + zip.FileName = _filename; + + return zip; + } + /// + /// Method to create a new zip storage in a stream + /// + /// + /// + /// A valid ZipStorer object + public static ZipStorer Create(Stream _stream, string _comment) + { + ZipStorer zip = new ZipStorer(); + zip.Comment = _comment; + zip.ZipFileStream = _stream; + zip.Access = FileAccess.Write; + + return zip; + } + /// + /// Method to open an existing storage file + /// + /// Full path of Zip file to open + /// File access mode as used in FileStream constructor + /// A valid ZipStorer object + public static ZipStorer Open(string _filename, FileAccess _access) + { + Stream stream = (Stream)new FileStream(_filename, FileMode.Open, _access == FileAccess.Read ? FileAccess.Read : FileAccess.ReadWrite); + + ZipStorer zip = Open(stream, _access); + zip.FileName = _filename; + + return zip; + } + /// + /// Method to open an existing storage from stream + /// + /// Already opened stream with zip contents + /// File access mode for stream operations + /// A valid ZipStorer object + public static ZipStorer Open(Stream _stream, FileAccess _access) + { + if (!_stream.CanSeek && _access != FileAccess.Read) + throw new InvalidOperationException("Stream cannot seek"); + + ZipStorer zip = new ZipStorer(); + //zip.FileName = _filename; + zip.ZipFileStream = _stream; + zip.Access = _access; + + if (zip.ReadFileInfo()) + return zip; + + throw new System.IO.InvalidDataException(); + } + /// + /// Add full contents of a file into the Zip storage + /// + /// Compression method + /// Full path of file to add to Zip storage + /// Filename and path as desired in Zip directory + /// Comment for stored file + public void AddFile(Compression _method, string _pathname, string _filenameInZip, string _comment) + { + if (Access == FileAccess.Read) + throw new InvalidOperationException("Writing is not alowed"); + + FileStream stream = new FileStream(_pathname, FileMode.Open, FileAccess.Read); + AddStream(_method, _filenameInZip, stream, File.GetLastWriteTime(_pathname), _comment); + stream.Close(); + } + /// + /// Add full contents of a stream into the Zip storage + /// + /// Compression method + /// Filename and path as desired in Zip directory + /// Stream object containing the data to store in Zip + /// Modification time of the data to store + /// Comment for stored file + public void AddStream(Compression _method, string _filenameInZip, Stream _source, DateTime _modTime, string _comment) + { + if (Access == FileAccess.Read) + throw new InvalidOperationException("Writing is not alowed"); + + long offset; + if (this.Files.Count==0) + offset = 0; + else + { + ZipFileEntry last = this.Files[this.Files.Count-1]; + offset = last.HeaderOffset + last.HeaderSize; + } + + // Prepare the fileinfo + ZipFileEntry zfe = new ZipFileEntry(); + zfe.Method = _method; + zfe.EncodeUTF8 = this.EncodeUTF8; + zfe.FilenameInZip = NormalizedFilename(_filenameInZip); + zfe.Comment = (_comment == null ? "" : _comment); + + // Even though we write the header now, it will have to be rewritten, since we don't know compressed size or crc. + zfe.Crc32 = 0; // to be updated later + zfe.HeaderOffset = (uint)this.ZipFileStream.Position; // offset within file of the start of this local record + zfe.ModifyTime = _modTime; + + // Write local header + WriteLocalHeader(ref zfe); + zfe.FileOffset = (uint)this.ZipFileStream.Position; + + // Write file to zip (store) + Store(ref zfe, _source); + _source.Close(); + + this.UpdateCrcAndSizes(ref zfe); + + Files.Add(zfe); + } + /// + /// Updates central directory (if pertinent) and close the Zip storage + /// + /// This is a required step, unless automatic dispose is used + public void Close() + { + if (this.Access != FileAccess.Read) + { + uint centralOffset = (uint)this.ZipFileStream.Position; + uint centralSize = 0; + + if (this.CentralDirImage != null) + this.ZipFileStream.Write(CentralDirImage, 0, CentralDirImage.Length); + + for (int i = 0; i < Files.Count; i++) + { + long pos = this.ZipFileStream.Position; + this.WriteCentralDirRecord(Files[i]); + centralSize += (uint)(this.ZipFileStream.Position - pos); + } + + if (this.CentralDirImage != null) + this.WriteEndRecord(centralSize + (uint)CentralDirImage.Length, centralOffset); + else + this.WriteEndRecord(centralSize, centralOffset); + } + + if (this.ZipFileStream != null) + { + this.ZipFileStream.Flush(); + this.ZipFileStream.Dispose(); + this.ZipFileStream = null; + } + } + /// + /// Read all the file records in the central directory + /// + /// List of all entries in directory + public List ReadCentralDir() + { + if (this.CentralDirImage == null) + throw new InvalidOperationException("Central directory currently does not exist"); + + List result = new List(); + + for (int pointer = 0; pointer < this.CentralDirImage.Length; ) + { + uint signature = BitConverter.ToUInt32(CentralDirImage, pointer); + if (signature != 0x02014b50) + break; + + bool encodeUTF8 = (BitConverter.ToUInt16(CentralDirImage, pointer + 8) & 0x0800) != 0; + ushort method = BitConverter.ToUInt16(CentralDirImage, pointer + 10); + uint modifyTime = BitConverter.ToUInt32(CentralDirImage, pointer + 12); + uint crc32 = BitConverter.ToUInt32(CentralDirImage, pointer + 16); + uint comprSize = BitConverter.ToUInt32(CentralDirImage, pointer + 20); + uint fileSize = BitConverter.ToUInt32(CentralDirImage, pointer + 24); + ushort filenameSize = BitConverter.ToUInt16(CentralDirImage, pointer + 28); + ushort extraSize = BitConverter.ToUInt16(CentralDirImage, pointer + 30); + ushort commentSize = BitConverter.ToUInt16(CentralDirImage, pointer + 32); + uint headerOffset = BitConverter.ToUInt32(CentralDirImage, pointer + 42); + uint headerSize = (uint)( 46 + filenameSize + extraSize + commentSize); + + Encoding encoder = encodeUTF8 ? Encoding.UTF8 : DefaultEncoding; + + ZipFileEntry zfe = new ZipFileEntry(); + zfe.Method = (Compression)method; + zfe.FilenameInZip = encoder.GetString(CentralDirImage, pointer + 46, filenameSize); + zfe.FileOffset = GetFileOffset(headerOffset); + zfe.FileSize = fileSize; + zfe.CompressedSize = comprSize; + zfe.HeaderOffset = headerOffset; + zfe.HeaderSize = headerSize; + zfe.Crc32 = crc32; + zfe.ModifyTime = DosTimeToDateTime(modifyTime); + if (commentSize > 0) + zfe.Comment = encoder.GetString(CentralDirImage, pointer + 46 + filenameSize + extraSize, commentSize); + + result.Add(zfe); + pointer += (46 + filenameSize + extraSize + commentSize); + } + + return result; + } + /// + /// Copy the contents of a stored file into a physical file + /// + /// Entry information of file to extract + /// Name of file to store uncompressed data + /// True if success, false if not. + /// Unique compression methods are Store and Deflate + public bool ExtractFile(ZipFileEntry _zfe, string _filename) + { + // Make sure the parent directory exist + string path = System.IO.Path.GetDirectoryName(_filename); + + if (!Directory.Exists(path)) + Directory.CreateDirectory(path); + // Check it is directory. If so, do nothing + if (Directory.Exists(_filename)) + return true; + + Stream output = new FileStream(_filename, FileMode.Create, FileAccess.Write); + bool result = ExtractFile(_zfe, output); + if (result) + output.Close(); + + File.SetCreationTime(_filename, _zfe.ModifyTime); + File.SetLastWriteTime(_filename, _zfe.ModifyTime); + + return result; + } + /// + /// Copy the contents of a stored file into an opened stream + /// + /// Entry information of file to extract + /// Stream to store the uncompressed data + /// True if success, false if not. + /// Unique compression methods are Store and Deflate + public bool ExtractFile(ZipFileEntry _zfe, Stream _stream) + { + if (!_stream.CanWrite) + throw new InvalidOperationException("Stream cannot be written"); + + // check signature + byte[] signature = new byte[4]; + this.ZipFileStream.Seek(_zfe.HeaderOffset, SeekOrigin.Begin); + this.ZipFileStream.Read(signature, 0, 4); + if (BitConverter.ToUInt32(signature, 0) != 0x04034b50) + return false; + + // Select input stream for inflating or just reading + Stream inStream; + if (_zfe.Method == Compression.Store) + inStream = this.ZipFileStream; + else if (_zfe.Method == Compression.Deflate) + inStream = new DeflateStream(this.ZipFileStream, CompressionMode.Decompress, true); + else + return false; + + // Buffered copy + byte[] buffer = new byte[16384]; + this.ZipFileStream.Seek(_zfe.FileOffset, SeekOrigin.Begin); + uint bytesPending = _zfe.FileSize; + while (bytesPending > 0) + { + int bytesRead = inStream.Read(buffer, 0, (int)Math.Min(bytesPending, buffer.Length)); + _stream.Write(buffer, 0, bytesRead); + bytesPending -= (uint)bytesRead; + } + _stream.Flush(); + + if (_zfe.Method == Compression.Deflate) + inStream.Dispose(); + return true; + } + /// + /// Removes one of many files in storage. It creates a new Zip file. + /// + /// Reference to the current Zip object + /// List of Entries to remove from storage + /// True if success, false if not + /// This method only works for storage of type FileStream + public static bool RemoveEntries(ref ZipStorer _zip, List _zfes) + { + if (!(_zip.ZipFileStream is FileStream)) + throw new InvalidOperationException("RemoveEntries is allowed just over streams of type FileStream"); + + + //Get full list of entries + List fullList = _zip.ReadCentralDir(); + + //In order to delete we need to create a copy of the zip file excluding the selected items + string tempZipName = Path.GetTempFileName(); + string tempEntryName = Path.GetTempFileName(); + + try + { + ZipStorer tempZip = ZipStorer.Create(tempZipName, string.Empty); + + foreach (ZipFileEntry zfe in fullList) + { + if (!_zfes.Contains(zfe)) + { + if (_zip.ExtractFile(zfe, tempEntryName)) + { + tempZip.AddFile(zfe.Method, tempEntryName, zfe.FilenameInZip, zfe.Comment); + } + } + } + _zip.Close(); + tempZip.Close(); + + File.Delete(_zip.FileName); + File.Move(tempZipName, _zip.FileName); + + _zip = ZipStorer.Open(_zip.FileName, _zip.Access); + } + catch + { + return false; + } + finally + { + if (File.Exists(tempZipName)) + File.Delete(tempZipName); + if (File.Exists(tempEntryName)) + File.Delete(tempEntryName); + } + return true; + } + #endregion + + #region Private methods + // Calculate the file offset by reading the corresponding local header + private uint GetFileOffset(uint _headerOffset) + { + byte[] buffer = new byte[2]; + + this.ZipFileStream.Seek(_headerOffset + 26, SeekOrigin.Begin); + this.ZipFileStream.Read(buffer, 0, 2); + ushort filenameSize = BitConverter.ToUInt16(buffer, 0); + this.ZipFileStream.Read(buffer, 0, 2); + ushort extraSize = BitConverter.ToUInt16(buffer, 0); + + return (uint)(30 + filenameSize + extraSize + _headerOffset); + } + /* Local file header: + local file header signature 4 bytes (0x04034b50) + version needed to extract 2 bytes + general purpose bit flag 2 bytes + compression method 2 bytes + last mod file time 2 bytes + last mod file date 2 bytes + crc-32 4 bytes + compressed size 4 bytes + uncompressed size 4 bytes + filename length 2 bytes + extra field length 2 bytes + + filename (variable size) + extra field (variable size) + */ + private void WriteLocalHeader(ref ZipFileEntry _zfe) + { + long pos = this.ZipFileStream.Position; + Encoding encoder = _zfe.EncodeUTF8 ? Encoding.UTF8 : DefaultEncoding; + byte[] encodedFilename = encoder.GetBytes(_zfe.FilenameInZip); + + this.ZipFileStream.Write(new byte[] { 80, 75, 3, 4, 20, 0}, 0, 6); // No extra header + this.ZipFileStream.Write(BitConverter.GetBytes((ushort)(_zfe.EncodeUTF8 ? 0x0800 : 0)), 0, 2); // filename and comment encoding + this.ZipFileStream.Write(BitConverter.GetBytes((ushort)_zfe.Method), 0, 2); // zipping method + this.ZipFileStream.Write(BitConverter.GetBytes(DateTimeToDosTime(_zfe.ModifyTime)), 0, 4); // zipping date and time + this.ZipFileStream.Write(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 12); // unused CRC, un/compressed size, updated later + this.ZipFileStream.Write(BitConverter.GetBytes((ushort)encodedFilename.Length), 0, 2); // filename length + this.ZipFileStream.Write(BitConverter.GetBytes((ushort)0), 0, 2); // extra length + + this.ZipFileStream.Write(encodedFilename, 0, encodedFilename.Length); + _zfe.HeaderSize = (uint)(this.ZipFileStream.Position - pos); + } + /* Central directory's File header: + central file header signature 4 bytes (0x02014b50) + version made by 2 bytes + version needed to extract 2 bytes + general purpose bit flag 2 bytes + compression method 2 bytes + last mod file time 2 bytes + last mod file date 2 bytes + crc-32 4 bytes + compressed size 4 bytes + uncompressed size 4 bytes + filename length 2 bytes + extra field length 2 bytes + file comment length 2 bytes + disk number start 2 bytes + internal file attributes 2 bytes + external file attributes 4 bytes + relative offset of local header 4 bytes + + filename (variable size) + extra field (variable size) + file comment (variable size) + */ + private void WriteCentralDirRecord(ZipFileEntry _zfe) + { + Encoding encoder = _zfe.EncodeUTF8 ? Encoding.UTF8 : DefaultEncoding; + byte[] encodedFilename = encoder.GetBytes(_zfe.FilenameInZip); + byte[] encodedComment = encoder.GetBytes(_zfe.Comment); + + this.ZipFileStream.Write(new byte[] { 80, 75, 1, 2, 23, 0xB, 20, 0 }, 0, 8); + this.ZipFileStream.Write(BitConverter.GetBytes((ushort)(_zfe.EncodeUTF8 ? 0x0800 : 0)), 0, 2); // filename and comment encoding + this.ZipFileStream.Write(BitConverter.GetBytes((ushort)_zfe.Method), 0, 2); // zipping method + this.ZipFileStream.Write(BitConverter.GetBytes(DateTimeToDosTime(_zfe.ModifyTime)), 0, 4); // zipping date and time + this.ZipFileStream.Write(BitConverter.GetBytes(_zfe.Crc32), 0, 4); // file CRC + this.ZipFileStream.Write(BitConverter.GetBytes(_zfe.CompressedSize), 0, 4); // compressed file size + this.ZipFileStream.Write(BitConverter.GetBytes(_zfe.FileSize), 0, 4); // uncompressed file size + this.ZipFileStream.Write(BitConverter.GetBytes((ushort)encodedFilename.Length), 0, 2); // Filename in zip + this.ZipFileStream.Write(BitConverter.GetBytes((ushort)0), 0, 2); // extra length + this.ZipFileStream.Write(BitConverter.GetBytes((ushort)encodedComment.Length), 0, 2); + + this.ZipFileStream.Write(BitConverter.GetBytes((ushort)0), 0, 2); // disk=0 + this.ZipFileStream.Write(BitConverter.GetBytes((ushort)0), 0, 2); // file type: binary + this.ZipFileStream.Write(BitConverter.GetBytes((ushort)0), 0, 2); // Internal file attributes + this.ZipFileStream.Write(BitConverter.GetBytes((ushort)0x8100), 0, 2); // External file attributes (normal/readable) + this.ZipFileStream.Write(BitConverter.GetBytes(_zfe.HeaderOffset), 0, 4); // Offset of header + + this.ZipFileStream.Write(encodedFilename, 0, encodedFilename.Length); + this.ZipFileStream.Write(encodedComment, 0, encodedComment.Length); + } + /* End of central dir record: + end of central dir signature 4 bytes (0x06054b50) + number of this disk 2 bytes + number of the disk with the + start of the central directory 2 bytes + total number of entries in + the central dir on this disk 2 bytes + total number of entries in + the central dir 2 bytes + size of the central directory 4 bytes + offset of start of central + directory with respect to + the starting disk number 4 bytes + zipfile comment length 2 bytes + zipfile comment (variable size) + */ + private void WriteEndRecord(uint _size, uint _offset) + { + Encoding encoder = this.EncodeUTF8 ? Encoding.UTF8 : DefaultEncoding; + byte[] encodedComment = encoder.GetBytes(this.Comment); + + this.ZipFileStream.Write(new byte[] { 80, 75, 5, 6, 0, 0, 0, 0 }, 0, 8); + this.ZipFileStream.Write(BitConverter.GetBytes((ushort)Files.Count+ExistingFiles), 0, 2); + this.ZipFileStream.Write(BitConverter.GetBytes((ushort)Files.Count+ExistingFiles), 0, 2); + this.ZipFileStream.Write(BitConverter.GetBytes(_size), 0, 4); + this.ZipFileStream.Write(BitConverter.GetBytes(_offset), 0, 4); + this.ZipFileStream.Write(BitConverter.GetBytes((ushort)encodedComment.Length), 0, 2); + this.ZipFileStream.Write(encodedComment, 0, encodedComment.Length); + } + // Copies all source file into storage file + private void Store(ref ZipFileEntry _zfe, Stream _source) + { + byte[] buffer = new byte[16384]; + int bytesRead; + uint totalRead = 0; + Stream outStream; + + long posStart = this.ZipFileStream.Position; + long sourceStart = _source.Position; + + if (_zfe.Method == Compression.Store) + outStream = this.ZipFileStream; + else + outStream = new DeflateStream(this.ZipFileStream, CompressionMode.Compress, true); + + _zfe.Crc32 = 0 ^ 0xffffffff; + + do + { + bytesRead = _source.Read(buffer, 0, buffer.Length); + totalRead += (uint)bytesRead; + if (bytesRead > 0) + { + outStream.Write(buffer, 0, bytesRead); + + for (uint i = 0; i < bytesRead; i++) + { + _zfe.Crc32 = ZipStorer.CrcTable[(_zfe.Crc32 ^ buffer[i]) & 0xFF] ^ (_zfe.Crc32 >> 8); + } + } + } while (bytesRead == buffer.Length); + outStream.Flush(); + + if (_zfe.Method == Compression.Deflate) + outStream.Dispose(); + + _zfe.Crc32 ^= 0xffffffff; + _zfe.FileSize = totalRead; + _zfe.CompressedSize = (uint)(this.ZipFileStream.Position - posStart); + + // Verify for real compression + if (_zfe.Method == Compression.Deflate && !this.ForceDeflating && _source.CanSeek && _zfe.CompressedSize > _zfe.FileSize) + { + // Start operation again with Store algorithm + _zfe.Method = Compression.Store; + this.ZipFileStream.Position = posStart; + this.ZipFileStream.SetLength(posStart); + _source.Position = sourceStart; + this.Store(ref _zfe, _source); + } + } + /* DOS Date and time: + MS-DOS date. The date is a packed value with the following format. Bits Description + 0-4 Day of the month (1–31) + 5-8 Month (1 = January, 2 = February, and so on) + 9-15 Year offset from 1980 (add 1980 to get actual year) + MS-DOS time. The time is a packed value with the following format. Bits Description + 0-4 Second divided by 2 + 5-10 Minute (0–59) + 11-15 Hour (0–23 on a 24-hour clock) + */ + private uint DateTimeToDosTime(DateTime _dt) + { + return (uint)( + (_dt.Second / 2) | (_dt.Minute << 5) | (_dt.Hour << 11) | + (_dt.Day<<16) | (_dt.Month << 21) | ((_dt.Year - 1980) << 25)); + } + private DateTime DosTimeToDateTime(uint _dt) + { + return new DateTime( + (int)(_dt >> 25) + 1980, + (int)(_dt >> 21) & 15, + (int)(_dt >> 16) & 31, + (int)(_dt >> 11) & 31, + (int)(_dt >> 5) & 63, + (int)(_dt & 31) * 2); + } + + /* CRC32 algorithm + The 'magic number' for the CRC is 0xdebb20e3. + The proper CRC pre and post conditioning + is used, meaning that the CRC register is + pre-conditioned with all ones (a starting value + of 0xffffffff) and the value is post-conditioned by + taking the one's complement of the CRC residual. + If bit 3 of the general purpose flag is set, this + field is set to zero in the local header and the correct + value is put in the data descriptor and in the central + directory. + */ + private void UpdateCrcAndSizes(ref ZipFileEntry _zfe) + { + long lastPos = this.ZipFileStream.Position; // remember position + + this.ZipFileStream.Position = _zfe.HeaderOffset + 8; + this.ZipFileStream.Write(BitConverter.GetBytes((ushort)_zfe.Method), 0, 2); // zipping method + + this.ZipFileStream.Position = _zfe.HeaderOffset + 14; + this.ZipFileStream.Write(BitConverter.GetBytes(_zfe.Crc32), 0, 4); // Update CRC + this.ZipFileStream.Write(BitConverter.GetBytes(_zfe.CompressedSize), 0, 4); // Compressed size + this.ZipFileStream.Write(BitConverter.GetBytes(_zfe.FileSize), 0, 4); // Uncompressed size + + this.ZipFileStream.Position = lastPos; // restore position + } + // Replaces backslashes with slashes to store in zip header + private string NormalizedFilename(string _filename) + { + string filename = _filename.Replace('\\', '/'); + + int pos = filename.IndexOf(':'); + if (pos >= 0) + filename = filename.Remove(0, pos + 1); + + return filename.Trim('/'); + } + // Reads the end-of-central-directory record + private bool ReadFileInfo() + { + if (this.ZipFileStream.Length < 22) + return false; + + try + { + this.ZipFileStream.Seek(-17, SeekOrigin.End); + BinaryReader br = new BinaryReader(this.ZipFileStream); + do + { + this.ZipFileStream.Seek(-5, SeekOrigin.Current); + UInt32 sig = br.ReadUInt32(); + if (sig == 0x06054b50) + { + this.ZipFileStream.Seek(6, SeekOrigin.Current); + + UInt16 entries = br.ReadUInt16(); + Int32 centralSize = br.ReadInt32(); + UInt32 centralDirOffset = br.ReadUInt32(); + UInt16 commentSize = br.ReadUInt16(); + + // check if comment field is the very last data in file + if (this.ZipFileStream.Position + commentSize != this.ZipFileStream.Length) + return false; + + // Copy entire central directory to a memory buffer + this.ExistingFiles = entries; + this.CentralDirImage = new byte[centralSize]; + this.ZipFileStream.Seek(centralDirOffset, SeekOrigin.Begin); + this.ZipFileStream.Read(this.CentralDirImage, 0, centralSize); + + // Leave the pointer at the begining of central dir, to append new files + this.ZipFileStream.Seek(centralDirOffset, SeekOrigin.Begin); + return true; + } + } while (this.ZipFileStream.Position > 0); + } + catch { } + + return false; + } + #endregion + + #region IDisposable Members + /// + /// Closes the Zip file stream + /// + public void Dispose() + { + this.Close(); + } + #endregion + } +} From a7e73cfa99fa6ff762f202713dd11f0f409b6512 Mon Sep 17 00:00:00 2001 From: Juergen Koller Date: Mon, 1 Jun 2015 14:51:00 +0200 Subject: [PATCH 3/9] Added GetFileFromAppBundleAsync: var file1 = await PCLStorage.FileSystem.Current.GetFileFromAppBundleAsync(path, cancelationToken); If file1 is a zip archive now you can do var listWithFileNamesFromZipArchive = await file1.ExtractZip(PCLStorage.FileSystem.Current.LocalStorage, NameCollisionOption.ReplaceExisting, cancelationToken); to extract the zip. And if you need to save a stream: IFile file2 = await folder.CreateFileAsync("test1.dat", CreationCollisionOption.ReplaceExisting); await file2.WriteAsync(stream, cancelationToken); --- PCLStorage.sln | 2 - build/build - Copy.proj | 70 --------- build/build.proj | 2 +- common/CommonAssemblyInfo.cs | 4 +- src/PCLStorage.Abstractions/FileExtensions.cs | 39 ++--- src/PCLStorage.Abstractions/IFile.cs | 10 +- .../PCLStorage.Android.csproj | 1 + .../TargetPlatformFileSystem.cs | 33 +++++ .../DesktopFileSystem.cs | 5 +- .../FileSystemFile.cs | 24 +++- .../PCLStorage.FileSystem.Desktop.csproj | 1 + .../TargetPlatformFileSystem.cs | 28 ++++ src/PCLStorage.IsoStore.SL/IsoStoreFile.cs | 11 +- src/PCLStorage.WinRT/PCLStorage.WinRT.csproj | 1 + .../TargetPlatformFileSystem.cs | 134 ++++++++++++++++++ src/PCLStorage.WinRT/WinRTFile.cs | 113 +++++++-------- .../PCLStorage.WindowsPhone.csproj | 1 + .../TargetPlatformFileSystem.cs | 99 +++++++++++++ .../PCLStorage.iOS-Unified.csproj | 1 + .../TargetPlatformFileSystem.cs} | 19 ++- src/PCLStorage.iOS/PCLStorage.iOS.csproj | 2 +- .../TargetPlatformFileSystem.cs | 40 ++++++ 22 files changed, 462 insertions(+), 178 deletions(-) delete mode 100644 build/build - Copy.proj create mode 100644 src/PCLStorage.Android/TargetPlatformFileSystem.cs create mode 100644 src/PCLStorage.FileSystem.Desktop/TargetPlatformFileSystem.cs create mode 100644 src/PCLStorage.WinRT/TargetPlatformFileSystem.cs create mode 100644 src/PCLStorage.WindowsPhone/TargetPlatformFileSystem.cs rename src/{PCLStorage.iOS/iOSFileSystem.cs => PCLStorage.iOS-Unified/TargetPlatformFileSystem.cs} (63%) create mode 100644 src/PCLStorage.iOS/TargetPlatformFileSystem.cs diff --git a/PCLStorage.sln b/PCLStorage.sln index 7f78688..9eefb5c 100644 --- a/PCLStorage.sln +++ b/PCLStorage.sln @@ -53,8 +53,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{A5AE3457 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCLStorage.iOS-Unified", "src\PCLStorage.iOS-Unified\PCLStorage.iOS-Unified.csproj", "{3B479AED-CC1C-46F7-AF55-8BF9E8BA1C01}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "fsdfsfd", "fsdfsfd", "{C68BF2D5-548D-4318-9831-0B30646ACF15}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/build/build - Copy.proj b/build/build - Copy.proj deleted file mode 100644 index 9f40576..0000000 --- a/build/build - Copy.proj +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - $(MSBuildProjectDirectory)\.. - $(PCLStorageRoot)\.nuget\NuGet.exe - Release - - - - 1 - 0 - 2 - 0 - - - $(MajorVersion).$(MinorVersion).$(Build).$(Revision) - $(MajorVersion).$(MinorVersion).$(Build).$(Revision) - $(MajorVersion).$(MinorVersion).$(Build) - - - - - AssemblyVersion\("\d+\.\d+\.\d+\.\d+"\) - AssemblyVersion("$(AssemblyVersion)") - - - AssemblyFileVersion\("\d+\.\d+\.\d+\.\d+"\) - AssemblyFileVersion("$(AssemblyFileVersion)") - - - - - RestorePackages;UpdateVersion - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/build/build.proj b/build/build.proj index 306f5e6..043504d 100644 --- a/build/build.proj +++ b/build/build.proj @@ -11,7 +11,7 @@ 1 0 - 5 + 10 0 diff --git a/common/CommonAssemblyInfo.cs b/common/CommonAssemblyInfo.cs index 49e5280..4394901 100644 --- a/common/CommonAssemblyInfo.cs +++ b/common/CommonAssemblyInfo.cs @@ -26,5 +26,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.5.0")] -[assembly: AssemblyFileVersion("1.0.5.0")] +[assembly: AssemblyVersion("1.0.10.0")] +[assembly: AssemblyFileVersion("1.0.10.0")] diff --git a/src/PCLStorage.Abstractions/FileExtensions.cs b/src/PCLStorage.Abstractions/FileExtensions.cs index 033fd8c..9b9b7bb 100644 --- a/src/PCLStorage.Abstractions/FileExtensions.cs +++ b/src/PCLStorage.Abstractions/FileExtensions.cs @@ -27,24 +27,25 @@ public static async Task ReadAllTextAsync(this IFile file) return text; } } - } - - /// - /// Writes text to a file, overwriting any existing data - /// - /// The file to write to - /// The content to write to the file - /// A task which completes when the write operation finishes - public static async Task WriteAllTextAsync(this IFile file, string contents) - { - using (var stream = await file.OpenAsync(FileAccess.ReadAndWrite).ConfigureAwait(false)) - { - stream.SetLength(0); - using (var sw = new StreamWriter(stream)) - { - await sw.WriteAsync(contents).ConfigureAwait(false); - } - } - } + } + + /// + /// Writes text to a file, overwriting any existing data + /// + /// The file to write to + /// The content to write to the file + /// A task which completes when the write operation finishes + public static async Task WriteAllTextAsync(this IFile file, string contents) + { + using (var stream = await file.OpenAsync(FileAccess.ReadAndWrite).ConfigureAwait(false)) + { + stream.SetLength(0); + using (var sw = new StreamWriter(stream)) + { + await sw.WriteAsync(contents).ConfigureAwait(false); + } + } + } + } } diff --git a/src/PCLStorage.Abstractions/IFile.cs b/src/PCLStorage.Abstractions/IFile.cs index 0b7d606..3a5e3c6 100644 --- a/src/PCLStorage.Abstractions/IFile.cs +++ b/src/PCLStorage.Abstractions/IFile.cs @@ -45,6 +45,14 @@ public interface IFile /// A which can be used to read from or write to the file Task OpenAsync(FileAccess fileAccess, CancellationToken cancellationToken = default(CancellationToken)); + /// + /// Writes a stream to the file + /// + /// The data stream which should be written to the file. + /// The cancellation token. + /// Returns true for success. + Task WriteAsync(Stream stream, CancellationToken cancellationToken); + /// /// Deletes the file /// @@ -81,6 +89,6 @@ public interface IFile /// How to deal with collisions with existing files. /// The cancellation token. /// A task which will complete after the file is moved. - Task> ExtractZip(string desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)); + Task> ExtractZip(IFolder desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)); } } diff --git a/src/PCLStorage.Android/PCLStorage.Android.csproj b/src/PCLStorage.Android/PCLStorage.Android.csproj index 5a747a5..1363edd 100644 --- a/src/PCLStorage.Android/PCLStorage.Android.csproj +++ b/src/PCLStorage.Android/PCLStorage.Android.csproj @@ -77,6 +77,7 @@ + diff --git a/src/PCLStorage.Android/TargetPlatformFileSystem.cs b/src/PCLStorage.Android/TargetPlatformFileSystem.cs new file mode 100644 index 0000000..0b84e50 --- /dev/null +++ b/src/PCLStorage.Android/TargetPlatformFileSystem.cs @@ -0,0 +1,33 @@ +using Android.App; +using Android.Content.Res; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace PCLStorage +{ + /// + /// Implementation of over classic .NET file I/O APIs + /// + public class TargetPlatformFileSystem + { + /// + /// Gets a file from the App Bundle. Returns null if the file does not exist. + /// + /// The path to a file, as returned from the property. + /// The cancellation token. + /// A file for the given path, or null if it does not exist. + public static async Task GetFileFromAppBundleAsync(string path, CancellationToken cancellationToken) + { + Requires.NotNullOrEmpty(path, "path"); + await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken); + var f = new FileSystemFile(path); + return f; + } + + } +} diff --git a/src/PCLStorage.FileSystem.Desktop/DesktopFileSystem.cs b/src/PCLStorage.FileSystem.Desktop/DesktopFileSystem.cs index 03d1fd7..dab8fda 100644 --- a/src/PCLStorage.FileSystem.Desktop/DesktopFileSystem.cs +++ b/src/PCLStorage.FileSystem.Desktop/DesktopFileSystem.cs @@ -98,9 +98,10 @@ public async Task GetFolderFromPathAsync(string path, CancellationToken /// The cancellation token. /// A file for the given path, or null if it does not exist. //public partial Task GetFileFromAppBundleAsync(string path, CancellationToken cancellationToken); - public Task GetFileFromAppBundleAsync(string path, CancellationToken cancellationToken) + //public virtual Task GetFileFromAppBundleAsync(string path, CancellationToken cancellationToken); + public async Task GetFileFromAppBundleAsync(string path, CancellationToken cancellationToken) { - throw new NotImplementedException(); + return await TargetPlatformFileSystem.GetFileFromAppBundleAsync(path, cancellationToken); } } } diff --git a/src/PCLStorage.FileSystem.Desktop/FileSystemFile.cs b/src/PCLStorage.FileSystem.Desktop/FileSystemFile.cs index 6e64563..af4ab15 100644 --- a/src/PCLStorage.FileSystem.Desktop/FileSystemFile.cs +++ b/src/PCLStorage.FileSystem.Desktop/FileSystemFile.cs @@ -68,7 +68,24 @@ public async Task OpenAsync(FileAccess fileAccess, CancellationToken can { throw new ArgumentException("Unrecognized FileAccess value: " + fileAccess); } - } + } + + /// + /// Writes a stream to the file + /// + /// The data stream which should be written to the file. + /// Specifies whether the file should be overridden. + /// The cancellation token. + /// A returns true for success + public async Task WriteAsync(Stream stream, CancellationToken cancellationToken) + { + if (stream == null) return false; + byte[] bytes = new byte[stream.Length]; + await stream.ReadAsync(bytes, 0, (int)stream.Length).ConfigureAwait(false); + File.WriteAllBytes(this.Path, bytes); + stream.Close(); + return true; + } /// /// Deletes the file @@ -165,7 +182,7 @@ public async Task MoveAsync(string newPath, NameCollisionOption collisionOption, /// How to deal with collisions with existing files. /// The cancellation token. /// A task with a List of strings containing the names of extracted files from the zip archive. - public async Task> ExtractZip(string desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) + public async Task> ExtractZip(IFolder desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) { var extractedFilenames = new List(); await Task.Factory.StartNew(() => @@ -178,7 +195,7 @@ await Task.Factory.StartNew(() => { bool result = false; extractedFilenames.Add(entry.FilenameInZip); - var path = System.IO.Path.Combine(desinationFolder, System.IO.Path.GetFileName(entry.FilenameInZip)); + var path = System.IO.Path.Combine(desinationFolder.Path, System.IO.Path.GetFileName(entry.FilenameInZip)); if (System.IO.File.Exists(path)) { if (collisionOption == NameCollisionOption.ReplaceExisting) @@ -204,5 +221,6 @@ await Task.Factory.StartNew(() => }, cancellationToken); return extractedFilenames; } + } } diff --git a/src/PCLStorage.FileSystem.Desktop/PCLStorage.FileSystem.Desktop.csproj b/src/PCLStorage.FileSystem.Desktop/PCLStorage.FileSystem.Desktop.csproj index 755070b..7f674f2 100644 --- a/src/PCLStorage.FileSystem.Desktop/PCLStorage.FileSystem.Desktop.csproj +++ b/src/PCLStorage.FileSystem.Desktop/PCLStorage.FileSystem.Desktop.csproj @@ -78,6 +78,7 @@ + diff --git a/src/PCLStorage.FileSystem.Desktop/TargetPlatformFileSystem.cs b/src/PCLStorage.FileSystem.Desktop/TargetPlatformFileSystem.cs new file mode 100644 index 0000000..264b579 --- /dev/null +++ b/src/PCLStorage.FileSystem.Desktop/TargetPlatformFileSystem.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace PCLStorage +{ + /// + /// Implementation of over classic .NET file I/O APIs + /// + public class TargetPlatformFileSystem + { + /// + /// Gets a file from the App Bundle. Returns null if the file does not exist. + /// + /// The path to a file, as returned from the property. + /// The cancellation token. + /// A file for the given path, or null if it does not exist. + public static async Task GetFileFromAppBundleAsync(string path, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + } +} diff --git a/src/PCLStorage.IsoStore.SL/IsoStoreFile.cs b/src/PCLStorage.IsoStore.SL/IsoStoreFile.cs index 8a58acb..483fd92 100644 --- a/src/PCLStorage.IsoStore.SL/IsoStoreFile.cs +++ b/src/PCLStorage.IsoStore.SL/IsoStoreFile.cs @@ -119,7 +119,12 @@ public async Task OpenAsync(FileAccess fileAccess, CancellationToken can throw; } } - } + } + + public Task WriteAsync(Stream stream, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } /// /// Deletes the file @@ -235,10 +240,10 @@ public async Task MoveAsync(string newPath, NameCollisionOption collisionOption, } } - - public Task> ExtractZip(string desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) + public Task> ExtractZip(IFolder desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } + } } diff --git a/src/PCLStorage.WinRT/PCLStorage.WinRT.csproj b/src/PCLStorage.WinRT/PCLStorage.WinRT.csproj index cd5a284..bbf67b9 100644 --- a/src/PCLStorage.WinRT/PCLStorage.WinRT.csproj +++ b/src/PCLStorage.WinRT/PCLStorage.WinRT.csproj @@ -126,6 +126,7 @@ + diff --git a/src/PCLStorage.WinRT/TargetPlatformFileSystem.cs b/src/PCLStorage.WinRT/TargetPlatformFileSystem.cs new file mode 100644 index 0000000..b3b9b58 --- /dev/null +++ b/src/PCLStorage.WinRT/TargetPlatformFileSystem.cs @@ -0,0 +1,134 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Windows.Storage; +using Windows.Storage.Streams; + +namespace PCLStorage +{ + /// + /// Provides extension methods for the class + /// + public class TargetPlatformFileSystem + { + /// + /// Writes a stream to a file, overwriting any existing data + /// + /// The file to write to + /// The content to write to the file + /// The cancellation token. + /// A task which completes when the write operation finishes + public static async Task WriteStreamAsync(IFile file, Stream stream, CancellationToken cancellationToken) + { + if (stream == null) return false; + if (file == null) return false; + bool success = true; + StorageFile storageFile = await StorageFile.GetFileFromPathAsync(file.Path); + if (file != null) + { + try + { + if (stream != null) + { + using (StorageStreamTransaction transaction = await storageFile.OpenTransactedWriteAsync()) + { + using (DataWriter dataWriter = new DataWriter(transaction.Stream)) + { + dataWriter.WriteBytes(await ReadFully(stream, cancellationToken)); + transaction.Stream.Size = await dataWriter.StoreAsync(); // reset stream size to override the file + await transaction.CommitAsync(); + } + } + } + else + { + //JK.JKTools.JKLog("JK#66# The text box is empty, please write something and then click 'Write' again."); + success = false; + } + } + catch (FileNotFoundException) + { + //JK.JKTools.JKLog("JK#67# NotifyUserFileNotExist()"); + success = false; + } + } + else + { + //JK.JKTools.JKLog("JK#68# NotifyUserFileNotExist()"); + success = false; + } + return success; + } + + //Helper for WriteStreamAsync + private static async Task ReadFully(Stream input, CancellationToken cancellationToken) + { + byte[] buffer = new byte[16 * 1024]; + using (MemoryStream ms = new MemoryStream()) + { + int read; + while ((read = await input.ReadAsync(buffer, 0, buffer.Length)) > 0) + { + await ms.WriteAsync(buffer, 0, read); + if (cancellationToken.IsCancellationRequested) + { + return null; + } + } + return ms.ToArray(); + } + } + + /// + /// Extract a zip file. + /// + /// The destination folder for zip file extraction + /// How to deal with collisions with existing files. + /// The cancellation token. + /// A task with a List of strings containing the names of extracted files from the zip archive. + public static async Task> ExtractZip(IFile zipFile, IFolder desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) + { + var zipFiles = new List(); + Stream zipDataStream = await zipFile.OpenAsync(FileAccess.Read, cancellationToken); + if (zipDataStream == null) return null; + try + { + + ZipArchive zipArchive = new ZipArchive(zipDataStream); + foreach (var zipArchiveEntry in zipArchive.Entries) + { + var zipData = zipArchiveEntry.Open(); + if (zipData == null) + { + + } + else + { + if (zipArchiveEntry.Name == null || zipArchiveEntry.Name.Length == 0) + { + + } + else + { + IFile file = await desinationFolder.CreateFileAsync(zipArchiveEntry.Name, CreationCollisionOption.ReplaceExisting); + await WriteStreamAsync(file, zipData, cancellationToken); + zipFiles.Add(zipArchiveEntry.Name); + } + } + } + + } + catch (Exception e) + { + + } + return zipFiles; + } + + } +} diff --git a/src/PCLStorage.WinRT/WinRTFile.cs b/src/PCLStorage.WinRT/WinRTFile.cs index 8e53c8b..12b977b 100644 --- a/src/PCLStorage.WinRT/WinRTFile.cs +++ b/src/PCLStorage.WinRT/WinRTFile.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.IO.Compression; using System.Linq; using System.Text; using System.Threading; @@ -47,34 +46,46 @@ public string Name public string Path { get { return _wrappedFile.Path; } - } - - /// - /// Opens the file - /// - /// Specifies whether the file should be opened in read-only or read/write mode - /// The cancellation token. - /// A which can be used to read from or write to the file - public async Task OpenAsync(FileAccess fileAccess, CancellationToken cancellationToken) - { - FileAccessMode fileAccessMode; - if (fileAccess == FileAccess.Read) - { - fileAccessMode = FileAccessMode.Read; - } - else if (fileAccess == FileAccess.ReadAndWrite) - { - fileAccessMode = FileAccessMode.ReadWrite; - } - else - { - throw new ArgumentException("Unrecognized FileAccess value: " + fileAccess); - } - - var wrtStream = await _wrappedFile.OpenAsync(fileAccessMode).AsTask(cancellationToken).ConfigureAwait(false); - return wrtStream.AsStream(); - } - + } + + /// + /// Opens the file + /// + /// Specifies whether the file should be opened in read-only or read/write mode + /// The cancellation token. + /// A which can be used to read from or write to the file + public async Task OpenAsync(FileAccess fileAccess, CancellationToken cancellationToken) + { + FileAccessMode fileAccessMode; + if (fileAccess == FileAccess.Read) + { + fileAccessMode = FileAccessMode.Read; + } + else if (fileAccess == FileAccess.ReadAndWrite) + { + fileAccessMode = FileAccessMode.ReadWrite; + } + else + { + throw new ArgumentException("Unrecognized FileAccess value: " + fileAccess); + } + + var wrtStream = await _wrappedFile.OpenAsync(fileAccessMode).AsTask(cancellationToken).ConfigureAwait(false); + return wrtStream.AsStream(); + } + + /// + /// Writes a stream to the file + /// + /// The data stream which should be written to the file. + /// Specifies whether the file should be overridden. + /// The cancellation token. + /// A returns true for success + public async Task WriteAsync(Stream stream, CancellationToken cancellationToken) + { + return await TargetPlatformFileSystem.WriteStreamAsync(this, stream, cancellationToken); + } + /// /// Deletes the file /// @@ -144,41 +155,17 @@ public async Task MoveAsync(string newPath, NameCollisionOption collisionOption, } } - public async Task> ExtractZip(string desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) + /// + /// Extract a zip file. + /// + /// The destination folder for zip file extraction + /// How to deal with collisions with existing files. + /// The cancellation token. + /// A task with a List of strings containing the names of extracted files from the zip archive. + public async Task> ExtractZip(IFolder desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) { - var zipFiles = new List(); - var zipDataStream = await _wrappedFile.OpenReadAsync();// ReadFileFromDiskAsStream(ZipFilepath); - if (zipDataStream == null) return null; - try - { - ZipArchive zipArchive = new ZipArchive(zipDataStream.AsStream()); - foreach (var zipArchiveEntry in zipArchive.Entries) - { - var zipData = zipArchiveEntry.Open(); - if (zipData == null) - { - JK.JKTools.JKLog("JK#156# zipData == null speichern nicht möglich, " + ZipFilepath + ", " + ZipTargetFolder); - } - else - { - if (zipArchiveEntry.Name == null || zipArchiveEntry.Name.Length == 0) - { - JK.JKTools.JKLog("JK#157# kein gültiger Name für " + zipArchiveEntry.FullName + ", " + ZipFilepath + ", " + ZipTargetFolder); - } - else - { - await WriteFileToDisk(zipData, zipArchiveEntry.Name); - zipFiles.Add(zipArchiveEntry.Name); - } - } - } - - } - catch (Exception e) - { - JK.JKTools.JKLog("JK#91# ZipDecompress " + e.Message); - } - return zipFiles; + return await TargetPlatformFileSystem.ExtractZip(this, desinationFolder, collisionOption, cancellationToken); } + } } diff --git a/src/PCLStorage.WindowsPhone/PCLStorage.WindowsPhone.csproj b/src/PCLStorage.WindowsPhone/PCLStorage.WindowsPhone.csproj index aac5baf..842170d 100644 --- a/src/PCLStorage.WindowsPhone/PCLStorage.WindowsPhone.csproj +++ b/src/PCLStorage.WindowsPhone/PCLStorage.WindowsPhone.csproj @@ -133,6 +133,7 @@ Requires.cs + diff --git a/src/PCLStorage.WindowsPhone/TargetPlatformFileSystem.cs b/src/PCLStorage.WindowsPhone/TargetPlatformFileSystem.cs new file mode 100644 index 0000000..7f4c981 --- /dev/null +++ b/src/PCLStorage.WindowsPhone/TargetPlatformFileSystem.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Windows.Storage; +using Windows.Storage.Streams; + +namespace PCLStorage +{ + /// + /// Provides extension methods for the class + /// + public class TargetPlatformFileSystem + { + /// + /// Writes a stream to a file, overwriting any existing data + /// + /// The file to write to + /// The content to write to the file + /// The cancellation token. + /// A task which completes when the write operation finishes + public static async Task WriteStreamAsync(IFile file, Stream stream, CancellationToken cancellationToken) + { + if (stream == null) return false; + if (file == null) return false; + bool success = true; + StorageFile storageFile = await StorageFile.GetFileFromPathAsync(file.Path); + if (file != null) + { + try + { + if (stream != null) + { + using (StorageStreamTransaction transaction = await storageFile.OpenTransactedWriteAsync()) + { + using (DataWriter dataWriter = new DataWriter(transaction.Stream)) + { + dataWriter.WriteBytes(await ReadFully(stream, cancellationToken)); + transaction.Stream.Size = await dataWriter.StoreAsync(); // reset stream size to override the file + await transaction.CommitAsync(); + } + } + } + else + { + //JK.JKTools.JKLog("JK#66# The text box is empty, please write something and then click 'Write' again."); + success = false; + } + } + catch (FileNotFoundException) + { + //JK.JKTools.JKLog("JK#67# NotifyUserFileNotExist()"); + success = false; + } + } + else + { + //JK.JKTools.JKLog("JK#68# NotifyUserFileNotExist()"); + success = false; + } + return success; + } + + //Helper for WriteStreamAsync + private static async Task ReadFully(Stream input, CancellationToken cancellationToken) + { + byte[] buffer = new byte[16 * 1024]; + using (MemoryStream ms = new MemoryStream()) + { + int read; + while ((read = await input.ReadAsync(buffer, 0, buffer.Length)) > 0) + { + await ms.WriteAsync(buffer, 0, read); + if (cancellationToken.IsCancellationRequested) + { + return null; + } + } + return ms.ToArray(); + } + } + + /// + /// Extract a zip file. + /// + /// The destination folder for zip file extraction + /// How to deal with collisions with existing files. + /// The cancellation token. + /// A task with a List of strings containing the names of extracted files from the zip archive. + public static async Task> ExtractZip(IFile zipFile, IFolder desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) + { + throw new NotImplementedException(); + } + + } +} diff --git a/src/PCLStorage.iOS-Unified/PCLStorage.iOS-Unified.csproj b/src/PCLStorage.iOS-Unified/PCLStorage.iOS-Unified.csproj index 07ab1d5..851b20f 100644 --- a/src/PCLStorage.iOS-Unified/PCLStorage.iOS-Unified.csproj +++ b/src/PCLStorage.iOS-Unified/PCLStorage.iOS-Unified.csproj @@ -75,6 +75,7 @@ ZipStorer.cs + diff --git a/src/PCLStorage.iOS/iOSFileSystem.cs b/src/PCLStorage.iOS-Unified/TargetPlatformFileSystem.cs similarity index 63% rename from src/PCLStorage.iOS/iOSFileSystem.cs rename to src/PCLStorage.iOS-Unified/TargetPlatformFileSystem.cs index b2e9710..c9af5dd 100644 --- a/src/PCLStorage.iOS/iOSFileSystem.cs +++ b/src/PCLStorage.iOS-Unified/TargetPlatformFileSystem.cs @@ -1,4 +1,4 @@ -using MonoTouch.Foundation; +using Foundation; using System; using System.Collections.Generic; using System.IO; @@ -12,7 +12,7 @@ namespace PCLStorage /// /// Implementation of over classic .NET file I/O APIs /// - public abstract class iOSFileSystem + public class TargetPlatformFileSystem { /// /// Gets a file from the App Bundle. Returns null if the file does not exist. @@ -20,23 +20,20 @@ public abstract class iOSFileSystem /// The path to a file, as returned from the property. /// The cancellation token. /// A file for the given path, or null if it does not exist. - public async Task GetFileFromAppBundleAsync(string path, CancellationToken cancellationToken) + public static async Task GetFileFromAppBundleAsync(string path, CancellationToken cancellationToken) { Requires.NotNullOrEmpty(path, "path"); await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken); - var extension = new NSString(path).PathExtension; - var filename = new NSString(path).LastPathComponent.DeletePathExtension(); - var bundlePath = NSBundle.MainBundle.PathForResource(filename, extension); - + string bundlePath = NSBundle.MainBundle.ResourcePath; + bundlePath = Path.Combine(bundlePath, path); + FileSystemFile f = null; if (File.Exists(bundlePath)) { - return new FileSystemFile(bundlePath); + f = new FileSystemFile(bundlePath); } - - return null; - + return f; } } diff --git a/src/PCLStorage.iOS/PCLStorage.iOS.csproj b/src/PCLStorage.iOS/PCLStorage.iOS.csproj index 8637ce9..00a744c 100644 --- a/src/PCLStorage.iOS/PCLStorage.iOS.csproj +++ b/src/PCLStorage.iOS/PCLStorage.iOS.csproj @@ -67,7 +67,7 @@ ZipStorer.cs - + diff --git a/src/PCLStorage.iOS/TargetPlatformFileSystem.cs b/src/PCLStorage.iOS/TargetPlatformFileSystem.cs new file mode 100644 index 0000000..aa98db5 --- /dev/null +++ b/src/PCLStorage.iOS/TargetPlatformFileSystem.cs @@ -0,0 +1,40 @@ +using MonoTouch.Foundation; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace PCLStorage +{ + /// + /// Implementation of with platform specific Foundation methods + /// + public class TargetPlatformFileSystem + { + /// + /// Gets a file from the App Bundle. Returns null if the file does not exist. + /// + /// The path to a file, as returned from the property. + /// The cancellation token. + /// A file for the given path, or null if it does not exist. + public static async Task GetFileFromAppBundleAsync(string path, CancellationToken cancellationToken) + { + Requires.NotNullOrEmpty(path, "path"); + + await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken); + + string bundlePath = NSBundle.MainBundle.ResourcePath; + bundlePath = Path.Combine(bundlePath, path); + FileSystemFile f = null; + if (File.Exists(bundlePath)) + { + f = new FileSystemFile(bundlePath); + } + return f; + } + + } +} From dbd159cab1cc50a036b2b85fe32c7e512dd827d3 Mon Sep 17 00:00:00 2001 From: Juergen Koller Date: Tue, 2 Jun 2015 18:53:21 +0200 Subject: [PATCH 4/9] Android GetFileFromAppBundleAsync implemented --- build/build.proj | 2 +- common/CommonAssemblyInfo.cs | 4 +- src/PCLStorage.Abstractions/IFile.cs | 2 +- .../TargetPlatformFileSystem.cs | 32 +++++++++- .../FileSystemFile.cs | 58 +++++++++++-------- src/PCLStorage.IsoStore.SL/IsoStoreFile.cs | 2 +- .../TargetPlatformFileSystem.cs | 2 +- src/PCLStorage.WinRT/WinRTFile.cs | 4 +- .../TargetPlatformFileSystem.cs | 2 +- 9 files changed, 72 insertions(+), 36 deletions(-) diff --git a/build/build.proj b/build/build.proj index 043504d..dc995cf 100644 --- a/build/build.proj +++ b/build/build.proj @@ -11,7 +11,7 @@ 1 0 - 10 + 15 0 diff --git a/common/CommonAssemblyInfo.cs b/common/CommonAssemblyInfo.cs index 4394901..4c62c3a 100644 --- a/common/CommonAssemblyInfo.cs +++ b/common/CommonAssemblyInfo.cs @@ -26,5 +26,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.10.0")] -[assembly: AssemblyFileVersion("1.0.10.0")] +[assembly: AssemblyVersion("1.0.15.0")] +[assembly: AssemblyFileVersion("1.0.15.0")] diff --git a/src/PCLStorage.Abstractions/IFile.cs b/src/PCLStorage.Abstractions/IFile.cs index 3a5e3c6..79c6e29 100644 --- a/src/PCLStorage.Abstractions/IFile.cs +++ b/src/PCLStorage.Abstractions/IFile.cs @@ -89,6 +89,6 @@ public interface IFile /// How to deal with collisions with existing files. /// The cancellation token. /// A task which will complete after the file is moved. - Task> ExtractZip(IFolder desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)); + Task> ExtractZipAsync(IFolder desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)); } } diff --git a/src/PCLStorage.Android/TargetPlatformFileSystem.cs b/src/PCLStorage.Android/TargetPlatformFileSystem.cs index 0b84e50..1448a79 100644 --- a/src/PCLStorage.Android/TargetPlatformFileSystem.cs +++ b/src/PCLStorage.Android/TargetPlatformFileSystem.cs @@ -1,5 +1,6 @@ using Android.App; using Android.Content.Res; +using Java.IO; using System; using System.Collections.Generic; using System.IO; @@ -25,8 +26,35 @@ public static async Task GetFileFromAppBundleAsync(string path, Cancellat { Requires.NotNullOrEmpty(path, "path"); await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken); - var f = new FileSystemFile(path); - return f; + + //I was not able to access files from the Assets folder like 'file://android_asset/' + //Now I copy the file into a temp folder first + //Hopefully somebody got a better solution for this + + Stream iStream = Application.Context.Assets.Open(path); + var tempPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal); + tempPath = System.IO.Path.Combine(tempPath, "appbundlefilestempfolder"); + if (System.IO.Directory.Exists(tempPath) == false) + { + System.IO.Directory.CreateDirectory(tempPath); + } + tempPath = System.IO.Path.Combine(tempPath, path); + var oStream = new FileOutputStream(tempPath); + byte[] buffer = new byte[2048]; + int length = 2048; + while (iStream.Read(buffer, 0, length) > 0) + { + oStream.Write(buffer, 0, length); + } + oStream.Flush(); + oStream.Close(); + iStream.Close(); + + if (System.IO.File.Exists(tempPath) == false) + { + return null; + } + return new FileSystemFile(tempPath); } } diff --git a/src/PCLStorage.FileSystem.Desktop/FileSystemFile.cs b/src/PCLStorage.FileSystem.Desktop/FileSystemFile.cs index af4ab15..423ed53 100644 --- a/src/PCLStorage.FileSystem.Desktop/FileSystemFile.cs +++ b/src/PCLStorage.FileSystem.Desktop/FileSystemFile.cs @@ -182,42 +182,50 @@ public async Task MoveAsync(string newPath, NameCollisionOption collisionOption, /// How to deal with collisions with existing files. /// The cancellation token. /// A task with a List of strings containing the names of extracted files from the zip archive. - public async Task> ExtractZip(IFolder desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) + public async Task> ExtractZipAsync(IFolder desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) { + //Extraction fails on Android if the zip files comes from the asset folder; couldnt' find out why var extractedFilenames = new List(); await Task.Factory.StartNew(() => { - ZipStorer zip = ZipStorer.Open(_path, System.IO.FileAccess.Read); - //// Read all directory contents - List dir = zip.ReadCentralDir(); - //// Extract all files in target directory - foreach (ZipStorer.ZipFileEntry entry in dir) + try { - bool result = false; - extractedFilenames.Add(entry.FilenameInZip); - var path = System.IO.Path.Combine(desinationFolder.Path, System.IO.Path.GetFileName(entry.FilenameInZip)); - if (System.IO.File.Exists(path)) + ZipStorer zip = ZipStorer.Open(_path, System.IO.FileAccess.Read); + //// Read all directory contents + List dir = zip.ReadCentralDir(); + //// Extract all files in target directory + foreach (ZipStorer.ZipFileEntry entry in dir) { - if (collisionOption == NameCollisionOption.ReplaceExisting) + bool result = false; + extractedFilenames.Add(entry.FilenameInZip); + var path = System.IO.Path.Combine(desinationFolder.Path, System.IO.Path.GetFileName(entry.FilenameInZip)); + if (System.IO.File.Exists(path)) + { + if (collisionOption == NameCollisionOption.ReplaceExisting) + { + System.IO.File.Delete(path); + result = zip.ExtractFile(entry, path); + } + } + else { - System.IO.File.Delete(path); result = zip.ExtractFile(entry, path); } + if (result) + { + extractedFilenames.Add(System.IO.Path.GetFileName(entry.FilenameInZip)); + } + if (cancellationToken.IsCancellationRequested) + { + break; + } } - else - { - result = zip.ExtractFile(entry, path); - } - if (result) - { - extractedFilenames.Add(System.IO.Path.GetFileName(entry.FilenameInZip)); - } - if (cancellationToken.IsCancellationRequested) - { - break; - } + zip.Close(); + } + catch (Exception) + { + } - zip.Close(); }, cancellationToken); return extractedFilenames; } diff --git a/src/PCLStorage.IsoStore.SL/IsoStoreFile.cs b/src/PCLStorage.IsoStore.SL/IsoStoreFile.cs index 483fd92..4fd3d5c 100644 --- a/src/PCLStorage.IsoStore.SL/IsoStoreFile.cs +++ b/src/PCLStorage.IsoStore.SL/IsoStoreFile.cs @@ -240,7 +240,7 @@ public async Task MoveAsync(string newPath, NameCollisionOption collisionOption, } } - public Task> ExtractZip(IFolder desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) + public Task> ExtractZipAsync(IFolder desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } diff --git a/src/PCLStorage.WinRT/TargetPlatformFileSystem.cs b/src/PCLStorage.WinRT/TargetPlatformFileSystem.cs index b3b9b58..449b15c 100644 --- a/src/PCLStorage.WinRT/TargetPlatformFileSystem.cs +++ b/src/PCLStorage.WinRT/TargetPlatformFileSystem.cs @@ -91,7 +91,7 @@ private static async Task ReadFully(Stream input, CancellationToken canc /// How to deal with collisions with existing files. /// The cancellation token. /// A task with a List of strings containing the names of extracted files from the zip archive. - public static async Task> ExtractZip(IFile zipFile, IFolder desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) + public static async Task> ExtractZipAsync(IFile zipFile, IFolder desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) { var zipFiles = new List(); Stream zipDataStream = await zipFile.OpenAsync(FileAccess.Read, cancellationToken); diff --git a/src/PCLStorage.WinRT/WinRTFile.cs b/src/PCLStorage.WinRT/WinRTFile.cs index 12b977b..fa52ac7 100644 --- a/src/PCLStorage.WinRT/WinRTFile.cs +++ b/src/PCLStorage.WinRT/WinRTFile.cs @@ -162,9 +162,9 @@ public async Task MoveAsync(string newPath, NameCollisionOption collisionOption, /// How to deal with collisions with existing files. /// The cancellation token. /// A task with a List of strings containing the names of extracted files from the zip archive. - public async Task> ExtractZip(IFolder desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) + public async Task> ExtractZipAsync(IFolder desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) { - return await TargetPlatformFileSystem.ExtractZip(this, desinationFolder, collisionOption, cancellationToken); + return await TargetPlatformFileSystem.ExtractZipAsync(this, desinationFolder, collisionOption, cancellationToken); } } diff --git a/src/PCLStorage.WindowsPhone/TargetPlatformFileSystem.cs b/src/PCLStorage.WindowsPhone/TargetPlatformFileSystem.cs index 7f4c981..65e44ef 100644 --- a/src/PCLStorage.WindowsPhone/TargetPlatformFileSystem.cs +++ b/src/PCLStorage.WindowsPhone/TargetPlatformFileSystem.cs @@ -90,7 +90,7 @@ private static async Task ReadFully(Stream input, CancellationToken canc /// How to deal with collisions with existing files. /// The cancellation token. /// A task with a List of strings containing the names of extracted files from the zip archive. - public static async Task> ExtractZip(IFile zipFile, IFolder desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) + public static async Task> ExtractZipAsync(IFile zipFile, IFolder desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } From 51d5f6c5fe64ac4fb61530e802999615d286322d Mon Sep 17 00:00:00 2001 From: Juergen Koller Date: Thu, 4 Jun 2015 15:16:42 +0200 Subject: [PATCH 5/9] Android ExtractZipAsync --- .../TargetPlatformFileSystem.cs | 20 +++++++------ .../FileSystemFile.cs | 3 +- src/PCLStorage.WinRT/WinRTFolder.cs | 28 +++++++++---------- .../TargetPlatformFileSystem.cs | 1 + 4 files changed, 28 insertions(+), 24 deletions(-) diff --git a/src/PCLStorage.Android/TargetPlatformFileSystem.cs b/src/PCLStorage.Android/TargetPlatformFileSystem.cs index 1448a79..fdf3e98 100644 --- a/src/PCLStorage.Android/TargetPlatformFileSystem.cs +++ b/src/PCLStorage.Android/TargetPlatformFileSystem.cs @@ -39,16 +39,20 @@ public static async Task GetFileFromAppBundleAsync(string path, Cancellat System.IO.Directory.CreateDirectory(tempPath); } tempPath = System.IO.Path.Combine(tempPath, path); - var oStream = new FileOutputStream(tempPath); - byte[] buffer = new byte[2048]; - int length = 2048; - while (iStream.Read(buffer, 0, length) > 0) + if (System.IO.Directory.Exists(tempPath) == false) { - oStream.Write(buffer, 0, length); + //Files from the app package can't change so there is no need to copy them again + var oStream = new FileOutputStream(tempPath); + byte[] buffer = new byte[2048]; + int length = 2048; + while (iStream.Read(buffer, 0, length) > 0) + { + oStream.Write(buffer, 0, length); + } + oStream.Flush(); + oStream.Close(); + iStream.Close(); } - oStream.Flush(); - oStream.Close(); - iStream.Close(); if (System.IO.File.Exists(tempPath) == false) { diff --git a/src/PCLStorage.FileSystem.Desktop/FileSystemFile.cs b/src/PCLStorage.FileSystem.Desktop/FileSystemFile.cs index 423ed53..efb09b4 100644 --- a/src/PCLStorage.FileSystem.Desktop/FileSystemFile.cs +++ b/src/PCLStorage.FileSystem.Desktop/FileSystemFile.cs @@ -197,7 +197,6 @@ await Task.Factory.StartNew(() => foreach (ZipStorer.ZipFileEntry entry in dir) { bool result = false; - extractedFilenames.Add(entry.FilenameInZip); var path = System.IO.Path.Combine(desinationFolder.Path, System.IO.Path.GetFileName(entry.FilenameInZip)); if (System.IO.File.Exists(path)) { @@ -213,7 +212,7 @@ await Task.Factory.StartNew(() => } if (result) { - extractedFilenames.Add(System.IO.Path.GetFileName(entry.FilenameInZip)); + extractedFilenames.Add(entry.FilenameInZip); } if (cancellationToken.IsCancellationRequested) { diff --git a/src/PCLStorage.WinRT/WinRTFolder.cs b/src/PCLStorage.WinRT/WinRTFolder.cs index 52bcb09..a6e93f7 100644 --- a/src/PCLStorage.WinRT/WinRTFolder.cs +++ b/src/PCLStorage.WinRT/WinRTFolder.cs @@ -105,20 +105,20 @@ public async Task GetFileAsync(string name, CancellationToken cancellatio { throw new Exceptions.FileNotFoundException(ex.Message, ex); } - } - - /// - /// Gets a list of the files in this folder - /// - /// A list of the files in the folder - public async Task> GetFilesAsync(CancellationToken cancellationToken) - { - await EnsureExistsAsync(cancellationToken).ConfigureAwait(false); - var wrtFiles = await _wrappedFolder.GetFilesAsync().AsTask(cancellationToken).ConfigureAwait(false); - var files = wrtFiles.Select(f => new WinRTFile(f)).ToList(); - return new ReadOnlyCollection(files); - } - + } + + /// + /// Gets a list of the files in this folder + /// + /// A list of the files in the folder + public async Task> GetFilesAsync(CancellationToken cancellationToken) + { + await EnsureExistsAsync(cancellationToken).ConfigureAwait(false); + var wrtFiles = await _wrappedFolder.GetFilesAsync().AsTask(cancellationToken).ConfigureAwait(false); + var files = wrtFiles.Select(f => new WinRTFile(f)).ToList(); + return new ReadOnlyCollection(files); + } + /// /// Creates a subfolder in this folder /// diff --git a/src/PCLStorage.WindowsPhone/TargetPlatformFileSystem.cs b/src/PCLStorage.WindowsPhone/TargetPlatformFileSystem.cs index 65e44ef..cb7e2b5 100644 --- a/src/PCLStorage.WindowsPhone/TargetPlatformFileSystem.cs +++ b/src/PCLStorage.WindowsPhone/TargetPlatformFileSystem.cs @@ -86,6 +86,7 @@ private static async Task ReadFully(Stream input, CancellationToken canc /// /// Extract a zip file. /// + /// The zip archive /// The destination folder for zip file extraction /// How to deal with collisions with existing files. /// The cancellation token. From dc8677eebe45659e35371fd82cae556fe978c9a2 Mon Sep 17 00:00:00 2001 From: Juergen Koller Date: Fri, 12 Jun 2015 21:16:38 +0200 Subject: [PATCH 6/9] Added CopyAsync --- build/build.proj | 2 +- common/CommonAssemblyInfo.cs | 4 +- src/PCLStorage.Abstractions/IFile.cs | 11 +++- .../TargetPlatformFileSystem.cs | 6 +-- .../FileSystemFile.cs | 53 +++++++++++++++++++ src/PCLStorage.IsoStore.SL/IsoStoreFile.cs | 52 ++++++++++++++++++ src/PCLStorage.WinRT/WinRTFile.cs | 29 ++++++++++ 7 files changed, 150 insertions(+), 7 deletions(-) diff --git a/build/build.proj b/build/build.proj index dc995cf..e175cd1 100644 --- a/build/build.proj +++ b/build/build.proj @@ -11,7 +11,7 @@ 1 0 - 15 + 18 0 diff --git a/common/CommonAssemblyInfo.cs b/common/CommonAssemblyInfo.cs index 4c62c3a..2bd7b48 100644 --- a/common/CommonAssemblyInfo.cs +++ b/common/CommonAssemblyInfo.cs @@ -26,5 +26,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.15.0")] -[assembly: AssemblyFileVersion("1.0.15.0")] +[assembly: AssemblyVersion("1.0.18.0")] +[assembly: AssemblyFileVersion("1.0.18.0")] diff --git a/src/PCLStorage.Abstractions/IFile.cs b/src/PCLStorage.Abstractions/IFile.cs index 79c6e29..b5d8ab2 100644 --- a/src/PCLStorage.Abstractions/IFile.cs +++ b/src/PCLStorage.Abstractions/IFile.cs @@ -81,7 +81,16 @@ public interface IFile /// The cancellation token. /// A task which will complete after the file is moved. Task MoveAsync(string newPath, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)); - + + /// + /// Copy a file. + /// + /// The new full path of the file. + /// How to deal with collisions with existing files. + /// The cancellation token. + /// A task which will complete after the file is moved. + Task CopyAsync(string newPath, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)); + /// /// Extract a zip file. /// diff --git a/src/PCLStorage.Android/TargetPlatformFileSystem.cs b/src/PCLStorage.Android/TargetPlatformFileSystem.cs index fdf3e98..122b1cf 100644 --- a/src/PCLStorage.Android/TargetPlatformFileSystem.cs +++ b/src/PCLStorage.Android/TargetPlatformFileSystem.cs @@ -38,10 +38,11 @@ public static async Task GetFileFromAppBundleAsync(string path, Cancellat { System.IO.Directory.CreateDirectory(tempPath); } + path = System.IO.Path.GetFileName(path); //No subfolder inside the tempfolder tempPath = System.IO.Path.Combine(tempPath, path); - if (System.IO.Directory.Exists(tempPath) == false) + //Files from the app package can't change so there is no need to copy them again + if (System.IO.File.Exists(tempPath) == false) { - //Files from the app package can't change so there is no need to copy them again var oStream = new FileOutputStream(tempPath); byte[] buffer = new byte[2048]; int length = 2048; @@ -53,7 +54,6 @@ public static async Task GetFileFromAppBundleAsync(string path, Cancellat oStream.Close(); iStream.Close(); } - if (System.IO.File.Exists(tempPath) == false) { return null; diff --git a/src/PCLStorage.FileSystem.Desktop/FileSystemFile.cs b/src/PCLStorage.FileSystem.Desktop/FileSystemFile.cs index efb09b4..0344ec0 100644 --- a/src/PCLStorage.FileSystem.Desktop/FileSystemFile.cs +++ b/src/PCLStorage.FileSystem.Desktop/FileSystemFile.cs @@ -175,6 +175,59 @@ public async Task MoveAsync(string newPath, NameCollisionOption collisionOption, } + /// + /// Copy a file. + /// + /// The new full path of the file. + /// How to deal with collisions with existing files. + /// The cancellation token. + /// A task which will complete after the file is moved. + public async Task CopyAsync(string newPath, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) + { + Requires.NotNullOrEmpty(newPath, "newPath"); + + await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken); + + string newDirectory = System.IO.Path.GetDirectoryName(newPath); + string newName = System.IO.Path.GetFileName(newPath); + + for (int counter = 1; ; counter++) + { + cancellationToken.ThrowIfCancellationRequested(); + string candidateName = newName; + if (counter > 1) + { + candidateName = String.Format( + CultureInfo.InvariantCulture, + "{0} ({1}){2}", + System.IO.Path.GetFileNameWithoutExtension(newName), + counter, + System.IO.Path.GetExtension(newName)); + } + + string candidatePath = PortablePath.Combine(newDirectory, candidateName); + + if (File.Exists(candidatePath)) + { + switch (collisionOption) + { + case NameCollisionOption.FailIfExists: + throw new IOException("File already exists."); + case NameCollisionOption.GenerateUniqueName: + continue; // try again with a new name. + case NameCollisionOption.ReplaceExisting: + File.Delete(candidatePath); + break; + } + } + + File.Copy(_path, candidatePath); + _path = candidatePath; + _name = candidateName; + return; + } + } + /// /// Extract a zip file. /// diff --git a/src/PCLStorage.IsoStore.SL/IsoStoreFile.cs b/src/PCLStorage.IsoStore.SL/IsoStoreFile.cs index 4fd3d5c..4fc017e 100644 --- a/src/PCLStorage.IsoStore.SL/IsoStoreFile.cs +++ b/src/PCLStorage.IsoStore.SL/IsoStoreFile.cs @@ -240,6 +240,58 @@ public async Task MoveAsync(string newPath, NameCollisionOption collisionOption, } } + /// + /// Copy a file. + /// + /// The new full path of the file. + /// How to deal with collisions with existing files. + /// The cancellation token. + /// A task which will complete after the file is moved. + public async Task CopyAsync(string newPath, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) + { + Requires.NotNullOrEmpty(newPath, "newPath"); + + await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken); + string newDirectory = System.IO.Path.GetDirectoryName(newPath); + string newName = System.IO.Path.GetFileName(newPath); + + for (int counter = 1; ; counter++) + { + cancellationToken.ThrowIfCancellationRequested(); + string candidateName = newName; + if (counter > 1) + { + candidateName = String.Format( + CultureInfo.InvariantCulture, + "{0} ({1}){2}", + System.IO.Path.GetFileNameWithoutExtension(newName), + counter, + System.IO.Path.GetExtension(newName)); + } + + string candidatePath = PortablePath.Combine(newDirectory, candidateName); + + if (_root.FileExists(candidatePath)) + { + switch (collisionOption) + { + case NameCollisionOption.FailIfExists: + throw new IOException("File already exists."); + case NameCollisionOption.GenerateUniqueName: + continue; // try again with a new name. + case NameCollisionOption.ReplaceExisting: + _root.DeleteFile(candidatePath); + break; + } + } + + _root.CopyFile(_path, candidatePath); + _path = candidatePath; + _name = candidateName; + return; + } + } + public Task> ExtractZipAsync(IFolder desinationFolder, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); diff --git a/src/PCLStorage.WinRT/WinRTFile.cs b/src/PCLStorage.WinRT/WinRTFile.cs index fa52ac7..d2aee62 100644 --- a/src/PCLStorage.WinRT/WinRTFile.cs +++ b/src/PCLStorage.WinRT/WinRTFile.cs @@ -155,6 +155,35 @@ public async Task MoveAsync(string newPath, NameCollisionOption collisionOption, } } + /// + /// Copy a file. + /// + /// The new full path of the file. + /// How to deal with collisions with existing files. + /// The cancellation token. + /// A task which will complete after the file is moved. + public async Task CopyAsync(string newPath, NameCollisionOption collisionOption = NameCollisionOption.ReplaceExisting, CancellationToken cancellationToken = default(CancellationToken)) + { + Requires.NotNullOrEmpty(newPath, "newPath"); + + var newFolder = await StorageFolder.GetFolderFromPathAsync(System.IO.Path.GetDirectoryName(newPath)).AsTask(cancellationToken).ConfigureAwait(false); + string newName = System.IO.Path.GetFileName(newPath); + + try + { + await _wrappedFile.CopyAsync(newFolder, newName, (Windows.Storage.NameCollisionOption)collisionOption).AsTask(cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + if (ex.HResult == FILE_ALREADY_EXISTS) + { + throw new IOException("File already exists.", ex); + } + + throw; + } + } + /// /// Extract a zip file. /// From 59ea14081d73e3fef3c576bddea52a7d7e4270cb Mon Sep 17 00:00:00 2001 From: Juergen Koller Date: Tue, 28 Jul 2015 10:25:34 +0200 Subject: [PATCH 7/9] Android GetFileFromAppBundleAsync crash fixed --- build/build.proj | 2 +- common/CommonAssemblyInfo.cs | 4 ++-- src/PCLStorage.Android/TargetPlatformFileSystem.cs | 14 ++++++++++++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/build/build.proj b/build/build.proj index e175cd1..c16a02a 100644 --- a/build/build.proj +++ b/build/build.proj @@ -11,7 +11,7 @@ 1 0 - 18 + 20 0 diff --git a/common/CommonAssemblyInfo.cs b/common/CommonAssemblyInfo.cs index 2bd7b48..c3d069e 100644 --- a/common/CommonAssemblyInfo.cs +++ b/common/CommonAssemblyInfo.cs @@ -26,5 +26,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.18.0")] -[assembly: AssemblyFileVersion("1.0.18.0")] +[assembly: AssemblyVersion("1.0.20.0")] +[assembly: AssemblyFileVersion("1.0.20.0")] diff --git a/src/PCLStorage.Android/TargetPlatformFileSystem.cs b/src/PCLStorage.Android/TargetPlatformFileSystem.cs index 122b1cf..b698493 100644 --- a/src/PCLStorage.Android/TargetPlatformFileSystem.cs +++ b/src/PCLStorage.Android/TargetPlatformFileSystem.cs @@ -30,8 +30,18 @@ public static async Task GetFileFromAppBundleAsync(string path, Cancellat //I was not able to access files from the Assets folder like 'file://android_asset/' //Now I copy the file into a temp folder first //Hopefully somebody got a better solution for this - - Stream iStream = Application.Context.Assets.Open(path); + Stream iStream = null; + try + { + iStream = Application.Context.Assets.Open(path); + } + catch (Exception) + { + } + if (iStream == null) + { + return null; + } var tempPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal); tempPath = System.IO.Path.Combine(tempPath, "appbundlefilestempfolder"); if (System.IO.Directory.Exists(tempPath) == false) From 98a2a2e5cf1187bb9e6092e61380c5440de9ebc1 Mon Sep 17 00:00:00 2001 From: Juergen Koller Date: Fri, 20 Nov 2015 10:09:50 +0100 Subject: [PATCH 8/9] Android GetFileFromAppBundleAsync bug fixes --- build/build.proj | 2 +- common/CommonAssemblyInfo.cs | 4 +- .../PCLStorage.Android.csproj | 2 +- .../TargetPlatformFileSystem.cs | 62 ++++++++++++------- src/PCLStorage.WinRT/WinRTFileSystem.cs | 1 + .../TargetPlatformFileSystem.cs | 4 ++ .../TargetPlatformFileSystem.cs | 4 ++ .../PCLStorage.Test.Android.csproj | 2 +- 8 files changed, 55 insertions(+), 26 deletions(-) diff --git a/build/build.proj b/build/build.proj index c16a02a..afb2c68 100644 --- a/build/build.proj +++ b/build/build.proj @@ -11,7 +11,7 @@ 1 0 - 20 + 22 0 diff --git a/common/CommonAssemblyInfo.cs b/common/CommonAssemblyInfo.cs index c3d069e..ceb8f17 100644 --- a/common/CommonAssemblyInfo.cs +++ b/common/CommonAssemblyInfo.cs @@ -26,5 +26,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.20.0")] -[assembly: AssemblyFileVersion("1.0.20.0")] +[assembly: AssemblyVersion("1.0.22.0")] +[assembly: AssemblyFileVersion("1.0.22.0")] diff --git a/src/PCLStorage.Android/PCLStorage.Android.csproj b/src/PCLStorage.Android/PCLStorage.Android.csproj index 1363edd..f49ec53 100644 --- a/src/PCLStorage.Android/PCLStorage.Android.csproj +++ b/src/PCLStorage.Android/PCLStorage.Android.csproj @@ -15,7 +15,7 @@ Resources\Resource.Designer.cs Off True - v5.0 + v6.0 true diff --git a/src/PCLStorage.Android/TargetPlatformFileSystem.cs b/src/PCLStorage.Android/TargetPlatformFileSystem.cs index b698493..e3bbf64 100644 --- a/src/PCLStorage.Android/TargetPlatformFileSystem.cs +++ b/src/PCLStorage.Android/TargetPlatformFileSystem.cs @@ -29,19 +29,20 @@ public static async Task GetFileFromAppBundleAsync(string path, Cancellat //I was not able to access files from the Assets folder like 'file://android_asset/' //Now I copy the file into a temp folder first - //Hopefully somebody got a better solution for this - Stream iStream = null; - try - { - iStream = Application.Context.Assets.Open(path); - } - catch (Exception) - { - } - if (iStream == null) - { - return null; - } + //Hopefully somebody knows a better solution for this + //Stream iStream = null; + //try + //{ + // iStream = Application.Context.Assets.Open(path); + //} + //catch (Exception) + //{ + // System.Diagnostics.Debug.WriteLine("JK#237# GetFileFromAppBundleAsync Error file (" + path + ") must be in the assets folder marked as AndroidAsset."); + //} + //if (iStream == null) + //{ + // return null; + //} var tempPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal); tempPath = System.IO.Path.Combine(tempPath, "appbundlefilestempfolder"); if (System.IO.Directory.Exists(tempPath) == false) @@ -53,16 +54,35 @@ public static async Task GetFileFromAppBundleAsync(string path, Cancellat //Files from the app package can't change so there is no need to copy them again if (System.IO.File.Exists(tempPath) == false) { - var oStream = new FileOutputStream(tempPath); - byte[] buffer = new byte[2048]; - int length = 2048; - while (iStream.Read(buffer, 0, length) > 0) + try + { + using (var br = new BinaryReader(Application.Context.Assets.Open(path))) + { + using (var bw = new BinaryWriter(new FileStream(tempPath, FileMode.Create))) + { + byte[] buffer = new byte[2048]; + int length = 0; + while ((length = br.Read(buffer, 0, buffer.Length)) > 0) + { + bw.Write(buffer, 0, length); + } + } + } + } + catch (Exception e) { - oStream.Write(buffer, 0, length); + System.Diagnostics.Debug.WriteLine("JK#237# GetFileFromAppBundleAsync Error file (" + path + ") must be in the assets folder marked as AndroidAsset. " + e.Message); } - oStream.Flush(); - oStream.Close(); - iStream.Close(); + //var oStream = new FileOutputStream(tempPath); + //byte[] buffer = new byte[2048]; + //int length = 2048; + //while (iStream.Read(buffer, 0, length) > 0) + //{ + // oStream.Write(buffer, 0, length); + //} + //oStream.Flush(); + //oStream.Close(); + //iStream.Close(); } if (System.IO.File.Exists(tempPath) == false) { diff --git a/src/PCLStorage.WinRT/WinRTFileSystem.cs b/src/PCLStorage.WinRT/WinRTFileSystem.cs index f9bd285..f37637d 100644 --- a/src/PCLStorage.WinRT/WinRTFileSystem.cs +++ b/src/PCLStorage.WinRT/WinRTFileSystem.cs @@ -112,6 +112,7 @@ public async Task GetFileFromAppBundleAsync(string path, CancellationToke } catch (FileNotFoundException) { + System.Diagnostics.Debug.WriteLine("JK#237b# GetFileFromAppBundleAsync Error file (" + path + ") must be in the project folder marked as content."); return null; } diff --git a/src/PCLStorage.iOS-Unified/TargetPlatformFileSystem.cs b/src/PCLStorage.iOS-Unified/TargetPlatformFileSystem.cs index c9af5dd..430d637 100644 --- a/src/PCLStorage.iOS-Unified/TargetPlatformFileSystem.cs +++ b/src/PCLStorage.iOS-Unified/TargetPlatformFileSystem.cs @@ -33,6 +33,10 @@ public static async Task GetFileFromAppBundleAsync(string path, Cancellat { f = new FileSystemFile(bundlePath); } + else + { + System.Diagnostics.Debug.WriteLine("JK#237c# GetFileFromAppBundleAsync Error file (" + path + ") must be in the Recources folder marked as BundleResource."); + } return f; } diff --git a/src/PCLStorage.iOS/TargetPlatformFileSystem.cs b/src/PCLStorage.iOS/TargetPlatformFileSystem.cs index aa98db5..f90229c 100644 --- a/src/PCLStorage.iOS/TargetPlatformFileSystem.cs +++ b/src/PCLStorage.iOS/TargetPlatformFileSystem.cs @@ -33,6 +33,10 @@ public static async Task GetFileFromAppBundleAsync(string path, Cancellat { f = new FileSystemFile(bundlePath); } + else + { + System.Diagnostics.Debug.WriteLine("JK#237b# GetFileFromAppBundleAsync Error file (" + path + ") must be in the Resources folder marked as BundleResource."); + } return f; } diff --git a/test/PCLStorage.Test.Android/PCLStorage.Test.Android.csproj b/test/PCLStorage.Test.Android/PCLStorage.Test.Android.csproj index 3a88aec..fea8b9d 100644 --- a/test/PCLStorage.Test.Android/PCLStorage.Test.Android.csproj +++ b/test/PCLStorage.Test.Android/PCLStorage.Test.Android.csproj @@ -15,7 +15,7 @@ true Resources\Resource.Designer.cs Off - v5.0 + v6.0 Properties\AndroidManifest.xml True From ea1142d77628313fdb0999ed7d61a9d010d2224e Mon Sep 17 00:00:00 2001 From: Juergen Koller Date: Mon, 14 Dec 2015 11:49:06 +0100 Subject: [PATCH 9/9] Android sup folders in android assets are no longer ignored --- build/build.proj | 2 +- common/CommonAssemblyInfo.cs | 4 ++-- src/PCLStorage.Android/TargetPlatformFileSystem.cs | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/build.proj b/build/build.proj index afb2c68..c59a158 100644 --- a/build/build.proj +++ b/build/build.proj @@ -11,7 +11,7 @@ 1 0 - 22 + 23 0 diff --git a/common/CommonAssemblyInfo.cs b/common/CommonAssemblyInfo.cs index ceb8f17..137cac3 100644 --- a/common/CommonAssemblyInfo.cs +++ b/common/CommonAssemblyInfo.cs @@ -26,5 +26,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.22.0")] -[assembly: AssemblyFileVersion("1.0.22.0")] +[assembly: AssemblyVersion("1.0.23.0")] +[assembly: AssemblyFileVersion("1.0.23.0")] diff --git a/src/PCLStorage.Android/TargetPlatformFileSystem.cs b/src/PCLStorage.Android/TargetPlatformFileSystem.cs index e3bbf64..45534a4 100644 --- a/src/PCLStorage.Android/TargetPlatformFileSystem.cs +++ b/src/PCLStorage.Android/TargetPlatformFileSystem.cs @@ -22,9 +22,9 @@ public class TargetPlatformFileSystem /// The path to a file, as returned from the property. /// The cancellation token. /// A file for the given path, or null if it does not exist. - public static async Task GetFileFromAppBundleAsync(string path, CancellationToken cancellationToken) + public static async Task GetFileFromAppBundleAsync(string assetFolderFilePath, CancellationToken cancellationToken) { - Requires.NotNullOrEmpty(path, "path"); + Requires.NotNullOrEmpty(assetFolderFilePath, "assetFolderFilePath"); await AwaitExtensions.SwitchOffMainThreadAsync(cancellationToken); //I was not able to access files from the Assets folder like 'file://android_asset/' @@ -49,14 +49,14 @@ public static async Task GetFileFromAppBundleAsync(string path, Cancellat { System.IO.Directory.CreateDirectory(tempPath); } - path = System.IO.Path.GetFileName(path); //No subfolder inside the tempfolder + var path = System.IO.Path.GetFileName(assetFolderFilePath); //No subfolder inside the tempfolder tempPath = System.IO.Path.Combine(tempPath, path); //Files from the app package can't change so there is no need to copy them again if (System.IO.File.Exists(tempPath) == false) { try { - using (var br = new BinaryReader(Application.Context.Assets.Open(path))) + using (var br = new BinaryReader(Application.Context.Assets.Open(assetFolderFilePath))) { using (var bw = new BinaryWriter(new FileStream(tempPath, FileMode.Create))) {