1.通過http發送或讀取數據(Post,Get)
HttpClient方式已被廢棄。
1.1 從指定url獲取返回信息(GET/POST)。
private void requestHttpView(final String urlRequest){
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection=null;
try {
URL url=new URL(urlRequest);
connection=(HttpURLConnection)url.openConnection();
//從指定url建立鏈接。
connection.setRequestMethod("GET");
//設置連接方式。
/*
connection.setRequestMethod("POST");
//需要發送數據時,將鏈接方式設置爲“POST”
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
//獲取連接的輸出流(輸出流輸出流是相對本機而言的)
out.writeBytes("username=admin&password=123456");
//將需要發送的數據送入輸出流
*/
connection.setConnectTimeout(5000);
//設置連接超時。
connection.setReadTimeout(5000);
//設置讀取超時。
InputStream inputStream=connection.getInputStream();
//獲取鏈接的輸入流。
BufferedReader reader=new BufferedReader(new InputStreamReader(inputStream));
//新建BufferedReader對象,讀取數據方便
StringBuilder builder=new StringBuilder();
String line;
while((line=reader.readline())!=null){
builder.append(line);
}//輸入流讀取完畢。
Message message=new Message();
message.what=REQUEST_OK;
message.obj=builder;
handler.sendMessage(message);
//將獲取到的數據交給主線程處理。
} catch (IOException e) {
Message message=new Message();
message.what=REQUEST_ERROR;
handler.sendMessage(message);
} finally {
if (connection!=null) {
connection.disconnect();
//關閉鏈接
}
}
}
}).start();
}
1.2 被廢棄的HttpClient方式:
private void POSTUrl(String url){
new Thread(new Runnable() {
@Override
public void run() {
Message message=null;
try {
HttpClient client=new DefaultHttpClient();
//新建“客戶”對象
HttpPost httpPost=new HttpPost(url);
//新建post請求
List<NameValuePair> pairs=new ArrayList<NameValuePair>();
pairs.add(new BasicNameValuePair("title", "hello"));
UrlEncodedFormEntity entity=new UrlEncodedFormEntity(pairs,"utf-8");
httpPost.setEntity(entity);
//將要發送內容添加到list中,並提交給post對象;
HttpResponse response=client.execute(httpPost);
if(response.getStatusLine().getStatusCode()==200){
//返回值狀態爲200代表成功
message.what=REQUEST_OK;
HttpEntity httpEntity=response.getEntity();
message.obj= EntityUtils.toString(httpEntity,"utf-8");
//取出訪問url返回的內容。
}else{
message.what=REQUEST_ERROR;
message.obj="statusCode not equals 200";
}
} catch (IOException e) {
message.what=REQUEST_ERROR;
message.obj=e.toString();
}finally {
handler.sendMessage(message);
//交給主線程處理
}
}
}).start();
}
//此時方法只供參考,說明http請求的另一種模式。
2. 數據解析——xml文檔;
訪問某個url返回的數據,大都是html語言,例如WebView控件就是將http請求以及獲取的數據封裝,用瀏覽器的方式進行查看。
還有些返回的內容只提供數據,不能形成可視化網頁,例如xml和json。這些內容大都不要進行解析,從中提取想要的information。
2.1 解析xml文檔——pull
Pull解析器提供的事件類型總共有5種,分別如下:
- (1)START_DOCUMENT 文檔開始
- (2)START_TAG 開始節點
- (3)TEXT 文本節點
- (4)END_TAG 節點結束
- (5)END_DOCUMENT 文檔結束
pull解析原理:從文檔頭開始,整個文檔由節點組成,有些節點中包含屬性和文本;
<qq mm="a" nn="b">text</qq>
//<qq ……>表示qq節點的開始
//<qq mm="a" nn="b">text</qq>就是節點。
//qq是節點名字
//mm和nn都是屬性名
//a和b是節點對應的值
//text是文本
//遇到</qq>代表節點qq結束
pull方式解析,就是新建一個xmlPullParser對象,然後從頭開始“推”,開始解析時,將事件設置爲START_DOCUMENT,當碰到節點開始標誌時,會將事件設置爲START_TAG,如此解析下去,直到文檔結束,然後將事件爲END_DOCUMENT 文檔結束;下面介紹解析時用到的方法:
(1)int getAttributeCount(); //獲取當前節點的屬性個數
(2)String getAttributeValue(int index); //獲取屬性值,參數表示第index個屬性。
(3)int getEventType();//獲取事件類型
(4)String getName();//用於START_TAG和END_TAG事件中,獲取當前節點的名字
(5)int next();//處理下一個節點
(6)String nextText();//用於START_TAG事件中,獲得下一個TEXT類型的節點(就是文本)
pull解析代碼:
private String[] analyzeXML(String xml,String[] names){
String[] values=new String[names.length];
try {
XmlPullParserFactory factory=XmlPullParserFactory.newInstance();
XmlPullParser parser=factory.newPullParser();
//利用“工廠”生產一個進行pull解析的對象。
parser.setInput(new StringReader(xml));
//設置進行pull解析的內容或輸入流
int type=parser.getEventType();
//獲取當前的事件類型。
while(type!=XmlPullParser.END_DOCUMENT){
//不斷的讀取下一個節點,直到文檔結束。
String nodeName=parser.getName();
switch (type){
case XmlPullParser.START_TAG:{
for(int i=0;i<names.length;i++){
if(names[i].equals(nodeName)){
values[i]=parser.nextText();
//nodeName爲當前節點名
break;
}
}
break;
}
case XmlPullParser.END_TAG:{
break;
}
default:{
break;
}
}
type=parser.next();
}
} catch (Exception e) {
}
return values;
//返回獲取到的對應節點的文本
}
2.2 解析xml文檔——sax
sax解析原理:sax解析方式與pull有些類似,都是一邊讀取一邊解析,不過sax將解析以類的形式封裝起來,只需要重寫方法就可以了。
sax屬於事件驅動,每當遇到一定的標誌就執行特定的方法;pull像是”手動“驅動,需要代碼顯示控制讀取,判斷,取值,再讀取……
sax解析代碼:
SAXParserFactory factory=SAXParserFactory.newInstance();
XMLReader xmlReader=factory.newSAXParser().getXMLReader();
MyHandler handler = new MyHandler();
xmlReader.setContentHandler(handler);
// 將ContentHandler的實例設置到XMLReader
//(setContentHandler方法需要接收一個處理解析事件的類參數)
xmlReader.parse(new InputSource(new StringReader(xmlData)));
// 開始執行解析
myHandler類一般繼承DefaultHandler類,然後重寫其中的事件方法。
MyHandler代碼:
public class MyHandler extends DefaultHandler {
@Override
public void startDocument() throws SAXException {
//開始解析文檔時調用,進行初始化的工作。
}
@Override
public void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {
//開始某節點時候調用
/*uri - 名稱空間 URI,如果節點沒有任何名稱空間 URI,或者沒有正在執行名稱空間處理,則爲空字符串。
*localName - 本地名稱(不帶前綴),如果沒有正在執行名稱空間處理,則爲空字符串。
*qName - 限定的名稱(帶有前綴),如果限定的名稱不可用,則爲空字符串。(節點名,一般讀取數據時比較qName是否是自己想要的內容名稱,然後提取數據)
*attributes - 附加到節點的屬性。如果沒有屬性,則它將是空的 Attributes 對象。
*/
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
//獲取文本時候調用,準確的說應該是在讀取某節點中內容時候調用。
/*ch - 字符。
*length - 從字符數組中使用的字符數。
*start - 字符數組中的開始位置
*/
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
//節點結束時調用
//與startElement參數基本相同
}
@Override
public void endDocument() throws SAXException {
//文檔結束時調用
}
}
//從解析方法中也可以看出,xml格式非常重要,不規範的書寫方式會導致解析失敗。
這樣看起來是不是發現sax除了比較”自動化“之外,跟pull解析沒有多大的區別。
2.3 解析xml文檔——DOM
js中,dom指的是文檔對象模型,也是操作頁面最基本最常用的方法。
DOM原理: pull與sax解析都是無”記憶”的,即對整個文檔而言,只能在觸發事件時進行內容的讀取,不可能依靠前兩種解析方式理清文檔結構。DOM則是先將文檔 ”通讀“,以節點建立”樹“的模型,在想要獲取內容時只要知道在”樹“中的位置,就可以隨時讀取,不過因爲要建立模型,因此會佔用較大的內存空間。
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(file);
//其實解析xml文檔方法步驟都差不多,先構建出解析器,再傳入需要解析的內容,然後對內容進行分析。
此時獲得的doc包含整個文檔中的節點。直觀來看:
(隨便找了個xml的dom樹)
//可以看到,dom“樹”的節點是由節點(非TEXT類型)和文本組成的(文本總是沒有子節點的子節點,屬性相當於節點的“附加"信息。我們獲取的內容就是指文本)
//系統不可能將”樹“形象的映射到內存裏,因此dom解析是通過棧來實現的,因爲xml文檔的規範性,通過查看棧的數據,就可以”立體化“dom樹。
//需要注意的是,dom解析類似於引用,如果改變生成的doc,那麼實際的文檔將會被改變。
//dom查找數據可以通過根節點不停的查找子節點,直至定位到想要的節點,然後獲取內容。
節點——Node:節點本來是數據結構中tree的組成部分,不過在xml文檔中,所有的內容都可以稱爲節點。在Dom中,節點分爲十二總,涵蓋了文檔中所有部分,我們上面說的”文本“,其實只是TEXTNODE類型的節點,不過爲了直觀,把兩者區分開來。
元素——Element:元素和節點很相似,事實上,看源碼的話可以發現Element繼承自Node,Element相當於Node的擴展,不過使用起來較爲方便一些。
Node與Element的區別
例:
private String xmlAnalize(String xml){
/*xml字符串內容:
*<?version="1.0" encoding="utf-8"?>
*<html title="title">
* <head>head</head>
* <!--reliase-->
* <body>body</body>
*</html>
*/
try {
DocumentBuilder documentBuilder=DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document=documentBuilder.parse(new ByteArrayInputStream(xml.getBytes("UTF-8")));
NodeList childs=document.getChildNodes();
Node node1;
if(childs.getLength()>0){
for(int i=0;i<childs.getLength();i++){
node1=childs.item(i);
Log.i("java","……………………"+node1.getNodeType()+"&"+node1.getNodeName()+"&"+node1.getNodeValue());
}
}
/*控制檯輸出:
*……………………7&version="1.0"&encoding="utf-8"
* ……………………1&html&null
*/
//由此可見document相當於整個文檔,getChildNodes方法可以獲得“根目錄”下所有子節點,此處7表示文檔編碼版本等信息。
Element element=document.getDocumentElement();//xml規範,xml文檔除了開頭的編碼等說明外,其他內容必須包含在同一個根節點下。getDocumentElement()方法便是獲取該根目錄節點(此節點也是Element)。
Log.i("java","……………………"+element.getNodeType()+"&"+element.getNodeName()+"&"+element.getNodeValue());
/*控制檯輸出:
* ……………………1&html&null
*/
return getElements(element);
} catch (Exception e) {
Log.i("java",e.toString());
return null;
}
}
private String getElements(Node node){
//獲取html節點下所有子節點的類型,名字,和值。
StringBuilder builder=new StringBuilder();
NodeList nodeList=node.getChildNodes();
Node node1;
if(nodeList.getLength()>0){
for(int i=0;i<nodeList.getLength();i++){
node1=nodeList.item(i);
builder.append(node1.getNodeType()+"&"+node1.getNodeName()+"&"+node1.getNodeValue()+"\n");
Log.i("java",node1.getNodeType()+"&"+node1.getNodeName()+"&"+node1.getNodeValue());
//獲取結點對應的類型,name,以及value
}
}//判斷屬性結點會不會在節點樹中。
/*控制檯輸出:
* 1&head&null
* 8&#comment&reliase
* 1&body&null
*/
//可以看到,dom解析還可以獲取到註釋信息,而html節點下的屬性信息不能通過getChildNodes方法獲得。
return builder.toString();
}
3. 數據解析——json
假如json數據以“組”的形式存在,如數組,list(map除外)。
private Vector<String[]> analyzeJSON(String jsonData,String[]names) {
Vector<String[]> vector=new Vector<String[]>();
try {
JSONArray jsonArray = new JSONArray(jsonData);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
String[]values=new String[names.length];
for(int j=0;j<values.length;j++){
values[j]=jsonObject.getString(names[j]);
}
vector.add(values);
}
} catch (Exception e) {
}
return vector;
}
jsonArray可以存儲“組”,jsonObject提取組中的”單“個信息。