.NET を使用して Azure Data Lake Storage Gen2 でディレクトリとファイルを管理する

この記事では、階層型名前空間が有効になっているストレージ アカウントで、.NET を使用してディレクトリとファイルを作成および管理する方法を示します。

ディレクトリとファイルのアクセス制御リスト (ACL) を取得、設定、および更新する方法については、「Azure Data Lake Storage Gen2 で .NET を使用して ACL を管理する」を参照してください。

パッケージ (NuGet) | サンプル | API リファレンス | Gen1 から Gen2 へのマッピング | フィードバックを送る

前提条件

  • Azure サブスクリプション。 Azure 無料試用版の取得に関するページを参照してください。

  • 階層型名前空間が有効になっているストレージ アカウント。 作成するには、こちらの手順に従います。

プロジェクトの設定

まず、Azure.Storage.Files.DataLake NuGet パッケージをインストールします。

NuGet パッケージのインストール方法の詳細については、「NuGet パッケージ マネージャーを使用して Visual Studio にパッケージをインストールして管理する」を参照してください。

次に、これらの using ステートメントをコード ファイルの先頭に追加します。

using Azure;
using Azure.Storage.Files.DataLake;
using Azure.Storage.Files.DataLake.Models;
using Azure.Storage;
using System.IO;

Note

Data Lake Storage のマルチプロトコル アクセスでは、アプリケーションは BLOB API と Data Lake Storage Gen2 API の両方を使用して、階層型名前空間 (HNS) が有効なストレージ アカウント内のデータを操作できます。 ディレクトリ操作や ACL など、Data Lake Storage Gen2 に固有の機能を使用する場合は、この記事に示すように Data Lake Storage Gen2 API を使用します。

特定のシナリオで使用する API を選択する場合は、ワークロードとアプリケーションのニーズを、既知の問題HNS がワークロードとアプリケーションに与える影響と一緒に考慮してください。

データ リソースへのアクセスを認可して接続する

この記事のコード例を使用するには、ストレージ アカウントを表す認可済みの DataLakeServiceClient インスタンスを作成する必要があります。 Microsoft Entra ID、アカウント アクセス キー、または Shared Access Signature (SAS) を使って、DataLakeServiceClient オブジェクトを承認できます。

.NET 用 Azure ID クライアント ライブラリを使用して、Microsoft Entra ID でアプリケーションを認証できます。

DataLakeServiceClient インスタンスを作成し、DefaultAzureCredential クラスの新しいインスタンスを渡します。

public static DataLakeServiceClient GetDataLakeServiceClient(string accountName)
{
    string dfsUri = $"https://{accountName}.dfs.core.windows.net";

    DataLakeServiceClient dataLakeServiceClient = new DataLakeServiceClient(
        new Uri(dfsUri),
        new DefaultAzureCredential());

    return dataLakeServiceClient;
}

DefaultAzureCredential を使用してデータへのアクセスを承認する方法の詳細については、Azure サービスで .NET アプリケーションを認証する方法に関するページを参照してください。

コンテナーを作成する

コンテナーは、ファイルのファイル システムとして機能します。 次のメソッドを使用して、コンテナーを作成できます。

次のコード例では、コンテナーを作成し、後で使用する DataLakeFileSystemClient オブジェクトを返します:

public async Task<DataLakeFileSystemClient> CreateFileSystem(
    DataLakeServiceClient serviceClient,
    string fileSystemName)
{
    return await serviceClient.CreateFileSystemAsync(fileSystemName);
}

ディレクトリを作成する

次のメソッドを使用して、コンテナー内にディレクトリ参照を作成できます。

次のコード例では、コンテナーにディレクトリを追加した後に、サブディレクトリを追加し、後で使用するために DataLakeDirectoryClient オブジェクトを返します。

public async Task<DataLakeDirectoryClient> CreateDirectory(
    DataLakeFileSystemClient fileSystemClient,
    string directoryName,
    string subdirectoryName)
{
    DataLakeDirectoryClient directoryClient =
        await fileSystemClient.CreateDirectoryAsync(directoryName);

    return await directoryClient.CreateSubDirectoryAsync(subdirectoryName);
}

ディレクトリの名前変更または移動

次のメソッドを使用して、ディレクトリの名前の変更または移動を行うことができます。

目的のディレクトリ パスをパラメーターに渡します。 次のコード例は、サブディレクトリの名前の変更方法を示しています。

public async Task<DataLakeDirectoryClient> RenameDirectory(
    DataLakeFileSystemClient fileSystemClient,
    string directoryPath,
    string subdirectoryName,
    string subdirectoryNameNew)
{
    DataLakeDirectoryClient directoryClient =
        fileSystemClient.GetDirectoryClient(string.Join('/', directoryPath, subdirectoryName));

    return await directoryClient.RenameAsync(string.Join('/', directoryPath, subdirectoryNameNew));
}

次のコード例は、サブディレクトリをあるディレクトリから別のディレクトリに移動する方法を示しています。

public async Task<DataLakeDirectoryClient> MoveDirectory(
    DataLakeFileSystemClient fileSystemClient,
    string directoryPathFrom,
    string directoryPathTo,
    string subdirectoryName)
{
    DataLakeDirectoryClient directoryClient =
         fileSystemClient.GetDirectoryClient(string.Join('/', directoryPathFrom, subdirectoryName));

    return await directoryClient.RenameAsync(string.Join('/', directoryPathTo, subdirectoryName));
}

ファイルをディレクトリにアップロードする

次のメソッドを使用して、新規または既存のファイルにコンテンツをアップロードできます。

次のコード例は、UploadAsync メソッドを使用してローカル ファイルをディレクトリにアップロードする方法を示しています。

public async Task UploadFile(
    DataLakeDirectoryClient directoryClient,
    string fileName,
    string localPath)
{
    DataLakeFileClient fileClient = 
        directoryClient.GetFileClient(fileName);

    FileStream fileStream = File.OpenRead(localPath);

    await fileClient.UploadAsync(content: fileStream, overwrite: true);
}

このメソッドを使用してコンテンツを作成して新しいファイルにアップロードすることも、overwrite パラメーターを true に設定して既存のファイルを上書きすることもできます。

ファイルにデータを追加する

次のメソッドを使用して、ファイルに追加するデータをアップロードできます。

次のコード例は、これらの手順を使用してファイルの末尾にデータを追加する方法を示しています。

  • 操作しているファイル リソースを表す DataLakeFileClient オブジェクトを作成します。
  • DataLakeFileClient.AppendAsync メソッドを使用してファイルにデータをアップロードします。
  • DataLakeFileClient.FlushAsync メソッドを呼び出し、先にアップロード済みのデータをファイルに書き込むことで、アップロードを完了します。
public async Task AppendDataToFile(
    DataLakeDirectoryClient directoryClient,
    string fileName,
    Stream stream)
{
    DataLakeFileClient fileClient = 
        directoryClient.GetFileClient(fileName);

    long fileSize = fileClient.GetProperties().Value.ContentLength;

    await fileClient.AppendAsync(stream, offset: fileSize);

    await fileClient.FlushAsync(position: fileSize + stream.Length);
}

ディレクトリからダウンロードする

次のコード例は、これらの手順を使用して、ディレクトリからローカル ファイルへとファイルをダウンロードする方法を示しています。

  • ダウンロードしたいファイルを表す DataLakeFileClient インスタンスを作成します。
  • DataLakeFileClient.ReadAsync メソッドを使用した後に、戻り値を解析して Stream オブジェクトを取得します。 任意の .NET ファイル処理 API を使用して、ストリームからファイルにバイトを保存します。

この例では、BinaryReaderFileStream を使用してバイトをファイルに保存します。

public async Task DownloadFile(
    DataLakeDirectoryClient directoryClient,
    string fileName,
    string localPath)
{
    DataLakeFileClient fileClient =
        directoryClient.GetFileClient(fileName);

    Response<FileDownloadInfo> downloadResponse = await fileClient.ReadAsync();

    BinaryReader reader = new BinaryReader(downloadResponse.Value.Content);

    FileStream fileStream = File.OpenWrite(localPath);

    int bufferSize = 4096;

    byte[] buffer = new byte[bufferSize];

    int count;

    while ((count = reader.Read(buffer, 0, buffer.Length)) != 0)
    {
        fileStream.Write(buffer, 0, count);
    }

    await fileStream.FlushAsync();

    fileStream.Close();
}

ディレクトリの内容を一覧表示する

次のメソッドを使用し結果を列挙することで、ディレクトリのコンテンツを一覧表示できます。

結果内のパスの列挙は、値のフェッチ中にサービスに対して複数の要求を行う場合があります。

次のコード例では、ディレクトリにある各ファイルの名前を出力します。

public async Task ListFilesInDirectory(
    DataLakeFileSystemClient fileSystemClient,
    string directoryName)
{
    IAsyncEnumerator<PathItem> enumerator =
        fileSystemClient.GetPathsAsync(directoryName).GetAsyncEnumerator();

    await enumerator.MoveNextAsync();

    PathItem item = enumerator.Current;

    while (item != null)
    {
        Console.WriteLine(item.Name);

        if (!await enumerator.MoveNextAsync())
        {
            break;
        }

        item = enumerator.Current;
    }

}

ディレクトリを削除する

次のメソッドを使用して、ディレクトリを削除できます。

次のコード例は、ディレクトリを削除する方法を示しています。

public async Task DeleteDirectory(
    DataLakeFileSystemClient fileSystemClient,
    string directoryName)
{
    DataLakeDirectoryClient directoryClient =
        fileSystemClient.GetDirectoryClient(directoryName);

    await directoryClient.DeleteAsync();
}

論理的に削除されたディレクトリを復元する

Azure Storage クライアント ライブラリを使用して、論理的に削除されたディレクトリを復元できます。 DataLakeFileSystemClient インスタンスの削除されたパスを一覧表示するには、次のメソッドを使用します。

論理的に削除されたディレクトリを復元するには、次のメソッドを使用します。

次のコード例は、削除されたパスを一覧表示し、論理的に削除されたディレクトリを復元する方法を示しています。

public async Task RestoreDirectory(
    DataLakeFileSystemClient fileSystemClient,
    string directoryName)
{
    DataLakeDirectoryClient directoryClient =
        fileSystemClient.GetDirectoryClient(directoryName);

    // List deleted paths
    List<PathDeletedItem> deletedItems = new List<PathDeletedItem>();
    await foreach (PathDeletedItem deletedItem in fileSystemClient.GetDeletedPathsAsync(directoryName))
    {
        deletedItems.Add(deletedItem);
    }

    // Restore deleted directory
    Response<DataLakePathClient> restoreResponse = await fileSystemClient.UndeletePathAsync(
        deletedItems[0].Path,
        deletedItems[0].DeletionId);
}

論理的に削除された項目が含まれているディレクトリの名前を変更すると、それらの項目はディレクトリから切断されます。 それらの項目を復元するには、ディレクトリの名前を元の名前に戻すか、元のディレクトリ名を使用する別のディレクトリを作成する必要があります。 そうしないと、これらの論理的に削除された項目を復元しようとしたときにエラーが発生します。

ディレクトリ用のユーザー委任 SAS を作成する

このセクションのコード例を使用するには、次の using ディレクティブを追加します。

using Azure.Storage.Sas;

次のコード例は、階層型名前空間がストレージ アカウントに対して有効のときに、ディレクトリ用のユーザー委任 SAS を生成する方法を示しています。

async static Task<Uri> GetUserDelegationSasDirectory(DataLakeDirectoryClient directoryClient)
{
    try
    {
        // Get service endpoint from the directory URI.
        DataLakeUriBuilder dataLakeServiceUri = new DataLakeUriBuilder(directoryClient.Uri)
        {
            FileSystemName = null,
            DirectoryOrFilePath = null
        };

        // Get service client.
        DataLakeServiceClient dataLakeServiceClient =
            new DataLakeServiceClient(dataLakeServiceUri.ToUri(),
                                      new DefaultAzureCredential());

        // Get a user delegation key that's valid for seven days.
        // You can use the key to generate any number of shared access signatures 
        // over the lifetime of the key.
        Azure.Storage.Files.DataLake.Models.UserDelegationKey userDelegationKey =
            await dataLakeServiceClient.GetUserDelegationKeyAsync(DateTimeOffset.UtcNow,
                                                                  DateTimeOffset.UtcNow.AddDays(7));

        // Create a SAS token that's valid for seven days.
        DataLakeSasBuilder sasBuilder = new DataLakeSasBuilder()
        {
            // Specify the file system name and path, and indicate that
            // the client object points to a directory.
            FileSystemName = directoryClient.FileSystemName,
            Resource = "d",
            IsDirectory = true,
            Path = directoryClient.Path,
            ExpiresOn = DateTimeOffset.UtcNow.AddDays(7)
        };

        // Specify racwl permissions for the SAS.
        sasBuilder.SetPermissions(
            DataLakeSasPermissions.Read |
            DataLakeSasPermissions.Add |
            DataLakeSasPermissions.Create |
            DataLakeSasPermissions.Write |
            DataLakeSasPermissions.List
            );

        // Construct the full URI, including the SAS token.
        DataLakeUriBuilder fullUri = new DataLakeUriBuilder(directoryClient.Uri)
        {
            Sas = sasBuilder.ToSasQueryParameters(userDelegationKey,
                                                  dataLakeServiceClient.AccountName)
        };

        Console.WriteLine("Directory user delegation SAS URI: {0}", fullUri);
        Console.WriteLine();
        return fullUri.ToUri();
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
        throw;
    }
}

次の例では、前の例で作成されたユーザー委任 SAS を、シミュレートされたクライアント アプリケーションからテストします。 SAS が有効であれば、クライアント アプリケーションでこのディレクトリに対するファイル パスの一覧を表示することができます。 SAS が無効な場合 (たとえば、SAS の有効期限が切れている場合)、Storage サービスによってエラー コード 403 (禁止) が返されます。

private static async Task ListFilesPathsWithDirectorySasAsync(Uri sasUri)
{
    // Try performing an operation using the directory SAS provided.

    // Create a directory client object for listing operations.
    DataLakeDirectoryClient dataLakeDirectoryClient = new DataLakeDirectoryClient(sasUri);

    // List file paths in the directory.
    try
    {
        // Call the listing operation and return pages of the specified size.
        var resultSegment = dataLakeDirectoryClient.GetPathsAsync(false, false).AsPages();

        // Enumerate the file paths returned with each page.
        await foreach (Page<PathItem> pathPage in resultSegment)
        {
            foreach (PathItem pathItem in pathPage.Values)
            {
                Console.WriteLine("File name: {0}", pathItem.Name);
            }
            Console.WriteLine();
        }

        Console.WriteLine();
        Console.WriteLine("Directory listing operation succeeded for SAS {0}", sasUri);
    }
    catch (RequestFailedException e)
    {
        // Check for a 403 (Forbidden) error. If the SAS is invalid, 
        // Azure Storage returns this error.
        if (e.Status == 403)
        {
            Console.WriteLine("Directory listing operation failed for SAS {0}", sasUri);
            Console.WriteLine("Additional error information: " + e.Message);
            Console.WriteLine();
        }
        else
        {
            Console.WriteLine(e.Message);
            Console.ReadLine();
            throw;
        }
    }
}

ユーザー委任 SAS の作成に関する詳細については、.NET を使用したユーザー委任 SAS の作成に関するページを参照してください。

ディレクトリのサービス SAS を作成する

階層型名前空間が有効になっているストレージ アカウントでは、ディレクトリのサービス SAS を作成できます。 サービス SAS を作成するには、Azure.Storage.Files.DataLake パッケージのバージョン 12.5.0 以降がインストールされていることを確認します。

次の例は、ディレクトリのサービス SAS を作成する方法を示しています。

private static Uri GetServiceSasUriForDirectory(DataLakeDirectoryClient directoryClient,
                                          string storedPolicyName = null)
{
    if (directoryClient.CanGenerateSasUri)
    {
        // Create a SAS token that's valid for one hour.
        DataLakeSasBuilder sasBuilder = new DataLakeSasBuilder()
        {
            // Specify the file system name, the path, and indicate that
            // the client object points to a directory.
            FileSystemName = directoryClient.FileSystemName,
            Resource = "d",
            IsDirectory = true,
            Path = directoryClient.Path,
        };

        // If no stored access policy is specified, create the policy
        // by specifying expiry and permissions.
        if (storedPolicyName == null)
        {
            sasBuilder.ExpiresOn = DateTimeOffset.UtcNow.AddHours(1);
            sasBuilder.SetPermissions(DataLakeSasPermissions.Read |
                DataLakeSasPermissions.Write |
                DataLakeSasPermissions.List);
        }
        else
        {
            sasBuilder.Identifier = storedPolicyName;
        }

        // Get the SAS URI for the specified directory.
        Uri sasUri = directoryClient.GenerateSasUri(sasBuilder);
        Console.WriteLine("SAS URI for ADLS directory is: {0}", sasUri);
        Console.WriteLine();

        return sasUri;
    }
    else
    {
        Console.WriteLine(@"DataLakeDirectoryClient must be authorized with Shared Key 
                          credentials to create a service SAS.");
        return null;
    }
}

サービス SAS の作成に関する詳細については、.NET を使用したサービス SAS の作成に関するページを参照してください。

関連項目