MonoDroid : Encoding.ASCII.GetString failing

本文关键字:GetString failing ASCII Encoding MonoDroid | 更新日期: 2023-09-27 18:15:31

间歇性地,Encoding.ASCII.GetString调用失败,并产生一个异常,该异常会转义所有的catch块并冻结应用程序。

private string ExecuteRequest(Uri url, KeyValuePair<string, string>[] postItems = null)
{
    var data = new byte[0];
    var response = new byte[0];
    using (var client = new WebClient())
    {
        if (postItems != null && postItems.Count() > 0)
        {
            string dataString = string.Join("&", postItems.Select(
                                    item => string.Format("{0}={1}", item.Key, item.Value)).ToArray());
            data = new ASCIIEncoding().GetBytes(dataString);
        }
        response = client.UploadData(url, "POST", data);
        Android.Util.Log.Info("info", "response from the post received. about to get string");
        client.Dispose();
    }
    try
    {
        return Encoding.ASCII.GetString(response);
    }
    catch (Exception ex)
    {
        Android.Util.Log.Info("info", 
            "Encoding.ASCII.GetString Exception : {0}, {1}", ex.Message, ex.StackTrace);
        throw new ApplicationException("UnRecoverable. Abort");
    }            
}

StackTrace =

I/sssvida (10960): response from the post received. about to get string
I/mono    (10960): Stacktrace:
I/mono    (10960):
I/mono    (10960):   at System.Text.ASCIIEncoding.GetString (byte[],int,int) <0x000cb>
I/mono    (10960):   at System.Text.Encoding.GetString (byte[]) <0x00037>
I/mono    (10960):   at ServiceRequest.ExecuteRequest (System.Uri,System.Collections.Generic.KeyValuePair`2<string, string>[]) <0x0026b>

间歇性地,我得到一个不寻常的堆栈跟踪如下所示

I/mono    ( 9817): Stacktrace:
I/mono    ( 9817):
F/        ( 9817): * Assertion at ../../../../mono/mini/mini-exceptions.c:472, condition `class' not met
D/dalvikvm(  220): GC_EXPLICIT freed 1K, 35% free 17547K/26759K, paused 3ms+3ms

响应是json数据,可以在1 - 4mb之间。

请帮助。谢谢! !

Edit 2:我更新了代码,使用UploadString而不是UploadData,间歇性地我得到这个:

I/mono    (15065): Stacktrace:
I/mono    (15065):
I/mono    (15065):   at string.CreateString (char[]) <0x0004b>
I/mono    (15065):   at (wrapper managed-to-managed) string..ctor (char[]) <0xffffffff>
I/mono    (15065):   at System.Text.Encoding.GetString (byte[],int,int) <0x00043>
I/mono    (15065):   at System.Text.UTF8Encoding.GetString (byte[],int,int) <0x0002b>
I/mono    (15065):   at System.Text.Encoding.GetString (byte[]) <0x00037>
I/mono    (15065):   at System.Net.WebClient.UploadString (System.Uri,string,string) <0x0007f>
I/mono    (15065):   at (wrapper remoting-invoke-with-check) System.Net.WebClient.UploadString (System.Uri,string,string) <0xffffffff>

MonoDroid : Encoding.ASCII.GetString failing

首先,请按照Rolf在评论中的要求填写一个bug报告。第二个堆栈跟踪是一个永远不应该发生的崩溃。

关于第一个问题,是否有理由不使用(其中一个重载)WebClient ?UploadString ?

该方法将负责编码,确保HTTP请求头匹配,编码请求和响应…它还将返回一个字符串(对您来说代码更少:-)。

否则,您可能最终得到一个字符串(除非在此代码之前有其他验证),该字符串不能用ASCII编码,并且会导致异常(遗憾的是,我们只有堆栈跟踪,而不是抛出确切的异常来确认这一点)。

分页数据和块下载可能是唯一正确且可扩展/健壮的解决方案。

现在,下面的代码没有爆炸,可能是我还没有达到临界点。但这是我第一次尝试在这个设备上进行分组。Encoding.ASCII.GetString不会在下面的代码中爆炸。

private string ExecuteRequest(Uri url, KeyValuePair<string, string>[] postItems = null)
{
    var data = new byte[0];
    var response = new byte[0];
    ///switched to WebClient because
    /// http://stackoverflow.com/questions/8167726/monodroid-intermittent-failure-when-reading-a-large-json-string-from-web-servi
    using (var client = new WebClient())
    {
        if (postItems != null && postItems.Count() > 0)
        {
            string dataString = string.Join("&", postItems.Select(
                                    item => string.Format("{0}={1}", item.Key, item.Value)).ToArray());
            data = new ASCIIEncoding().GetBytes(dataString);
        }
        response = client.UploadData(url, "POST", data);
        Android.Util.Log.Info("info", "response from the post received. about to get string");
        client.Dispose();
    }
    try
    {
        Android.Util.Log.Info("info", "response size : {0}", response.Length);
        var chunkSize = 50000;
        if (response.Length > chunkSize)
        {
            var returnValue = new StringBuilder();
            for (int i = 0; i < response.Length; i+= chunkSize)
            {                        
                int end = (i + chunkSize) > response.Length ? response.Length - i : chunkSize;
                returnValue.Append(Encoding.ASCII.GetString(response, i, end));
                Android.Util.Log.Info("info", "added a chunk from {0} to {1}", i, end);
            }
            return returnValue.ToString();
        }
        return Encoding.ASCII.GetString(response);
    }
    catch (Exception ex)
    {
        Android.Util.Log.Info("info", 
            "Encoding.ASCII.GetString Exception : {0}, {1}", ex.Message, ex.StackTrace);
        throw new ApplicationException("UnRecoverable. Abort");
    }            
}