要对打包为应用程序一部分的文件进行读写访问,您需要在ApplicationData.LocalFolder
应用程序首次运行时将其复制到您的目录,然后您可以从那里更新它。然后,您可以使用该LocalFolder.Path
属性使用正确的位置初始化连接字符串。原始文件将位于您的Package.InstalledLocation
.
这是一个基本示例,使用一个帮助类,您可以使用该类将任何文件从包中的任意位置复制到本地文件夹中的镜像位置,然后返回生成的文件名。
该示例是异步的,以防您在启动等过程中复制大文件,但如果您只需要包目录中的文件,则可以轻松地使其同步。此外,即使 API 是异步的,如果您愿意,也可以 100% 安全地阻止它(如下图所示)。
class LocalDataUtils
{
static readonly string destinationDirectory =
ApplicationData.Current.LocalFolder.Path;
static readonly string sourceDirectory =
Package.Current.InstalledPath;
static Dictionary<string, TaskCompletionSource<string>> fileCompletionTasks =
new Dictionary<string, TaskCompletionSource<string>>();
public static Task<string> GetFilenameAsync(string relativePath)
{
TaskCompletionSource<string> completion;
if (!fileCompletionTasks.TryGetValue(relativePath, out completion))
{
lock (fileCompletionTasks)
{
// Check again in case there was a race.
if (!fileCompletionTasks.TryGetValue(relativePath, out completion))
{
completion = new TaskCompletionSource<string>();
fileCompletionTasks.Add(relativePath, completion);
// This is async in case you ever need to copy from locations
// other than your local folders or you are copying files
// that might take a while.
// You can simplify and make it not-async if you like.
Task.Run(() => CopyFileAndGetFilename(relativePath, completion));
}
}
}
return completion.Task;
}
static void CopyFileAndGetFilename(string relativePath,
TaskCompletionSource<string> completion)
{
try
{
// Also a fun movie :)
var finalDestination = Path.Combine(destinationDirectory, relativePath);
if (!File.Exists(finalDestination))
{
var originalLocation = Path.Combine(sourceDirectory, relativePath);
Directory.CreateDirectory(Path.GetDirectoryName(finalDestination));
File.Copy(originalLocation, finalDestination);
}
completion.SetResult(finalDestination);
}
catch (Exception ex)
{
completion.SetException(ex);
}
}
}
使用它非常简单:
var name = await LocalDataUtils.GetFilenameAsync(@"Database\test.db");
var text = File.ReadAllText(name);
Debug.Write(text);
// Note: no 'await' here for illustrative purposes; subsequent calls
// for the same file will always return immediately.
var otherNameTask = LocalDataUtils.GetFilenameAsync(@"Database\test.db");
Debug.Assert(otherNameTask.IsCompletedSuccessfully);
// Don't call 'await' and instead block on the 'Result'
// This is not safe in general for async methods, but is fine in this case.
var name2 = LocalDataUtils.GetFilenameAsync(@"Assets\StoreLogo.png").Result;
var size = new FileInfo(name2).Length;
Debug.WriteLine($"{Path.GetFileName(name2)} is {size} bytes long.");