Files, folders, and libraries阅读笔记。
Enumerate and query files and folders
WinRT可以让APP访问目录,文档库,设备,以及网络上的文件。你可以编写查询来搜寻想要的文件。
WinRT的文件访问有一些需要注意的方面:API一般是异步进行的;文件需要一定的访问权限File access permissions。
文中所列举的例子是使用StorageFolder.GetFilesAsync和StorageFolder.GetFoldersAsync来列举KnownFolders.PicturesLibrary下的文件和目录。
或者,也可以使用StorageFolder.GetItemsAsync来同时获取文件和目录。
你可以通过查询的方式,来获取部分感兴趣的文件。文中列举了另一个例子,使用搭配CommonFolderQuery.GroupByMonth使用StorageFolder.CreateFolderQuery,来获取一个StorageFolderQueryResult 对象,里面包含若干个StorageFolder,表征虚拟的目录,每个目录存储有按月分组的文件。
Enumerate and query files and folders
通过FileIO.WriteTextAsync 可以向一个StorageFile写入字符串:
await Windows.Storage.FileIO.WriteTextAsync(sampleFile, "Swift as a shadow");
如果要直接写入字节,需要使用CryptographicBuffer.ConvertStringToBinary 先将字符编码,然后再调用FileIO.WriteBufferAsync写入:
var buffer = Windows.Security.Cryptography.CryptographicBuffer.ConvertStringToBinary(
"What fools these mortals be", Windows.Security.Cryptography.BinaryStringEncoding.Utf8);
await Windows.Storage.FileIO.WriteBufferAsync(sampleFile, buffer);
如果要以流式(stream)方式写入,那么需要以下几步:
- 打开一个流:
var stream = await sampleFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
- 调用IRandomAccessStream.GetOutputStreamAt获取输出流:
stream.GetOutputStreamAt(0)
- 创建一个DataWriter:
var dataWriter = new Windows.Storage.Streams.DataWriter(outputStream)
- 然后调用dataWriter的方法写入:
dataWriter.WriteString("DataWriter has methods to write to various types, such as DataTimeOffset.");
- 同步dataWriter中的数据到流:
await dataWriter.StoreAsync();
- 同步流中的数据到硬盘:
await outputStream.FlushAsync();
读取文件内容也有几种方式。一是通过FileIO.ReadTextAsync 直接从StorageFile读取字符串:string text = await Windows.Storage.FileIO.ReadTextAsync(sampleFile);
以缓冲方式读:
var buffer = await Windows.Storage.FileIO.ReadBufferAsync(sampleFile);
using (var dataReader = Windows.Storage.Streams.DataReader.FromBuffer(buffer))
{
string text = dataReader.ReadString(buffer.Length);
}
以流的方式读:
var stream = await sampleFile.OpenAsync(Windows.Storage.FileAccessMode.Read);
using (var inputStream = stream.GetInputStreamAt(0))
{
using (var dataReader = new Windows.Storage.Streams.DataReader(inputStream))
{
uint numBytesLoaded = await dataReader.LoadAsync((uint)size);
string text = dataReader.ReadString(numBytesLoaded);
}
}
Best practices for writing to files
这篇介绍Windows.Storage.FileIO和PathIO的下面几个方法:
- WriteBufferAsync
- WriteBytesAsync
- WriteLinesAsync
- WriteTextAsync
首先,StorageFile并不是传统意义上的Win32文件句柄,只是一个有若干文件操作方法的文件表示,本身不具有太多状态。文件写入方式有前面介绍过的直接写入,缓冲写入或者流式写入。前面两种方式可以看成第三种方式的包装。
实际写入过程非常复杂,需要使用到OpenTransactedWriteAsync来打开一个StorageStreamTransaction,并使用临时文件作为事务的缓存。中间过程会出现各种错误,列举如下:
- ERROR_ACCESS_DENIED (0X80070005) 文件可能已被删除
- ERROR_SHARING_VIOLATION (0x80070020) 文件已经被以exclusive write的方式打开。
- ERROR_UNABLE_TO_REMOVE_REPLACED (0x80070497) 临时文件无法替换目标文件
- ERROR_DISK_FULL (0x80070070) 顾名思义
- ERROR_OUTOFMEMORY (0x8007000E) 顾名思义
- E_FAIL (0x80004005) 其他错误
如果文件正在被写入,那么以FileAccessMode.Read操作打开的读操作会失败,返回ERROR_OPLOCK_HANDLE_CLOSED (0x80070323)。如果遇到此错误,然后再尝试打开文件读取,会导致文件写入出错。(可能文件写入的时候会让读取无效)
如果有多个Write操作指向同一个文件,不能保证那个Write操作的内容会写入。应用需要自己协调Write操作。
出错情况下有可能会出现~Tmp文件残留,可以再App Activation的时候清除这些文件。
当应用切入后台的时候,会有5秒钟清除所有资源。其他参考:App lifecycle 以及 the-lifecycle-of-a-uwp-app BasicSuspension AsyncReaderWriterLock
(未完待续)