如何在Windows Phone 8上使用Windows.Storage正确读写文件

4
我需要使用Windows.Storage API在Windows Phone 8中简单地写入并读取文件。使用旧的IsolatedStorage方法相对容易,但是使用新的WinRT API则更加困难。尝试编写代码时,会遇到一些奇怪的问题,例如IBuffer等。在完整版本的WinRT中,使用Windows.Storage.FileIO非常容易,这似乎是为了让像我这样的开发人员不要变得疯狂。但是,在Phone版本中没有实现它。此外,我观看了一个Channel9视频,其中展示了一些代码示例,但它们有一个错误,即使用标记为安全关键的方法来获取常规流。显然,不允许获取常规流。因此,是否可以向我提供一个简洁而正确的片段,以便将文件读入字符串并将字符串写入文件,包括适当的使用和处理技术?

根据您要做的事情,可以看一下Akavache。如果它能解决您的问题,您可以直接使用它,或者查看源代码以了解他们是如何解决这些问题的。 - vcsjones
@vcsjones 这是需要记在心里的好建议,但我们不能包含任何依赖项 :( 另外,它在 WP8 上使用 IsolatedStorage - Earlz
PCL Storage 项目为可移植类库提供了一个通用的 I/O 操作接口。或许这能给你一些提示? - Anders Gustafsson
你有没有尝试过使用 using (StreamReader sr = new StreamReader(File.OpenRead(strFileLoc)))... 这种代码风格?我在我的开发注册 WP8 上部署的应用程序中使用标准文件写入似乎很正常。这里提供了更多信息。 - ruffin
2个回答

13

这里有一个简单的例子:

public async Task WriteDataToFileAsync(string fileName, string content)
{
    byte[] data = Encoding.Unicode.GetBytes(content);

    var folder = ApplicationData.Current.LocalFolder;
    var file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);

    using (var s = await file.OpenStreamForWriteAsync())
    {
        await s.WriteAsync(data, 0, data.Length);
    }
}

public async Task<string> ReadFileContentsAsync(string fileName)
{
    var folder = ApplicationData.Current.LocalFolder;

    try
    {
        var file = await folder.OpenStreamForReadAsync(fileName);

        using (var streamReader = new StreamReader(file))
        {
            return streamReader.ReadToEnd();
        }
    }
    catch (Exception)
    {
        return string.Empty;
    }
}
请问需要翻译成什么语言呢?
await this.WriteDataToFileAsync("afile.txt", "some text to save in a file");

var contents = await this.ReadFileContentsAsync("afile.txt");

几个问题:1. 在写入方法中应该返回任务(Task),这样它就可以被等待。2. 看起来你正在写入 UTF8 并读取 UTF16,或者是 StreamReader 聪明到可以在没有被告知的情况下识别编码方式? - Paul Annetts
@PaulAnnetts 不错的建议。这会教会我不要只是从随意的互联网来源复制粘贴 ;) - Matt Lacey
此外,使用 OpenStreamForReadAsync 是安全关键的。 - Earlz
@Earlz 可以问一下为什么 OpenStreamForReadAsync 很重要吗?微软在他们的示例代码中使用了它(http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj681698(v=vs.105).aspx),所以似乎我们应该使用这些。 - Stefan Wexel
@StefanWexel 是的,最后这并不重要。我现在甚至不理解什么是安全关键,但是我从非安全关键代码调用安全关键函数时没有收到任何认证错误...所以我想一切都好了。 - Earlz

3
我没有尝试过在Windows Phone 8上使用它,但是WinRT XAML Toolkit提供了一个适用于Windows 8的解决方案,可能可以使用。请参考此处:链接
using System;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Storage.Streams;

namespace WinRTXamlToolkit.IO.Extensions
{
    /// <summary>
    /// Extensions for simple writing and reading of strings to/from files.
    /// </summary>
    /// <remarks>
    /// Note that these were created before FileIO class existed in WinRT, but they still serve a purpose.
    /// </remarks>
    public static class StringIOExtensions
    {
        /// <summary>
        /// Reads a string from a text file.
        /// </summary>
        /// <param name="fileName">Name of the file.</param>
        /// <param name="folder">The folder.</param>
        /// <returns></returns>
        public static async Task<string> ReadFromFile(
            string fileName,
            StorageFolder folder = null)
        {
            folder = folder ?? ApplicationData.Current.LocalFolder;
            var file = await folder.GetFileAsync(fileName);

            using (var fs = await file.OpenAsync(FileAccessMode.Read))
            {
                using (var inStream = fs.GetInputStreamAt(0))
                {
                    using (var reader = new DataReader(inStream))
                    {
                        await reader.LoadAsync((uint)fs.Size);
                        string data = reader.ReadString((uint)fs.Size);
                        reader.DetachStream();

                        return data;
                    }
                }
            }
        }

        /// <summary>
        /// Writes a string to a text file.
        /// </summary>
        /// <param name="text">The text to write.</param>
        /// <param name="fileName">Name of the file.</param>
        /// <param name="folder">The folder.</param>
        /// <param name="options">
        /// The enum value that determines how responds if the fileName is the same
        /// as the name of an existing file in the current folder. Defaults to ReplaceExisting.
        /// </param>
        /// <returns></returns>
        public static async Task WriteToFile(
            this string text,
            string fileName,
            StorageFolder folder = null,
            CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
        {
            folder = folder ?? ApplicationData.Current.LocalFolder;
            var file = await folder.CreateFileAsync(
                fileName,
                options);
            using (var fs = await file.OpenAsync(FileAccessMode.ReadWrite))
            {
                using (var outStream = fs.GetOutputStreamAt(0))
                {
                    using (var dataWriter = new DataWriter(outStream))
                    {
                        if (text != null)
                            dataWriter.WriteString(text);

                        await dataWriter.StoreAsync();
                        dataWriter.DetachStream();
                    }

                    await outStream.FlushAsync();
                }
            }
        }
    }
}

这比“简单示例”效果更好。可能是因为这段代码使用了FlushAsync等方法进行清理。我正在使用VS2013更新2,而在这个领域,事情变化很大! - ezaspi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接