2

我知道以前有人问过这个问题,但是由于我无法找到带有明确结论的答案,或者至少无法找到一个显示可能方法的优缺点的答案,所以我不得不问:

当谈到从 Internet 读取数据时,例如 web 服务,读取这些数据的正确或更有效的方法是什么?

从我浏览的所有书籍中,我发现了至少 4 种读取数据的方法:

1) 一次读取特定数量的字符。在这种情况下,数据以 4026 个字符的块读取

BufferedReader reader = new BufferedReader(
new InputStreamReader(in, encoding));
char[] buffer = new char[4096];
StringBuilder sb = new StringBuilder();
int downloadedBytes = 0;
int len1 = 0;
while ((len1 = reader.read(buffer)) > 0) {  
    sb.append(buffer);  
}
return sb.toString();

2)在知道内容长度的情况下读取数据

int length =(HttpURLConnection) urlConnection.getContentLength();
InputStream inputStream = urlConnection.getInputStream();
BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(inputStream));
StringBuilder stringBuilder = new StringBuilder(length);
char[] buffer = new char[length];
int charsRead;
while ((charsRead = bufferedReader.read(buffer)) != -1) {
    stringBuilder.append(buffer, 0, charsRead);
}
return stringBuilder.toString();

3)逐行读取数据:

BufferedReader reader=new BufferedReader(new InputStreamReader(c.getInputStream()));
StringBuilder buf=new StringBuilder();
String line=null;
while ((line=reader.readLine()) != null) {
  buf.append(line);
}
return(buf.toString());

4)逐字符读取数据:

InputStream in = mConnection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(
        in, enconding));    
int ch;
StringBuilder sb = new StringBuilder();         
while ((ch=reader.read()) > 0) {            
    sb.append((char)ch);
}

return sb.toString().trim();

我已经尝试了这 4 种不同技术中的 3 种,除了第 3 种(逐行读取数据)之外,在这三种技术中,只有第四种给了我很好的结果。

  • 第一种方法对我不起作用,因为当我读取大量数据时,它经常会切断数据,从而导致无效的 json 字符串或结尾带有空格的字符串。
  • 第二种方法,好吧,我无法使用该方法,因为 getContentLength并不总是可靠的,如果未设置该值,我们无能为力,这就是我的情况。
  • 我没有尝试第三种方法,因为我不确定逐行读取数据的事实。这适用于包含 json 对象数组的数据还是仅适用于确实包含行的文件?
  • 作为我最后选择的最后一种技术,我尝试了它并且它有效,但我认为逐个字符读取大量数据根本不会有效。

所以现在我真的很感激你的意见和想法。从 Web 服务读取数据时,您使用什么方法?更重要的是为什么?

谢谢。

PD 我知道我可以很容易地使用DefaultHttpClient,但文档明确鼓励不要这样做。

对于 Android 2.3 (Gingerbread) 及更高版本,HttpURLConnection 是最佳选择。其简单的 API 和小尺寸使其非常适合 Android。透明压缩和响应缓存可减少网络使用、提高速度并节省电池。

4

3 回答 3

2

我已经尝试了您提到的所有方法。如果面临的一个问题是没有完全阅读答复。经过一番研究,我发现最有效/最快的方法就是这样

       DefaultHttpClient client = new DefaultHttpClient();
                HttpGet httpGet = new HttpGet(url);

                httpGet.setHeader("Accept", "application/json");
                httpGet.setHeader("Content-type", "application/json");
//ive put json header because im using json


                try {
                    HttpResponse execute = client.execute(httpGet);


                    String responseStr = EntityUtils.toString(execute.getEntity());

                 }

responseStr 将包含 web 服务回复,它会一口气读取它。希望这可以帮助

于 2014-09-16T05:21:39.413 回答
2

如果数据量不是太大,那你使用什么方法并不重要。如果是,那么使用缓冲并以块的形式读取数据是有意义的。

第二种方法不太好,因为你并不总是能得到ContentLength.

然后,如果您的数据是 text/html/JSON,您可以使用第三种方法,因为您不必担心块大小。此外,您可以逐行打印传入的数据以进行目标调试。

如果您的数据是像图像这样的二进制/base64 流,您应该使用第一种方法并以 4k(通常使用的)块读取数据。

更新:

DefaultHttpClient顺便说一句,我使用的是单例而不是可怕的AndroidHttpClient,它工作顺利:)

于 2014-09-16T11:48:53.830 回答
0

这很重要。最好的性能是从 InputStream 读取到一个合理大小的缓冲区。通过这种方式,您可以一次传输大量数据,而不是重复相同的操作数千次。不要总是依赖 Content-length 标头值。对于 gzip 压缩的内容,它可能会显示不正确的大小。

于 2014-09-16T11:55:55.217 回答