2017-08-11 37 views
0

在将Azure Blob中的CSV文件解析为流时,TextFieldParser将始终直接到达EndOfData,而不会读取任何数据。相同的代码,但路径相同的物理文件,而不是流的作品。使用TextFieldParser从流中解析CSV始终达到EndOfData

Dim storageAccount As CloudStorageAccount = CloudStorageAccount.Parse(AzureStorageConnection) 
    Dim blobClient As CloudBlobClient = storageAccount.CreateCloudBlobClient() 
    Dim BlobList As IEnumerable(Of CloudBlockBlob) = blobClient.GetContainerReference("containername").ListBlobs().OfType(Of CloudBlockBlob) 

    For Each blb In BlobList 
     Dim myList As New List(Of MyBusinessObject) 

     Using memoryStream = New MemoryStream() 
      blb.DownloadToStream(memoryStream) 

      Using Reader As New FileIO.TextFieldParser(memoryStream) 
       Reader.TextFieldType = FileIO.FieldType.FixedWidth 
       Reader.SetFieldWidths(2, 9, 10) 
       Dim currentRow As String() 
       While Not Reader.EndOfData 
        Try 
         currentRow = Reader.ReadFields() 
         myList.Add(New GsmXFileRow() With { 
         ' code to read currentRow and add elements to myList 
         }) 
        Catch ex As FileIO.MalformedLineException 
        End Try 
       End While 
      End Using 
     End Using 
    Next 

我也试图MemoryStream转换为TextReader

Dim myTextReader As TextReader = New StreamReader(memoryStream) 

,然后传递到myTextReaderTextFieldParser,但这也不管用。

Using Reader As New FileIO.TextFieldParser(myTextReader)

+0

你已经把一个断点,并检查了你的'memoryStream'有你期望的数据?另外...我看到你的Try/Catch块正在吞噬捕获到的异常。你有没有Try/Catch运行代码,看是否有错误被抛出?我怀疑将字节转换为字符串的编码问题导致MalformedLineExceptions您永远不会看到。 –

+0

@JoelCoehoorn是的。 'Length'属性的值等于文件大小。 '位置'属性具有相同的值,表明流位于其末尾。对于异常,代码从不在'While'内执行,因为'Reader.EndOfData'总是'True'。 – Megrez7

+0

“'位置属性具有相同的值'”。那就是你的问题。它已经读到蒸汽的尽头了。你需要重新开始。当你这样做时,请检查我的答案,因为你可能也需要解决编码问题。 –

回答

1

我看到这一点:

长度属性的值等于文件大小

这:

“Position`酒店有相同的值

这意味着在循环开始时,MemoryStream已经进入流结束。只需将Position设置回0,你应该处在一个更好的位置。

但是,这里也可能存在另一个问题。该流数据是二进制的,有一些未知的编码。 TextFieldParser想与Text一起工作。您需要一种方法来提供有关使用哪种编码的信息。

在这种情况下,我推荐StreamReader。这种类型的TextReader继承,这样你就可以与TextFieldParser使用它:

Dim storageAccount As CloudStorageAccount = CloudStorageAccount.Parse(AzureStorageConnection) 
Dim blobClient As CloudBlobClient = storageAccount.CreateCloudBlobClient() 
Dim BlobList As IEnumerable(Of CloudBlockBlob) = blobClient.GetContainerReference("containername").ListBlobs().OfType(Of CloudBlockBlob) 

Dim myList As New List(Of MyBusinessObject) 
For Each blb In BlobList 

    'Several constructor overloads allow you to specify the encoding here 
    Using blobData As New StreamReader(New MemoryStream()) 
     blb.DownloadToStream(blobData.Stream) 

     'Fix the position problem 
     blobData.Stream.Position = 0 

     Using Reader As New FileIO.TextFieldParser(blogData) 
      Reader.TextFieldType = FileIO.FieldType.FixedWidth 
      Reader.SetFieldWidths(2, 9, 10) 
      Dim currentRow As String() = Reader.ReadFields() 
      While Not Reader.EndOfData 
       Try 
        myList.Add(New GsmXFileRow() With { 
         ' code to read currentRow and add elements to myList 
        }) 
        currentRow = Reader.ReadFields() 
       Catch ex As FileIO.MalformedLineException 
       End Try 
      End While 
     End Using 
    End Using 
Next 
+0

'使用rdr作为新的StreamReader(rdr)'???我想你在你的例子中留下了一部分思路。另外'TextFieldParser'可以配置一个默认的编码器以及尝试和检测编码。 – TnTinMn

+0

@TnTinMn对不起......你在编辑之间发现了我。再看一遍。 –

+1

我认为你最好在填充'MemoryStream'之前将其传递给'StreamReader',因为SR的构造器链会检测流上的编码;如果它是空的,可能会有问题。但是,由于TextFieldParser可以接受Stream和可选编码来构建自己的内部StreamReader,因此我不明白“StreamReader”的必要性, – TnTinMn