从Windows Azure中的blob存储逐行读取

时间:2012-10-22 21:26:43

标签: windows azure

有没有办法从windows Azure中的blob存储中的文本文件中逐行读取?

谢谢

4 个答案:

答案 0 :(得分:33)

是的,您可以使用流来执行此操作,并且它不一定要求您提取整个文件,但请仔细阅读(答案的答案...而不是相关文件),因为您可能希望无论如何拉完整个文件。

以下是代码:

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方法。我用它运行了小提琴手并注意到它最终调用了三次以获得额外的块来完成文件。看起来BlobStream有一些属性,你可以使用它来调整你必须做的读数,但我没有尝试调整它们。根据{{​​3}},我发现重试策略也适用于最后一个读取级别,所以它不会再次尝试重新读取整个内容,只是最后一次失败的请求。引用这里:

  

最后,DownloadToFile / ByteArray / Stream / Text()方法在单个流式传输中执行整个下载。如果您使用CloudBlob.OpenRead()方法,它将使用BlobReadStream抽象,它将在消耗时一次下载blob一个块。如果发生连接错误,则只需要重新下载一个块(根据配置的RetryPolicy)。此外,这可能有助于提高性能,因为客户端可能不需要在本地缓存大量数据。对于大型blob,这可能会有很大帮助,但请注意,您将针对该服务执行更多数量的整体事务。 - Joe Giardino

我认为重要的是要注意Joe提出的警告,这会导致针对您的存储帐户的整体交易数量增加。但是,根据您的要求,这可能仍然是您正在寻找的选项。

如果这些是大量文件并且您正在做很多这样的事情,那么它可以进行很多很多事务(尽管您可以看看是否可以在BlobStream上调整属性以增加一次检索的块数量等) 。在CloudBlob上执行DownloadFromStream(它会将整个内容拉下来)仍然有意义,然后以与上面相同的方式从该流中读取。

唯一真正的区别是,一个是一次拉小块,另一个是立即拉出整个文件。每个都有利弊,这在很大程度上取决于这些文件的大小,如果你打算在阅读文件的中间某一点停止(例如“是的,我发现了我正在搜索的字符串!)或者如果您打算一直阅读整个文件。如果您计划拉动整个文件,无论如何(因为您正在处理整个文件),那么只需使用DownloadToStream并将其包装在StreamReader中。

注意:我尝试使用1.7 SDK。我不确定引入了哪些SDK这些选项。

答案 1 :(得分:1)

要直接回答您的问题,您必须先编写代码,先在本地下载blob,然后再读取其中的内容。这主要是因为你不能只是在一个blob中达到峰值并在中间读取它的内容。如果您使用过Windows Azure表存储,则可以阅读表中的特定内容。

由于您的文本文件是Blob并位于Azure Blob存储中,因此您真正需要的是在本地下载blob(作为本地blob或内存流),然后读取其中的内容。您必须完全或部分下载blob,具体取决于您上传的blob类型。使用Page blobs,您可以在本地下载特定大小的内容并进行处理。在这方面了解difference between block and page blob会很棒。

答案 2 :(得分:1)

这是我用来逐行获取文件的代码。该文件存储在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());
                }
                }
            }
    }
}

答案 3 :(得分:1)

万一有人发现自己在这里,用于Azure Blob存储(v12)的Python SDK现在具有简单的download_blob()方法,该方法接受两个参数-offset和length。

使用Python,我的目标是从blob存储中的(许多)文件中提取标题行。我知道所有文件的位置,所以我创建了一个Blob客户端列表-每个文件一个。然后,我遍历列表并运行download_blob方法。

一旦创建了Blob客户端(使用directly via connection string或使用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..

希望有帮助。显而易见的折衷方案是网络开销,每次调用一行文本都不很快,但是可以满足您逐行阅读的要求。