簡體   English   中英

從 Windows Azure 中的 blob 存儲逐行讀取

[英]Reading line by line from blob Storage in Windows Azure

有沒有辦法從 Windows Azure 的 blob 存儲中的文本文件中逐行讀取?

謝謝

是的,你可以用流來做到這一點,它不一定要求你拉整個文件,但請閱讀到最后(答案......不是有問題的文件),因為你可能想拉整個無論如何文件。

這是代碼:

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.37 MB(我實際上使用了從 GitHub 復制到同一個文件中的 CloudBlob.cs 文件六七次)。 我用 BlockBlob 進行了嘗試,這很可能是您要處理的內容,因為您正在談論的是文本文件。

這會像往常一樣獲取對 BLOB 的引用,然后我調用 CloudBlob 對象的OpenRead () 方法,該方法返回一個 BlobStream,然后您可以將其包裝在 StreamReader 中以獲得 ReadLine 方法。 我用這個運行 fiddler 並注意到它最終調用了三次額外的塊來完成文件。 看起來 BlobStream 有一些屬性,因此您可以使用這些屬性來調整您必須執行的提前讀取量,但我沒有嘗試調整它們。 根據一個參考,我發現重試策略也適用於最后一次讀取級別,因此它不會嘗試再次重新讀取整個內容,只會嘗試重新讀取失敗的最后一個請求。 這里引用:

最后,DownloadToFile/ByteArray/Stream/Text() 方法在單個流式獲取中執行整個下載。 如果您使用 CloudBlob.OpenRead() 方法,它將利用 BlobReadStream 抽象,該抽象將在使用 blob 時一次下載一個塊。 如果發生連接錯誤,則僅需要重新下載該塊(根據配置的 RetryPolicy)。 此外,這可能有助於提高性能,因為客戶端可能不需要在本地緩存大量數據。 對於大型 blob,這可能會大有幫助,但請注意,您將針對服務執行更多的整體事務。 ——喬·賈爾迪諾

我認為重要的是要注意 Joe 指出的警告,因為這將導致針對您的存儲帳戶的整體交易數量增加。 但是,根據您的要求,這可能仍然是您正在尋找的選項。

如果這些是大文件並且您做了很多這樣的事情,那么它可能會有很多很多事務(盡管您可以查看是否可以調整 BlobStream 上的屬性以增加一次檢索的塊數量等)。 在 CloudBlob 上執行 DownloadFromStream 可能仍然有意義(這將拉下整個內容),然后以與我上面相同的方式從該流中讀取。

唯一真正的區別是,一個是一次拉取較小的塊,另一個是立即拉取整個文件。 每個都有優點和缺點,這在很大程度上取決於這些文件的大小,以及您是否打算在讀取文件的過程中停下來(例如“是的,我找到了我正在搜索的字符串!)或者,如果您打算無論如何都要讀取整個文件。如果您打算無論如何都要拉取整個文件(例如,因為您正在處理整個文件),那么只需使用 DownloadToStream 並將其包裝在 StreamReader 中。

注意:我用 1.7 SDK 試過這個。 我不確定這些選項是哪個 SDK 引入的。

要直接回答您的問題,您必須先編寫代碼將 blob 下載到本地,然后再讀取其中的內容。 這主要是因為您不能只是進入一個 blob 並在中間讀取其內容。 如果您使用過 Windows Azure 表存儲,您肯定可以閱讀表中的具體內容。

由於您的文本文件是一個 blob 並且位於 Azure Blob 存儲中,您真正需要的是在本地下載 blob(作為本地 blob 或內存流),然后讀取其中的內容。 您必須完整或部分下載 blob,具體取決於您上傳的 blob 類型。 使用頁面 blob,您可以在本地下載特定大小的內容並進行處理。 在這方面了解塊和頁 blob 之間的區別會很棒。

這是我用來逐行獲取文件的代碼。 該文件存儲在 Azure 存儲中。 使用了文件服務而不是 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());
                }
                }
            }
    }
}

萬一有人發現自己在這里,Azure Blob 存儲 (v12) 的 Python SDK 現在有簡單的download_blob()方法,它接受兩個參數 - 偏移量和長度。

使用 Python,我的目標是從 blob 存儲中的(許多)文件中提取標題行。 我知道所有文件的位置,所以我創建了一個 blob 客戶端列表 - 每個文件一個。 然后,我遍歷列表並運行 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 字節。 為了獲得最佳效率,最好知道一條線的最大長度,但如果不知道,請猜測一個足夠大的長度。

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..

希望有幫助。 這里明顯的權衡是網絡開銷,每次調用一行文本並不快,但它達到了你逐行閱讀的要求。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM