2012-01-27 79 views
3

我有一個查詢數據庫並返回JSON的WCF4 REST服務。儘管我很難返回字符串,但有些用戶希望做出非常大的查詢。例如,我需要返回一個500M JSON字符串(所有數據都是ASCII文本),但是當我嘗試從.NET的本機UTF-16轉換字符串時,我遇到了OutOfMemoryException。這是我正在做的一個簡潔的樣本。將大字符串轉換爲UTF-8

[WebInvoke(UriTemplate="/RunQuery", ResponseFormat=WebMessageFormat.Json)] 
public Stream RunQuery() { 
    // Perform query and return serialized json string (~500 million ASCII characters) 
    string json = DoQuery(HttpContext.Current.Request.Form); 
    // Set output charset 
    WebOperationContext.Current.OutgoingResponse.ContentType = "application/json; charset=utf-8"; 
    // Convert UTF-16 string to UTF-8 (OutOfMemoryException) 
    byte jsonBytes[] = System.Text.Encoding.UTF8.GetBytes(json) 
    // Send UTF-8 string, without BOM 
    return new MemoryStream(jsonBytes); 
} 

如果我把JSON低於200M左右,它纔有效。當它運行時,我看到IIS進程的內存使用量逐漸增加,然後爆炸到2.8G,並在此時死亡。堆棧跟蹤報告它發生在System.String.ToCharArray。我嘗試了將字符串分塊來構建字節數組的變體,但似乎沒有任何工作。任何想法如何我可以發送這些數據而不用炸燬?

+2

500M JSON?哎喲。難道你不能將數據分成頁面嗎? – 2012-01-27 20:33:40

+0

只是一個猜測:你可以嘗試寫入響應數據到一個臨時文件塊,然後返回一個打開的流爲臨時文件? (最好你應該重新構造DoQuery(),以便它支持將其結果寫入輸出流而不是返回流。如果不需要,你實際上不應該緩存整個兆字節的數據。) – millimoose 2012-01-27 20:34:53

+0

或將數據流傳回客戶端.... – Polity 2012-01-27 20:35:39

回答

0

您可以通過編寫自己的stream實現來解決此問題,該實現將輸入轉換爲實時轉換爲utf8。

您應該可以通過提取輸入字符串的一部分,並將它們逐塊轉換爲utf 8來實現。

請記住,字節數並非與字符數相同,除非您永遠不會發送任何類型的國際字符。

0

如果您必須返回流 - 使用文件流或至少預先分配MemoryStream空間。

如果你堅持使用500MB的字符串:

  • 使用64位機和64位進程。 x86進程不太可能成功分配2個這樣大小的內存。請注意,即使您使用64位進程,CLR也會限制大約2Gb的「單塊分配」大小,從而使1Gb字符串不太可能適合內存。因此,在接近500Mb的某個點 - 1Gb切換到64位將不再有幫助。

  • 使用作家 - 他們可以輕鬆地(即http://msdn.microsoft.com/en-us/library/3aadshsx.aspx)直接編碼到輸出,同時編寫JSON它。作爲附加建議 - 甚至不要創建JSON字符串,而是將輸出寫入Writer。

  • 如果你知道你的字符串只有ASCII碼 - 通過寫入流來欺騙你自己將每個字符轉換爲字節。

+0

不幸的是,我的服務必須是32位才能使用Oracle odp.net驅動程序(Oracle.DataAccess.dll)這似乎沒有64位的味道。 當我做一個「新的MemoryStream(500000000)」它死了,可能是因爲我有一個500000000字符串坐在內存中。這確實繞過了整個字節數組,這有所幫助。 JSON由JavaScriptSerializer生成,它使我可以選擇String或StringBuilder作爲輸出。我希望我可以簡單地返回我的序列化對象,但它使用嵌套字典... – Vimm 2012-01-27 23:23:51

+0

我看到 - 你必須非常小心,在32位過程中獲得大量結果,即2個這樣的請求同時將會終止你的服務器。考慮使用json.net序列化程序(json.codeplex.com),因爲它爲您提供了比內置的更高的靈活性 - http://james.newtonking.com/projects/json/help/html/T_Newtonsoft_Json_JsonTextWriter.htm。否則,我看到的唯一選擇是編寫自己的JSON序列化並直接寫入響應流... – 2012-01-27 23:55:50