2017-03-08 51 views
0

我試圖從soap API使用Python中的流式響應,並輸出一個CSV文件。響應輸出一個以64爲底的字符串,我不知道該怎麼辦。此外,api文檔還說,必須將響應讀取到逐個緩衝區的目標緩衝區。將Python解碼流爲CSV Byte(從C#代碼翻譯)

下面是C#代碼是由API的文檔提供:

byte[] buffer = new byte[4000]; 
bool endOfStream = false; 
int bytesRead = 0; 
using (FileStream localFileStream = new FileStream(destinationPath, FileMode.Create, FileAccess.Write)) 
{ 
    using (Stream remoteStream = client.DownloadFile(jobId)) 
    { 
    while (!endOfStream) 
    { 
     bytesRead = remoteStream.Read(buffer, 0, buffer.Length); 
     if (bytesRead > 0) 
     { 
       localFileStream.Write(buffer, 0, bytesRead); 
       totalBytes += bytesRead; 
     } 
     else 
     { 
       endOfStream = true; 
     } 
     } 
    } 
} 

我已經嘗試了許多不同的事情來得到這個流爲可讀的CSV文件,但非工作過。

with open('test.csv', 'w') as f: f.write(FileString) 

返回與BASE64字符串CSV分佈在多個線路

這裏是我的最新嘗試:

with open('csvfile13.csv', 'wb') as csvfile: 
      FileString = client.service.DownloadFile(yyy.JobId, False) 
      stream = io.BytesIO(str(FileString)) 
      with open(stream,"rt",4000) as readstream: 
      csvfile.write(readstream) 

這會產生錯誤:

TypeError: coercing to Unicode: need string or buffer, _io.BytesIO

任何幫助不勝感激,即使它只是指向正確的方向。即使我沒有完全解決問題,我也會確保把獎勵分給誰最有幫助的人!

我也問過類似這樣的一些問題,但我還沒有找到工作的完全的答案: What is the Python equivalent to FileStream in C#?

Write Streamed Response(file-like object) to CSV file Byte by Byte in Python

How to replicate C# 'byte' and 'Write' in Python

讓我知道如果你需要進一步澄清!

更新: 我試圖print(base64.b64decode(str(FileString)))

這給了我一整頁webdings像

]�P�O�J��Y��KW �

我也曾嘗試

for data in client.service.DownloadFile(yyy.JobId, False): 
    print data 

但這只是通過輸出字符循環通過像任何其他字符串characater。

我也設法通過整個字符串解碼像\命苦\ x97_D \ xfb的(而不是實際的字節,只是類似的格式)的字節長的字符串,但我不知道如何使之可讀。

編輯:糾正樣品蟒蛇的輸出,增加了更多的示例代碼,格式化

+0

什麼is'type(FileString)''中= FileString client.service.DownloadFile(yyy.JobId,FALSE)'? ??另外,你使用的是什麼版本的Python 2? –

+0

class'suds.sax.text.Text' – jvk777

+0

我正在使用Python 2.7.12 | Anaconda 4.2.0 – jvk777

回答

1

這聽起來像你需要使用的base64模塊下載的數據進行解碼。

這可能是這麼簡單:

with open(destinationPath, 'w') as localFile: 
    remoteFile = client.service.DownloadFile(yyy.JobId, False) 
    remoteData = str(remoteFile).decode('base64') 
    localFile.write(remoteData) 

我建議你下破的問題,並確定你在每個階段的數據。例如,你究竟從client.service.DownloadFile返回了什麼?

解碼您的樣本下載的數據(在評論中給出):

'UEsYAItH7brgsgPutAG\AoAYYAYa='.decode('base64') 

'PK\x18\x00\x8bG\xed\xba\xe0\xb2\x03\xee\xb4\x01\x80\xa0\x06\x18\x01\x86' 

這看起來很像一個ZIP file頭。我建議你重命名文件.zip並打開它來調查。

如果remoteData是一個ZIP類似下面的東西應該提取和寫入您的CSV。

import io 
import zipfile 

remoteFile = client.service.DownloadFile(yyy.JobId, False) 
remoteData = str(remoteFile).decode('base64') 

zipStream = io.BytesIO(remoteData) 
z = zipfile.ZipFile(zipStream, 'r') 
csvData = z.read(z.infolist()[0]) 

with open(destinationPath, 'w') as localFile: 
    localFile.write(csvData) 

注:BASE64可以有關於填充和備選字符映射一些變化,但一旦你可以看到數據應該是相當清楚你需要什麼。當然,仔細閱讀您的SOAP接口上的文檔。

+0

感謝您的迴應Mike。當我嘗試你的第一批代碼時,它給了我錯誤** AttributeError:'文本'對象沒有'readline'**屬性,當我做第二批時,它只是給我編碼的字符串。 – jvk777

+0

我已經設法通過解碼整個字符串來獲取單個字節,如下所示:** \ xbc \ x97_D \ xfb **,但我不知道如何使其可讀,並且我懷疑它必須在大塊不知何故。 – jvk777

+0

聽起來像DownloadFile將整個文件作爲BASE64編碼字符串返回。我的第二個代碼段中有一個錯字,抱歉。它應該閱讀'base64.b64decode(data)'看看[這個問題](http://stackoverflow.com/questions/3866316/whats-the-difference-between-utf8-utf16-and-base64-in-條件方面的編碼)。嘗試'localFile.write(base64.b64decode(remoteFile))' –

0

Are you sure FileString is a Base64 string?根據源代碼heresuds.sax.text.Text是Unicode的一個子類。你可以像寫普通字符串一樣將它寫到一個文件中,但是無論你用什麼來讀取文件中的數據,都可能會破壞它,除非它是UTF-8編碼的。

您可以嘗試使用io.open寫你Text對象爲UTF-8編碼的文件:記

import io 
with io.open('/path/to/my/file.txt', 'w', encoding='utf_8') as f: 
    f.write(FileString) 

熊,控制檯或文本編輯器可能顯示患非ASCII字符,但沒有按」這意味着他們沒有正確編碼。檢查他們的另一種方式是在Python交互shell打開文件備份:

import io 
with io.open('/path/to/my/file.txt', 'r', encoding='utf_8') as f: 
    next(f) # displays the representation of the first line of the file as a Unicode object 

在Python 3,你甚至可以使用內置的csv解析文件,但是在Python 2,你」會需要pip install backports.csv因爲內置模塊不使用Unicode工作對象:

from backports import csv 
import io 
with io.open('/path/to/my/file.txt', 'r', encoding='utf_8') as f: 
    r = csv.reader(f) 
    next(r) # displays the representation of the first line of the file as a list of Unicode objects (each value separated) 
+0

謝謝賈裏德,我相信你是在正確的軌道上,但是當我運行'從backports進口csv io.open('/ path/to/my/file.txt','r',encoding = 'utf_8')as f: r = csv.reader(f) next(r)''我得到的行仍然編碼在我認爲是base64的文本 – jvk777

+0

當我運行與base64.b64decode (下一個(R))。我以「\ xe5 \ xd1 \」的形式獲得長字節的字節數 – jvk777

+0

您能否給出一個例子,包括a)您期望看到的內容和b)您實際看到的內容?你能解釋爲什麼你期望看到它嗎? – Jared