Windows Azureのblobストレージにあるテキストファイルから1行ずつ読み取る方法はありますか?
ありがとう
はい、ストリームでこれを行うことができます。ファイル全体をプルする必要はありませんが、全体をプルしたい場合があるため、(答えの...問題のファイルではなく)最後まで読んでください。とにかくファイル。
コードは次のとおりです。
StorageCredentialsAccountAndKey credentials = new StorageCredentialsAccountAndKey(
"YourStorageAccountName",
"YourStorageAccountKey"
);
CloudStorageAccount account = new CloudStorageAccount(credentials, true);
CloudBlobClient client = new CloudBlobClient(account.BlobEndpoint.AbsoluteUri, account.Credentials);
CloudBlobContainer container = client.GetContainerReference("test");
CloudBlob blob = container.GetBlobReference("CloudBlob.txt");
using (var stream = blob.OpenRead())
{
using (StreamReader reader = new StreamReader(stream))
{
while (!reader.EndOfStream)
{
Console.WriteLine(reader.ReadLine());
}
}
}
CloudBlob.txtというテキストファイルをtestというコンテナにアップロードしました。ファイルのサイズは約1.37MBでした(実際には、同じファイルに6〜7回コピーされたGitHubのCloudBlob.csファイルを使用しました)。私はこれをBlockBlobで試してみました。これは、テキストファイルについて話しているので、おそらくあなたが扱っているものです。
これにより、通常どおりBLOBへの参照が取得されます。次に、CloudBlobオブジェクトからOpenRead()メソッドを呼び出します。これにより、BlobStreamが返され、StreamReaderでラップしてReadLineメソッドを取得できます。私はこれでフィドラーを実行し、ファイルを完成させるために追加のブロックを3回取得するために呼び出されることに気づきました。BlobStreamにはいくつかのプロパティがあるように見えます。そのため、必要な読み取り量を微調整するために使用できますが、私はそれらを調整しようとしませんでした。ある参考資料によると、再試行ポリシーは最後の読み取りレベルでも機能するため、最後に失敗した要求だけで、すべてを再読み取りしようとはしません。ここで引用:
最後に、DownloadToFile / ByteArray / Stream / Text()メソッドは、ダウンロード全体を1回のストリーミング取得で実行します。CloudBlob.OpenRead()メソッドを使用する場合、BlobReadStream抽象化を利用して、消費されるときに一度に1ブロックずつblobをダウンロードします。接続エラーが発生した場合は、その1つのブロックのみを再ダウンロードする必要があります(構成されたRetryPolicyに従って)。また、クライアントが大量のデータをローカルにキャッシュする必要がない場合があるため、これはパフォーマンスの向上に役立つ可能性があります。大きなBLOBの場合、これは非常に役立ちますが、サービスに対してより多くの全体的なトランザクションを実行することに注意してください。-ジョージャルディーノ
これにより、ストレージアカウントに対するトランザクションの数が全体的に増えるという点で、Joeが指摘している注意に注意することが重要だと思います。 ただし、要件によっては、これが探しているオプションである場合があります。
これらが大規模なファイルであり、これを大量に実行している場合は、多くのトランザクションが発生する可能性があります(ただし、BlobStreamのプロパティを微調整して、一度に取得するブロックの量を増やすことができるかどうかなどを確認できます)。CloudBlobでDownloadFromStreamを実行して(コンテンツ全体をプルダウンします)、上記と同じ方法でそのストリームから読み取ることは、依然として理にかなっている場合があります。
唯一の本当の違いは、1つは一度に小さなチャンクをプルし、もう1つはファイル全体をすぐにプルすることです。それぞれに長所と短所があり、これらのファイルの大きさや、ファイルの読み取りの途中で停止する予定があるかどうかに大きく依存します(「ええ、探していた文字列が見つかりました!」など)。または、とにかくファイル全体を読み取ることを計画している場合(たとえば、ファイル全体を処理しているため)、ファイル全体をプルすることを計画している場合は、DownloadToStreamを使用して、それをStreamReaderでラップします。
注:1.7SDKでこれを試しました。これらのオプションが導入されたSDKがわかりません。
質問に直接答えるには、最初にblobをローカルにダウンロードするコードを記述してから、その中のコンテンツを読み取る必要があります。これは主に、blobにピークを迎え、その内容を途中で読み取ることができないためです。Windows Azureテーブルストレージを使用したことがある場合は、テーブル内の特定のコンテンツを確実に読み取ることができます。
テキストファイルはblobであり、Azure Blobストレージにあるため、実際に必要なのは、blobをローカルに(ローカルblobまたはメモリストリームとして)ダウンロードしてから、その中のコンテンツを読み取ることです。アップロードしたBLOBのタイプに応じて、BLOBを完全または部分的にダウンロードする必要があります。ページBLOBを使用すると、特定のサイズのコンテンツをローカルにダウンロードして処理できます。この点に関して、ブロックブロブとページブロブの違いについて知っておくと便利です。
これは、ファイルを1行ずつフェッチするために使用したコードです。ファイルはAzureStorageに保存されました。BLOBサービスではなく、ファイルサービスが使用されました。
//https://docs.microsoft.com/en-us/azure/storage/storage-dotnet-how-to-use-files
//https://<storage account>.file.core.windows.net/<share>/<directory/directories>/<file>
public void ReadAzureFile() {
CloudStorageAccount account = CloudStorageAccount.Parse(
CloudConfigurationManager.GetSetting("StorageConnectionString"));
CloudFileClient fileClient = account.CreateCloudFileClient();
CloudFileShare share = fileClient.GetShareReference("jiosongdetails");
if (share.Exists()) {
CloudFileDirectory rootDir = share.GetRootDirectoryReference();
CloudFile file = rootDir.GetFileReference("songdetails(1).csv");
if (file.Exists()) {
using(var stream = file.OpenRead()) {
using(StreamReader reader = new StreamReader(stream)) {
while (!reader.EndOfStream) {
Console.WriteLine(reader.ReadLine());
}
}
}
}
}
誰かがここにいることに気付いた場合に備えて、Python SDK for Azure Blob Storage(v12)には、download_blob()
offsetとlengthの2つのパラメーターを受け入れる単純なメソッドがあります。
Pythonを使用して、私の目標は、BLOBストレージ内の(多くの)ファイルからヘッダー行を抽出することでした。すべてのファイルの場所を知っていたので、blobクライアントのリストを作成しました(ファイルごとに1つ)。次に、リストを繰り返して、download_blobメソッドを実行しました。
Blobクライアントを(接続文字列を介して直接、またはメソッドを使用して)作成したらBlobServiceClient.get_blob_client()
、最初の(たとえば)4kバイトをダウンロードして長いヘッダー行をカバーし、行末文字('\ n)を使用してテキストを分割します。 ')。結果のリストの最初の要素はヘッダー行になります。私の作業コード(単一のファイルのみ)は次のようになりました:
from azure.storage.blob import BlobServiceClient
MAX_LINE_SIZE = 4096 # You can change this..
my_blob_service_client = BlobServiceClient(account_url=my_url, credential=my_shared_access_key)
my_blob_client = my_blob_service_client.get_blob_client('my-container','my_file.csv')
file_size = my_blob_client.size
offset = 0
次に、最初の行末のバイトオフセットをカウントし、次のMAX_LINE_SIZEバイトを取得することにより、テキストを1行ずつダウンロードするループを記述できます。最適な効率を得るには、線の最大長を知っておくと便利ですが、知らない場合は、十分に長い長さを推測してください。
while offset < file_size - 1:
next_text_block = my_blob_client.download_blob(offset=offset, length=MAX_LINE_SIZE)
line = next_text_block.split('\n')[0]
offset = len(line) + 1
# Do something with your line..
お役に立てば幸いです。ここでの明らかなトレードオフはネットワークのオーバーヘッドであり、テキスト行の各呼び出しは高速ではありませんが、行ごとに読み取るという要件を満たしています。