热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

android网络处理HttpClient

转载自:http:android.tgbus.comAndroidtutorial201108364645.shtml(Android开发实现HttpClient工具类)

转载自:

      http://android.tgbus.com/Android/tutorial/201108/364645.shtml   (Android开发实现HttpClient工具类)

     http://www.open-open.com/lib/view/open1329101420890.html Android 网络数据的处理之 HttpClient)

   http://blog.csdn.net/heng615975867/article/details/9012303    (Android网络优化之HttpClient)


文章一、Android开发实现HttpClient工具类

      

在Android开发中我们经常会用到网络连接功能与服务器进行数据的交互,为此Android的SDK提供了Apache的HttpClient来方便我们使用各种    Http服务。你可以把HttpClient想象成一个浏览器,通过它的API我们可以很方便的发出GET,POST请求(当然它的功能远不止这些)。比如你只需以下几行代码就能发出一个简单的GET请求并打印响应结果:

  try {

          // 创建一个默认的HttpClient
          HttpClient httpclient = new DefaultHttpClient();
          // 创建一个GET请求
          HttpGet request = new HttpGet("www.google.com");
          // 发送GET请求,并将响应内容转换成字符串
          String respOnse= httpclient.execute(request, new BasicResponseHandler());
          Log.v("response text", response);
      } catch (ClientProtocolException e) {
          e.printStackTrace();
      } catch (IOException e) {
          e.printStackTrace();
      }

  为什么要使用单例HttpClient?

  这只是一段演示代码,实际的项目中的请求与响应处理会复杂一些,并且还要考虑到代码的容错性,但是这并不是本篇的重点。注意代码的第三行:

  HttpClient httpclient = new DefaultHttpClient();

  在发出HTTP请求前,我们先创建了一个HttpClient对象。那么,在实际项目中,我们很可能在多处需要进行HTTP通信,这时候我们不需要为每个请求都创建一个新的HttpClient。因为之前已经提到,HttpClient就像一个小型的浏览器,对于整个应用,我们只需要一个HttpClient就够了。看到这里,一定有人心里想,这有什么难的,用单例啊!!就像这样:

  public class CustomerHttpClient {
   private static HttpClient customerHttpClient;

   private CustomerHttpClient() {
   }

   public static HttpClient getHttpClient() {
   if(null == customerHttpClient) {
   customerHttpClient = new DefaultHttpClient();
   }
   return customerHttpClient;
   }
  }


  多线程!试想,现在我们的应用程序使用同一个HttpClient来管理所有的Http请求,一旦出现并发请求,那么一定会出现多线程的问题。这就好像我们的浏览器只有一个标签页却有多个用户,A要上google,B要上baidu,这时浏览器就会忙不过来了。幸运的是,HttpClient提供了创建线程安全对象的API,帮助我们能很快地得到线程安全的“浏览器”。

  解决多线程问题

public class CustomerHttpClient {
   private static final String CHARSET = HTTP.UTF_8;
   private static HttpClient customerHttpClient;

   private CustomerHttpClient() {
   }

   public static synchronized HttpClient getHttpClient() {
   if (null == customerHttpClient) {
   HttpParams params = new BasicHttpParams();
   // 设置一些基本参数
   HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
   HttpProtocolParams.setContentCharset(params,
   CHARSET);
   HttpProtocolParams.setUseExpectContinue(params, true);
   HttpProtocolParams
   .setUserAgent(
   params,
   "Mozilla/5.0(Linux;U;Android 2.2.1;en-us;Nexus One Build.FRG83) "
   + "AppleWebKit/553.1(KHTML,like Gecko) Version/4.0 Mobile Safari/533.1");
   // 超时设置
   /* 从连接池中取连接的超时时间 */
   ConnManagerParams.setTimeout(params, 1000);
   /* 连接超时 */
   HttpConnectionParams.setConnectionTimeout(params, 2000);
   /* 请求超时 */
   HttpConnectionParams.setSoTimeout(params, 4000);

   // 设置我们的HttpClient支持HTTP和HTTPS两种模式
   SchemeRegistry schReg = new SchemeRegistry();
   schReg.register(new Scheme("http", PlainSocketFactory
   .getSocketFactory(), 80));
   schReg.register(new Scheme("https", SSLSocketFactory
   .getSocketFactory(), 443));

   // 使用线程安全的连接管理来创建HttpClient
   ClientConnectionManager cOnMgr= new ThreadSafeClientConnManager(
   params, schReg);
   customerHttpClient = new DefaultHttpClient(conMgr, params);
   }
   return customerHttpClient;
   }
  }



  

  在上面的getHttpClient()方法中,我们为HttpClient配置了一些基本参数和超时设置,然后使用ThreadSafeClientConnManager来创建线程安全的HttpClient。上面的代码提到了3种超时设置,比较容易搞混,故在此特作辨析。

HttpClient的3种超时说明

  /* 从连接池中取连接的超时时间 */
  ConnManagerParams.setTimeout(params, 1000);
  /* 连接超时 */
  HttpConnectionParams.setConnectionTimeout(params, 2000);
  /* 请求超时 */
  HttpConnectionParams.setSoTimeout(params, 4000);

  第一行设置ConnectionPoolTimeout:这定义了从ConnectionManager管理的连接池中取出连接的超时时间,此处设置为1秒。
  第二行设置ConnectionTimeout:这定义了通过网络与服务器建立连接的超时时间。Httpclient包中通过一个异步线程去创建与服务器的socket连接,这就是该socket连接的超时时间,此处设置为2秒。
  第三行设置SocketTimeout:这定义了Socket读数据的超时时间,即从服务器获取响应数据需要等待的时间,此处设置为4秒。
  以上3种超时分别会抛出ConnectionPoolTimeoutException,ConnectionTimeoutException与SocketTimeoutException。

  封装简单的POST请求
  有了单例的HttpClient对象,我们就可以把一些常用的发出GET和POST请求的代码也封装起来,写进我们的工具类中了。目前我仅仅实现发出POST请求并返回响应字符串的方法以供大家参考。将以下代码加入我们的CustomerHttpClient类中:

private static final String TAG = "CustomerHttpClient";

  private static final String TAG = "CustomerHttpClient";

  public static String post(String url, NameValuePair... params) {
   try {
   // 编码参数
   List formparams = new ArrayList(); // 请求参数
   for (NameValuePair p : params) {
   formparams.add(p);
   }
   UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams,
   CHARSET);
   // 创建POST请求
   HttpPost request = new HttpPost(url);
   request.setEntity(entity);
   // 发送请求
   HttpClient client = getHttpClient();
   HttpResponse respOnse= client.execute(request);
   if(response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
   throw new RuntimeException("请求失败");
   }
   HttpEntity resEntity = response.getEntity();
   return (resEntity == null) ? null : EntityUtils.toString(resEntity, CHARSET);
   } catch (UnsupportedEncodingException e) {
   Log.w(TAG, e.getMessage());
   return null;
   } catch (ClientProtocolException e) {
   Log.w(TAG, e.getMessage());
   return null;
   } catch (IOException e) {
   throw new RuntimeException("连接失败", e);
   }

   }

  使用我们的CustomerHttpClient工具类
  现在,在整个项目中我们都能很方便的使用该工具类来进行网络通信的业务代码编写了。下面的代码演示了如何使用username和password注册一个账户并得到新账户ID。

 final String url = "http://yourdomain/context/adduser";
   //准备数据
   NameValuePair param1 = new BasicNameValuePair("username", "张三");
   NameValuePair param2 = new BasicNameValuePair("password", "123456");
   int resultId = -1;
   try {
   // 使用工具类直接发出POST请求,服务器返回json数据,比如"{userid:12}"
   String respOnse= CustomerHttpClient.post(url, param1, param2);
   JSONObject root = new JSONObject(response);
   resultId = Integer.parseInt(root.getString("userid"));
   Log.i(TAG, "新用户ID:" + resultId);
   } catch (RuntimeException e) {
   // 请求失败或者连接失败
   Log.w(TAG, e.getMessage());
   Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT);
   } catch (Exception e) {
   // JSon解析出错
   Log.w(TAG, e.getMessage());


文章二、Android 网络数据的处理之 HttpClient  这一章我们主要来介绍网络数据的传递与处理,相信很多读者都希望做出来的应用能跟网络上的数据进行互动,如微博,论坛之类的,这里我们就要学习网络传输与返回数据的处理,首先网络传递参数有POST跟GET两种协议,做过网页或是学习过的同学应该知道.网页每个表单中都有一个参数,这里method就是提交表单参数使用的协议,当然,协议不止这两种,还有文件上传协议,这我们以后会讲,今天我们首来就来熟悉Android中对于POST跟GET协议的应用,首先我们提供了一个HttpConnectionUtil.java的辅助类,这里面对POST跟GET进行了封装
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

import android.os.Handler;
import android.util.Log;

public class HttpConnectionUtil
{
public static enum HttpMethod
{
GET, POST
}

/**
* 异步连接
*
* @param url
* 网址
* @param method
* Http方法,POST跟GET
* @param callback
* 回调方法,返回给页面或其他的数据
*/
public void asyncConnect(final String url, final HttpMethod method,
final HttpConnectionCallback callback)
{
asyncConnect(url, null, method, callback);
}

/**
* 同步方法
*
* @param url
* 网址
* @param method
* Http方法,POST跟GET
* @param callback
* 回调方法,返回给页面或其他的数据
*/
public void syncConnect(final String url, final HttpMethod method,
final HttpConnectionCallback callback)
{
syncConnect(url, null, method, callback);
}

/**
* 异步带参数方法
*
* @param url
* 网址
* @param params
* POST或GET要传递的参数
* @param method
* 方法,POST或GET
* @param callback
* 回调方法
*/
public void asyncConnect(final String url,
final Map params, final HttpMethod method,
final HttpConnectionCallback callback)
{
Handler handler = new Handler();
Runnable runnable = new Runnable()
{
public void run()
{
syncConnect(url, params, method, callback);
}
};
handler.post(runnable);
}

/**
* 同步带参数方法
*
* @param url
* 网址
* @param params
* POST或GET要传递的参数
* @param method
* 方法,POST或GET
* @param callback
* 回调方法
*/
public void syncConnect(final String url, final Map params,
final HttpMethod method, final HttpConnectionCallback callback)
{
String json = null;
BufferedReader reader = null;

try
{
HttpClient client = new DefaultHttpClient();
HttpUriRequest request = getRequest(url, params, method);
HttpResponse respOnse= client.execute(request);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
{
reader = new BufferedReader(new InputStreamReader(response
.getEntity().getContent()));
StringBuilder sb = new StringBuilder();
for (String s = reader.readLine(); s != null; s = reader
.readLine())
{
sb.append(s);
}

json = sb.toString();
}
} catch (ClientProtocolException e)
{
Log.e("HttpConnectionUtil", e.getMessage(), e);
} catch (IOException e)
{
Log.e("HttpConnectionUtil", e.getMessage(), e);
} finally
{
try
{
if (reader != null)
{
reader.close();
}
} catch (IOException e)
{
// ignore me
}
}
callback.execute(json);
}

/**
* POST跟GET传递参数不同,POST是隐式传递,GET是显式传递
*
* @param url
* 网址
* @param params
* 参数
* @param method
* 方法
* @return
*/
private HttpUriRequest getRequest(String url, Map params,
HttpMethod method)
{
if (method.equals(HttpMethod.POST))
{
List listParams = new ArrayList();
if (params != null)
{
for (String name : params.keySet())
{
listParams.add(new BasicNameValuePair(name, params
.get(name)));
}
}
try
{
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(
listParams);
HttpPost request = new HttpPost(url);
request.setEntity(entity);
return request;
} catch (UnsupportedEncodingException e)
{
// Should not come here, ignore me.
throw new java.lang.RuntimeException(e.getMessage(), e);
}
} else
{
if (url.indexOf("?") <0)
{
url += "?";
}
if (params != null)
{
for (String name : params.keySet())
{
try
{
url += "&" + name + "="
+ URLEncoder.encode(params.get(name), "UTF-8");

} catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
}
}
HttpGet request = new HttpGet(url);
return request;
}
}

/**
* 回调接口
* @author Administrator
*
*/
public interface HttpConnectionCallback
{
/**
* Call back method will be execute after the http request return.
*
* @param response
* the response of http request. The value will be null if
* any error occur.
*/
void execute(String response);
}

}

这个类也是我从网上看到的,使用起来相当方便,希望读者能学会怎样使用,其实像java学习,可以将一些有用的类或是方法定义个自己包,将它们放进去,下次要用的话只要在主程序中调用就行了,这也是面向对象重要的方法.

这里面的方法,我就没有一行一行定义说明了,里面用的都是HttpClient的中方法

接下来,我们用这个类来进行Android的应用

main.xml(模板文件)


android:orientation="vertical" android:layout_
android:layout_>
android:layout_ android:id="@+id/http_edit"
android:text="http://">


android:layout_ android:id="@+id/relativeLayout1">



android:layout_>
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_ android:layout_>




然后就是主Actitiv的java代码了
import android.app.Activity;
import android.os.Bundle;
import android.text.Html;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.kang.http.HttpConnectionUtil;
import com.kang.http.HttpConnectionUtil.HttpConnectionCallback;
import com.kang.http.HttpConnectionUtil.HttpMethod;

public class HttpClientDemo extends Activity
{
private Button ok_btn;
private Button cancal_btn;
private EditText edit_text;
private TextView text;

@Override
protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.http_client);

//确定按钮
ok_btn = (Button) findViewById(R.id.http_ok);
ok_btn.setOnClickListener(new ClickEvent());

//取消按钮
cancal_btn = (Button) findViewById(R.id.http_cancal);
cancal_btn.setOnClickListener(new ClickEvent());

//文本编辑框
edit_text = (EditText) findViewById(R.id.http_edit);

//文本框
text = (TextView) findViewById(R.id.http_text);
}


//自定义按钮点击方法
public class ClickEvent implements OnClickListener
{

@Override
public void onClick(View v)
{
switch (v.getId())
{
case R.id.http_ok:
//网址
String url = edit_text.getText().toString().trim();

if (!url.equals("http://") && !url.equals(""))
{
//自定义类,封装了GET/POST方法,而且同样也封装了同步跟异步的方法
HttpConnectionUtil cOnn= new HttpConnectionUtil();
conn.asyncConnect(url, HttpMethod.GET,
new HttpConnectionCallback()
{

@Override
public void execute(String response)
{
text.setText(Html.fromHtml(response));
}
});
}

break;

case R.id.http_cancal:
edit_text.setText("http://");

break;

}

}

}
}


0_1318136821p6se.gif
你一定会奇怪,怎么会有其他一些代码呢?呵呵,这里我们取出的是它的源代码.OK,这一章讲完了



文章三、Android网络优化之HttpClient  尽管Android官网推荐在2.3及后续版本中使用HttpURLConnection作为网络开发首选类,但在连接管理线程安全方面,HttpClient还是具有很大优势。就目前而言,HttpClient仍是一个值得考虑的选择。对于HttpClient的优化,可以从以下几个方面着手:

    (1)采用单例模式(重用HttpClient实例)
    对于一个通信单元甚至是整个应用程序,Apache强烈推荐只使用一个HttpClient的实例。例如:

    private static HttpClient httpClient = null;
 
    private static synchronized HttpClient getHttpClient() {
       if(httpClient == null) {
           final HttpParams httpParams = new BasicHttpParams();  
           httpClient = new DefaultHttpClient(httpParams); 
       }  
  
      return httpClient;
    }

    (2)保持连接(重用连接)
    对于已经和服务端建立了连接的应用来说,再次调用HttpClient进行网络数据传输时,就不必重新建立新连接了,而可以重用已经建立的连接。这样无疑可以减少开销,提升速度。
    在这个方面,Apache已经做了“连接管理”,默认情况下,就会尽可能的重用已有连接,因此,不需要客户端程序员做任何配置。只是需要注意,Apache的连接管理并不会主动释放建立的连接,需要程序员在不用的时候手动关闭连接。

    (3)多线程安全管理的配置
    如果应用程序采用了多线程进行网络访问,则应该使用Apache封装好的线程安全管理类ThreadSafeClientConnManager来进行管理,这样能够更有效且更安全的管理多线程和连接池中的连接。
    (在网上也看到有人用MultiThreadedHttpConnectionManager进行线程安全管理的,后查了下Apache的API,发现MultiThreadedHttpConnectionManager是API 2.0中的类,而ThreadSafeClientConnManager是API 4.0中的类,比前者更新,所以选择使用ThreadSafeClientConnManager。另外,还看到有PoolingClientConnectionManager这个类,是API 4.2中的类,比ThreadSafeClientConnManager更新,但Android SDK中找不到该类。所以目前还是选择了ThreadSafeClientConnManager进行管理)
    例如:

    ClientConnectionManager manager = new ThreadSafeClientConnManager(httpParams, schemeRegistry); 
    httpClient = new DefaultHttpClient(manager, httpParams);

    (4)大量传输数据时,使用“请求流/响应流”的方式
    当需要传输大量数据时,不应使用字符串(strings)或者字节数组(byte arrays),因为它们会将数据缓存至内存。当数据过多,尤其在多线程情况下,很容易造成内存溢出(out of memory,OOM)。
    而HttpClient能够有效处理“实体流(stream)”。这些“流”不会缓存至内存、而会直接进行数据传输。采用“请求流/响应流”的方式进行传输,可以减少内存占用,降低内存溢出的风险。
    例如:

    // Get method: getResponseBodyAsStream()
    // not use getResponseBody(), or getResponseBodyAsString()
    GetMethod httpGet = new GetMethod(url);  
    InputStream inputStream = httpGet.getResponseBodyAsStream();

    // Post method: getResponseBodyAsStream()
    PostMethod httpPost = new PostMethod(url);  
    InputStream inputStream = httpPost.getResponseBodyAsStream(); 

    (5)持续握手(Expect-continue handshake)
    在认证系统或其他可能遭到服务器拒绝应答的情况下(如:登陆失败),如果发送整个请求体,则会大大降低效率。此时,可以先发送部分请求(如:只发送请求头)进行试探,如果服务器愿意接收,则继续发送请求体。此项优化主要进行以下配置:

    // use expect-continue handshake
    HttpProtocolParams.setUseExpectContinue(httpParams, true);

    (6)“旧连接”检查(Stale connection check)
    HttpClient为了提升性能,默认采用了“重用连接”机制,即在有传输数据需求时,会首先检查连接池中是否有可供重用的连接,如果有,则会重用连接。同时,为了确保该“被重用”的连接确实有效,会在重用之前对其进行有效性检查。这个检查大概会花费15-30毫秒。关闭该检查举措,会稍微提升传输速度,但也可能出现“旧连接”过久而被服务器端关闭、从而出现I/O异常。
    关闭旧连接检查的配置为:
    // disable stale check
    HttpConnectionParams.setStaleCheckingEnabled(httpParams, false);

    (7)超时设置
    进行超时设置,让连接在超过时间后自动失效,释放占用资源。
    // timeout: get connections from connection pool
    ConnManagerParams.setTimeout(httpParams, 1000);  
    // timeout: connect to the server
    HttpConnectionParams.setConnectionTimeout(httpParams, DEFAULT_SOCKET_TIMEOUT);
    // timeout: transfer data from server
    HttpConnectionParams.setSoTimeout(httpParams, DEFAULT_SOCKET_TIMEOUT);

    (8)连接数限制
    配置每台主机最多连接数和连接池中的最多连接总数,对连接数量进行限制。其中,DEFAULT_HOST_CONNECTIONS和DEFAULT_MAX_CONNECTIONS是由客户端程序员根据需要而设置的。
    // set max connections per host
    ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new ConnPerRouteBean(DEFAULT_HOST_CONNECTIONS)); 
    // set max total connections
    ConnManagerParams.setMaxTotalConnections(httpParams, DEFAULT_MAX_CONNECTIONS);

    经过优化后,上一篇日志中的getHttpClient()方法代码如下:

   

[java] view plaincopy
  1. private static synchronized HttpClient getHttpClient() {  
  2.     if(httpClient == null) {  
  3.         final HttpParams httpParams = new BasicHttpParams();    
  4.           
  5.         // timeout: get connections from connection pool  
  6.         ConnManagerParams.setTimeout(httpParams, 1000);    
  7.         // timeout: connect to the server  
  8.         HttpConnectionParams.setConnectionTimeout(httpParams, DEFAULT_SOCKET_TIMEOUT);  
  9.         // timeout: transfer data from server  
  10.         HttpConnectionParams.setSoTimeout(httpParams, DEFAULT_SOCKET_TIMEOUT);   
  11.           
  12.         // set max connections per host  
  13.         ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new ConnPerRouteBean(DEFAULT_HOST_CONNECTIONS));    
  14.         // set max total connections  
  15.         ConnManagerParams.setMaxTotalConnections(httpParams, DEFAULT_MAX_CONNECTIONS);  
  16.           
  17.         // use expect-continue handshake  
  18.         HttpProtocolParams.setUseExpectContinue(httpParams, true);  
  19.         // disable stale check  
  20.         HttpConnectionParams.setStaleCheckingEnabled(httpParams, false);  
  21.           
  22.         HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1);    
  23.         HttpProtocolParams.setContentCharset(httpParams, HTTP.UTF_8);   
  24.             
  25.         HttpClientParams.setRedirecting(httpParams, false);  
  26.           
  27.         // set user agent  
  28.         String userAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2) Gecko/20100115 Firefox/3.6";  
  29.         HttpProtocolParams.setUserAgent(httpParams, userAgent);       
  30.           
  31.         // disable Nagle algorithm  
  32.         HttpConnectionParams.setTcpNoDelay(httpParams, true);   
  33.           
  34.         HttpConnectionParams.setSocketBufferSize(httpParams, DEFAULT_SOCKET_BUFFER_SIZE);    
  35.           
  36.         // scheme: http and https  
  37.         SchemeRegistry schemeRegistry = new SchemeRegistry();    
  38.         schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));    
  39.         schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));  
  40.   
  41.         ClientConnectionManager manager = new ThreadSafeClientConnManager(httpParams, schemeRegistry);    
  42.         httpClient = new DefaultHttpClient(manager, httpParams);   
  43.     }         
  44.       
  45.     return httpClient;  
  46. }  


    附录:关于HttpURLConnection的优化,网上资料不多。从Android官网上看到一点,整理如下:

    (1)上传数据至服务器时(即:向服务器发送请求),如果知道上传数据的大小,应该显式使用setFixedLengthStreamingMode(int)来设置上传数据的精确值;如果不知道上传数据的大小,则应使用setChunkedStreamingMode(int)——通常使用默认值“0”作为实际参数传入。如果两个函数都未设置,则系统会强制将“请求体”中的所有内容都缓存至内存中(在通过网络进行传输之前),这样会浪费“堆”内存(甚至可能耗尽),并加重隐患。

    (2)如果通过流(stream)输入或输出少量数据,则需要使用带缓冲区的流(如BufferedInputStream);大量读取或输出数据时,可忽略缓冲流(不使用缓冲流会增加磁盘I/O,默认的流操作是直接进行磁盘I/O的);

    (3)当需要传输(输入或输出)大量数据时,使用“流”来限制内存中的数据量——即:将数据直接放在“流”中,而不是存储在字节数组或字符串中(这些都存储在内存中)。



推荐阅读
  • 使用EF Core在.Net Core控制台应用中操作SQLite数据库
    本文介绍如何利用Visual Studio 2019和Windows 10环境,通过Entity Framework Core(EF Core)实现对SQLite数据库的读写操作。项目源代码可从百度网盘下载。 ... [详细]
  • 本文总结了几个常用的Android开发技巧,包括检测设备上是否安装特定应用、获取应用的版本名称、设置状态栏透明以及如何从一个应用跳转至另一个应用的方法。 ... [详细]
  • 本文介绍如何使用Java实现AC自动机(Aho-Corasick算法),以实现高效的多模式字符串匹配。文章涵盖了Trie树和KMP算法的基础知识,并提供了一个详细的代码示例,包括构建Trie树、设置失败指针以及执行搜索的过程。 ... [详细]
  • C#爬虫Fiddler插件开发自动生成代码
    哈喽^_^一般我们在编写网页爬虫的时候经常会使用到Fiddler这个工具来分析http包,而且通常并不是分析一个包就够了的,所以为了把更多的时间放在分析http包上,自动化生成 ... [详细]
  • 在现代移动应用开发中,尤其是iOS应用,处理来自服务器的JSON数据是一项基本技能。无论是使用Swift还是PHP,有效地解析和利用JSON数据对于提升用户体验至关重要。本文将探讨如何在Swift中优雅地处理JSON,以及PHP中处理JSON的一些技巧。 ... [详细]
  • 本文介绍了如何在Spring框架中配置和使用定时任务,包括初始化配置和动态启动定时器的方法。通过示例代码展示了如何利用Spring的TaskScheduler接口来创建和管理定时任务。 ... [详细]
  • 设计模式系列-原型模式
    一、上篇回顾上篇创建者模式中,我们主要讲述了创建者的几类实现方案,和创建者模式的应用的场景和特点,创建者模式适合创建复杂的对象,并且这些对象的每个组成部分的详细创建步骤可以是动态的变化的,但 ... [详细]
  • Lua基本语法lua与C#的交互(相当简单详细的例子)
    lua脚本与C#的交互本文提供全流程,中文翻译。Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验——高分辨率用户请根据需求调整网页缩放比例)1LuaAndC#——L ... [详细]
  • 本文详细介绍了 Go 语言的关键特性和编程理念,包括其强大的并发处理能力、简洁的语法设计以及高效的开发效率。 ... [详细]
  • 本文提供了一个Android应用中用于抓取网页信息并下载图片的示例代码。通过该代码,开发者可以轻松实现从指定URL获取网页内容及其中的图片资源。 ... [详细]
  • 重写init方法后,属性声明后为什么不为nil? ... [详细]
  • ECharts图表绘制函数集
    本文档提供了使用ECharts库创建柱状图、饼图和双折线图的JavaScript函数。每个函数都详细列出了参数说明,并通过示例展示了如何调用这些函数以生成不同类型的图表。 ... [详细]
  • 本文探讨了在Qt框架下实现TCP多线程服务器端的方法,解决了一个常见的问题:服务器端仅能与最后一个连接的客户端通信。通过继承QThread类并利用socketDescriptor标识符,实现了多个客户端与服务器端的同时通信。 ... [详细]
  • 最近手上在进行一个性能测试项目,脚本是java语言使用httpClient实现http请求。并发用户数线程只有40个,但是服务器端启动的线程出现了400多个,是哪里平白无故出现这么多线程呢?肯定是有问 ... [详细]
  • Android本地化存储Cookie(针对HttpClient)
    因为最近有人问我怎么保存HttpClient的Cookie,所以这里写下,顺便记录总结吧.当然,有Android网络编程经历的童鞋一看就懂喇~就不多说了,直接上代码: ... [详细]
author-avatar
mobiledu2502881047
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有