當訪問WebSerivice時,如果數據量很大,傳輸數據時就會很慢。為了提高速度,我們就會想到對數據進行壓縮。首先我們來分析一下。
當在webserice中傳輸數據時,一般都采用Dataset進行數據傳輸。執行的過程就是先把Dataset轉化為xml進行傳輸,Dataset轉化為xml的格式如下:
- <DataSetName>
- <DataTableName>
- <Column1Name>.......</Column1Name>
- <Column2Name>.......</Column2Name>
- <Column3Name>.......</Column3Name>
- </DataTableName>
- ...
- ...
- ...
- <DataSetName>
很明顯的可以看到,Datase在t轉化為xml的過程中增加了大量的xml格式數據,這樣也就加大了傳輸量。
經過分析,我們就可以找到兩個解決數據傳輸量大的問題的方法:
1.不直接使用Dataset來傳輸數據,避免轉化為xml時增加的額外數據。所以我們可以將Dataset轉化為DataSetSurrogate對象用Binary進行序列化,用二進制數據來傳輸數據。當然你也可以采用其他更好的方式,總之就是減少為了傳輸而增加的額外數據
2.對數據進行壓縮后再傳輸,至於壓縮的方法有很多,可以參考我的文章.net中壓縮和解壓縮的研究
參考代碼如下(這里使用的是.net自帶的Gzip進行壓縮的,壓縮效率可能不是太好):
- //=========================================================================
- //類名:DataSetZip
- /// <summary>
- /// 當DataSet中的數據量很大時,進行網絡數據傳遞時,速度會很慢。
- /// 本類將Dataset轉化為DataSetSurrogate對象用Binary進行序列化,
- /// 然后進行壓縮之后進行傳輸,最后進行解壓縮
- /// </summary>
- /// <remarks>
- /// 將DataSet中的DataTable中的數據進行轉換或復原
- /// </remarks>
- /*=========================================================================
- 變更記錄
- 序號 更新日期 開發者 變更內容
- 001 2008/7/22 張 新建
- =========================================================================*/
- public class DataSetZip
- {
- //消息ID
- private const string MSG_ERR_INTERNAL = "MFWE00016";
- /// <summary>
- /// 取得將DataSet轉化為DataSetSurrogate對象用Binary進行序列化,並壓縮后的二進制數組
- /// </summary>
- /// <param name="dsData">需壓縮的DataSet數據</param>
- /// <returns>壓縮后二進制數組</returns>
- public static byte[] GetDataSetZipBytes(DataSet dsData)
- {
- try{
- DataSetSurrogate dss = new DataSetSurrogate(dsData);
- BinaryFormatter ser = new BinaryFormatter();
- MemoryStream ms = new MemoryStream();
- ser.Serialize(ms, dss);
- byte[] buffer = ms.ToArray();
- byte[] Zipbuffer = Compress(buffer);
- return Zipbuffer;
- }
- catch (Exception ex)
- {
- throw new DataSetConverterException(MSG_ERR_INTERNAL, new string[] { "DataSetZip", "GetDataSetZipBytes" }, ex, null);
- }
- }
- /// <summary>
- /// 用.net自帶的Gzip對二進制數組進行壓縮,壓縮比率可能不是太好
- /// </summary>
- /// <param name="data">二進制數組</param>
- /// <returns>壓縮后二進制數組</returns>
- public static byte[] Compress(byte[] data)
- {
- MemoryStream ms = new MemoryStream();
- Stream zipStream = null;
- zipStream = new GZipStream(ms, CompressionMode.Compress, true);
- zipStream.Write(data, 0, data.Length);
- zipStream.Close();
- ms.Position = 0;
- byte[] compressed_data = new byte[ms.Length];
- ms.Read(compressed_data, 0, int.Parse(ms.Length.ToString()));
- return compressed_data;
- }
- /// <summary>
- /// 對二進制數組進行解壓縮
- /// </summary>
- /// <param name="data">二進制數組</param>
- /// <returns>解壓縮后的DataSet</returns>
- public static DataSet Decompress(byte[] data)
- {
- try
- {
- byte[] buffer = null;
- MemoryStream zipMs = new MemoryStream(data);
- buffer = EtractBytesFormStream(zipMs, data.Length);
- BinaryFormatter ser = new BinaryFormatter();
- DataSetSurrogate dss = ser.Deserialize(new MemoryStream(buffer)) as DataSetSurrogate;
- DataSet dsData = dss.ConvertToDataSet();
- return dsData;
- }
- catch(Exception ex)
- {
- throw new DataSetConverterException(MSG_ERR_INTERNAL, new string[] { "DataSetZip", "Decompress" }, ex, null);
- }
- }
- /// <summary>
- /// 用.net自帶的Gzip對數據流進行解壓縮
- /// </summary>
- /// <param name="zipMs">數據流</param>
- /// <param name="dataBlock">數據長度</param>
- /// <returns>解壓縮后的二進制數組</returns>
- public static byte[] EtractBytesFormStream(MemoryStream zipMs, int dataBlock)
- {
- byte[] data = null;
- int totalBytesRead = 0;
- Stream zipStream = null;
- zipStream = new GZipStream(zipMs, CompressionMode.Decompress);
- while (true)
- {
- Array.Resize(ref data, totalBytesRead + dataBlock + 1);
- int bytesRead = zipStream.Read(data, totalBytesRead, dataBlock);
- if (bytesRead == 0)
- {
- break;
- }
- totalBytesRead += bytesRead;
- }
- Array.Resize(ref data, totalBytesRead);
- return data;
- }
- }