UWP でファイルのプロパティにすばやくアクセスするFast access to file properties in UWP 

ライブラリからファイルとそのプロパティの一覧をすばやく収集し、アプリでそれらのプロパティを使用する方法について説明します。Learn how to quickly gather a list of files and their properties from a library and use those properties in an app.  

前提条件Prerequisites 

  • ユニバーサル Windows プラットフォーム (UWP) アプリ向けの非同期プログラミング  C# または Visual Basic での非同期アプリの作成方法については、「C# または Visual Basic での非同期 API の呼び出し」をご覧ください。Asynchronous programming for Universal Windows Platform (UWP) apps   You can learn how to write asynchronous apps in C# or Visual Basic, see Call asynchronous APIs in C# or Visual Basic. C++ での非同期アプリの作成方法については、「C++ での非同期プログラミング」をご覧ください。To learn how to write asynchronous apps in C++, see Asynchronous programming in C++. 
  • ライブラリへのアクセス許可   これらの例のコードでは picturesLibrary 機能が必要ですが、ご利用のファイルの場所によっては別の機能が必要な場合や、機能をまったく必要としない場合もあります。Access permissions to Libraries   The code in these examples requires the picturesLibrary capability, but your file location may require a different capability, or no capability at all. 詳しくは、「ファイル アクセス許可」をご覧ください。To learn more, see File access permissions. 
  • シンプルなファイルの列挙    この例では、QueryOptions を使用して、高度な列挙プロパティをいくつか設定します。Simple file enumeration    This example uses QueryOptions to set a few advanced enumeration properties. 小さいディレクトリを対象としてファイルの簡単な一覧を取得する方法について詳しくは、「ファイルとフォルダーの列挙と照会」をご覧ください。To learn more about just getting a simple list of files for a smaller directory, see Enumerate and query files and folders. 

使用方法Usage  

多くのアプリでは、ファイルのグループのプロパティを一覧表示する必要がありますが、常にファイルと直接やり取りする必要はありません。Many apps need to list the properties of a group of files, but don't always need to interact with the files directly. たとえば、音楽アプリは一度に 1 つのファイルを再生します (開きます) が、アプリで曲のキューを表示したり、ユーザーが再生可能なファイルを選択したりする場合には、フォルダー内にあるすべてのファイルのプロパティが必要になります。For example, a music app plays (opens) one file at a time, but it needs the properties of all of the files in a folder so the app can show the song queue, or so the user can choose a valid file to play.

このページで紹介する例は、すべてのファイルのメタデータを変更するアプリや、プロパティを読み取ることができない場合に、生成されるすべての StorageFiles とやり取りするアプリには使用しないでください。The examples on this page shouldn't be used in apps that will modify the metadata of every file or apps that interact with all the resulting StorageFiles beyond reading their properties. 詳しくは、「ファイルとフォルダーの列挙と照会」をご覧ください。See Enumerate and query files and folders for more information. 

ある場所に保存されているすべての画像を列挙するEnumerate all the pictures in a location 

この例では、以下を行います。In this example, we will

  • QueryOptions オブジェクトを作成して、アプリではできるだけ早くファイルを列挙する必要があることを指定します。Build a QueryOptions object to specify that the app wants to enumerate the files as quickly as possible.
  • StorageFile オブジェクトをアプリにページングすることにより、ファイル プロパティをフェッチします。Fetch file properties by paging StorageFile objects into the app. ファイルをページングすることで、アプリによるメモリの使用量を削減し、認識可能な応答性を向上させることができます。Paging the files in reduces the memory used by the app and improves its perceived responsiveness.

クエリの作成Creating the query 

クエリを作成するには、QueryOptions オブジェクトを使用して、アプリでは特定の種類の画像ファイルだけを列挙する必要があることを指定し、Windows 情報保護 (System.Security.EncryptionOwners) によって保護されているファイルを除外します。To build the query, we use a QueryOptions object to specify that the app is interested in enumerating only certain types of images files and to filter out files protected with Windows Information Protection (System.Security.EncryptionOwners). 

QueryOptions.SetPropertyPrefetch を使用して、アプリがアクセサリするプロパティを設定することが重要です。It is important to set the properties the app is going to access using QueryOptions.SetPropertyPrefetch. アプリがプリフェッチされていないプロパティにアクセスすると、重大なパフォーマンス ペナルティが発生します。If the app accesses a property that isn’t prefetched, it will incur a significant performance penalty.

IndexerOption.OnlyUseIndexerAndOptimzeForIndexedProperties を設定して、結果をできるだけ早く返すこと、および SetPropertyPrefetch で指定したプロパティのみを含めることをシステムに通知します。Setting IndexerOption.OnlyUseIndexerAndOptimzeForIndexedProperties tells the system to return results as quickly as possible, but to only include the properties specified in SetPropertyPrefetch.

ページングして結果を生成するPaging in the results 

画像ライブラリには数十万または数百万のファイルが保存されている場合があり、GetFilesAsync を呼び出すことによって、コンピューターに過剰な負荷がかかる可能性があります。これは、画像ごとに StorageFile が作成されるためです。Users may have thousands or millions of files in their pictures library, so calling GetFilesAsync would overwhelm their machine because it creates a StorageFile for each image. これを解決するには、一度に一定数の StorageFiles を作成し、それらを処理して UI を作成してから、メモリを解放します。This can be solved by creating a fixed number of StorageFiles at one time, processing them into the UI, and then releasing the memory. 

この例では、StorageFileQueryResult.GetFilesAsync(UInt32 StartIndex, UInt32 maxNumberOfItems) を使用して、一度に 100 個のファイルのみをフェッチして、こうした問題に対処しています。In our example, we do this by using StorageFileQueryResult.GetFilesAsync(UInt32 StartIndex, UInt32 maxNumberOfItems) to only fetch 100 files at a time. この処理の次にアプリでファイルが処理され、その後で OS がメモリーを解放できるようにしています。The app will then process the files and allow the OS to release that memory afterwards. この方法では、アプリの最大メモリが制限され、システムは応答性を維持します。This technique caps the maximum memory of the app and ensures the system stays responsive. もちろん、実施するシナリオで返されるファイルの数は調整する必要がありますが、すべてのユーザーに対して応答性の高いエクスペリエンスを確保するために、一度にフェッチするファイルの数は 500 未満にすることをお勧めします。Of course, you will need to adjust the number of files returned for your scenario, but to ensure a responsive experience for all users, it's recommended to not fetch more than 500 files at one time.

Example  

StorageFolder folderToEnumerate = KnownFolders.PicturesLibrary; 
// Check if the folder is indexed before doing anything. 
IndexedState folderIndexedState = await folderToEnumerate.GetIndexedStateAsync(); 
if (folderIndexedState == IndexedState.NotIndexed || folderIndexedState == IndexedState.Unknown) 
{ 
    // Only possible in indexed directories.  
    return; 
} 
 
QueryOptions picturesQuery = new QueryOptions() 
{ 
    FolderDepth = FolderDepth.Deep, 
    // Filter out all files that have WIP enabled
    ApplicationSearchFilter = "System.Security.EncryptionOwners:[]", 
    IndexerOption = IndexerOption.OnlyUseIndexerAndOptimizeForIndexedProperties 
}; 

picturesQuery.FileTypeFilter.Add(".jpg"); 
string[] otherProperties = new string[] 
{ 
    SystemProperties.GPS.LatitudeDecimal, 
    SystemProperties.GPS.LongitudeDecimal 
}; 
 
picturesQuery.SetPropertyPrefetch(PropertyPrefetchOptions.BasicProperties | PropertyPrefetchOptions.ImageProperties, 
                                    otherProperties); 
SortEntry sortOrder = new SortEntry() 
{ 
    AscendingOrder = true, 
    PropertyName = "System.FileName" // FileName property is used as an example. Any property can be used here.  
}; 
picturesQuery.SortOrder.Add(sortOrder); 
 
// Create the query and get the results 
uint index = 0; 
const uint stepSize = 100; 
if (!folderToEnumerate.AreQueryOptionsSupported(picturesQuery)) 
{ 
    log("Querying for a sort order is not supported in this location"); 
    picturesQuery.SortOrder.Clear(); 
} 
StorageFileQueryResult queryResult = folderToEnumerate.CreateFileQueryWithOptions(picturesQuery); 
IReadOnlyList<StorageFile> images = await queryResult.GetFilesAsync(index, stepSize); 
while (images.Count != 0 || index < 10000) 
{ 
    foreach (StorageFile file in images) 
    { 
        // With the OnlyUseIndexerAndOptimizeForIndexedProperties set, this won't  
        // be async. It will run synchronously. 
        var imageProps = await file.Properties.GetImagePropertiesAsync(); 
 
        // Build the UI 
        log(String.Format("{0} at {1}, {2}", 
                    file.Path, 
                    imageProps.Latitude, 
                    imageProps.Longitude)); 
    } 
    index += stepSize; 
    images = await queryResult.GetFilesAsync(index, stepSize); 
} 

結果Results 

結果として生成される StorageFile ファイルには要求したプロパティのみが含まれますが、他の IndexerOptions と比較して、10 倍速く結果が返されます。The resulting StorageFile files only contain the properties requested, but are returned 10 times faster compared to the other IndexerOptions. アプリでは、クエリにまだ含まれていないプロパティへのアクセスを要求できますが、ファイルを開き、それらのプロパティを取得するとパフォーマンス ペナルティが発生します。 The app can still request access to properties not already included in the query, but there is a performance penalty to open the file and retrieve those properties.  

フォルダーをライブラリに追加するAdding folders to Libraries 

アプリでは、StorageLibrary.RequestAddFolderAsync を使用して、ファイルの場所をインデックスに追加するよう、ユーザーに対して要求することができます。Apps can request the user to add the location to the index using StorageLibrary.RequestAddFolderAsync. 場所が追加されると、自動的にインデックスが作成されます。アプリはこの方法を使用してファイルを列挙することができます。Once the location is included, it will be automatically indexed and apps can use this technique to enumerate the files.  

関連項目See also

QueryOptions API リファレンスQueryOptions API Reference
ファイルとフォルダーの列挙と照会Enumerate and query files and folders
ファイル アクセス許可File access permissions