[Android] 要學會的關鍵技術—XML的讀取(3)

device-2012-03-23-142254

系列文章:

[Android] 要學會的關鍵技術—XML的讀取(1) 

[Android] 要學會的關鍵技術—XML的讀取(2) 

[Android] 要學會的關鍵技術—XML的讀取(3)

 


講完技術性的東西之後,最後就是把它設定起來

 

版面檔 main.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    android:orientation="vertical" >

 

    <TextView

        android:id="@+id/textView1"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="讀取RSS新聞標題:" />

 

    <LinearLayout

        android:id="@+id/linearLayout1"

        android:layout_width="match_parent"

        android:layout_height="wrap_content" >

 

        <EditText

            android:id="@+id/trg_url"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_weight="1"

            android:hint="請輸入RSS網址"

            android:text="http://tw.news.yahoo.com/rss/travel"

            android:singleLine="true">

 

            <requestFocus />

        </EditText>

 

        <Button

            android:id="@+id/get_data"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="取得" />

    </LinearLayout>

 

    <ScrollView

        android:layout_width="match_parent"

        android:layout_height="match_parent" >

 

        <TextView

            android:id="@+id/result_txt"

            android:layout_width="fill_parent"

            android:layout_height="wrap_content" />

    </ScrollView>

 

</LinearLayout>

 

主程式 Main.java

 

package com.J_Test.XMLParserTest;

import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;
import com.J_Test.XMLParserTest.Module.SimpleXMLParser;
import com.J_Test.XMLParserTest.ParsingHandler.RssNewsXMLParsingHandler;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
 

public class Main extends Activity implements OnClickListener

{

     private static final String TAG = “XMLParserTest”;

     /** 「要更新版面」的訊息代碼 */

     protected static final intREFRESH_DATA = 0x00000001;

     /** Rss資料的網址 */

     String trgUrl;

     /** 新聞資料的物件陣列 */

     RssNews[] Arr_RssNews;

     private Button getData_btn;
     private TextView result_edtxt;
     private EditText trgUrl_txt;

     /** 建立UI Thread使用的Handler,來接收其他Thread來的訊息 */

     Handler mHandler = new Handler()

     {

           @Override

           public void handleMessage(Message msg)

           {

                switch (msg.what)

                {

                // 更新資料,將Rss新聞的標題用迴圈依序印出來

                case REFRESH_DATA:

                     result_edtxt.setText(“”);

                     for (int i = 0; i < Arr_RssNews.length; i++)

                     {

                           result_edtxt.append(Arr_RssNews[i].getTitle() + “n”);

                     }

                     break;

                }

           }

     };

 

     /** Called when the activity is first created. */

     @Override

     public void onCreate(Bundle savedInstanceState)

     {

           super.onCreate(savedInstanceState);

           setContentView(R.layout.main);

           // 版面初始化

 

           getData_btn = (Button) findViewById(R.id.get_data);
           result_edtxt = (TextView) findViewById(R.id.result_txt);
           trgUrl_txt = (EditText) findViewById(R.id.trg_url);
           getData_btn.setOnClickListener(this);

     }

     @Override

     public void onClick(View v)

     {

           // 若是按下getData_btn的按鈕

           if (v == getData_btn)

           {

                // 擷取trgUrl_txt文字框裡的內容

                trgUrl = trgUrl_txt.getEditableText().toString();

                // 開一個執行緒(Thread)

                new Thread()

                {

                     @Override

                     public void run()

                     {

                           Arr_RssNews = getRssNews();

                           if (Arr_RssNews != null)

                                 // Handler上發出「要更新版面」的訊息

                                 mHandler.sendEmptyMessage(REFRESH_DATA);

                     }

                 }.start();

            }

      }

 

     /**
      * 從網路擷取RSS的資料(需要搭配執行緒)
      * @return Rss新聞的物件陣列
      */

     public RssNews[] getRssNews()

     {

           if (trgUrl == null)

                return null;

           try

           {

                // 建立一個Parser物件,並指定擷取規則 (ParsingHandler)

                SimpleXMLParser dataXMLParser = new SimpleXMLParser(

                new RssNewsXMLParsingHandler());

                // 呼叫getData方法取得物件陣列

                Object[] data = (Object[]) dataXMLParser.getData(trgUrl);

                if (data != null)

                {

                     // 如果資料形態正確,就回傳

                     if (data[0] instanceof RssNews[])

                     {

                           return (RssNews[]) data[0];

                     }

                }

           } catch (SAXException e)

           {

                e.printStackTrace();

           } catch (IOException e)

           {

                e.printStackTrace();

           } catch (ParserConfigurationException e)

           {

                e.printStackTrace();

           }

           // 若有錯誤則回傳null

           return null;

     }

}

 


呼….結束了。

什麼?你又忘了!

再給我忘記這句

<uses-permission android:name="android.permission.INTERNET" />

我就搥你

 

參數設定檔 AndroidManifest.xml

<?xml version=“1.0” encoding=“utf-8”?>

<manifest xmlns:android=“http://schemas.android.com/apk/res/android”

    package=“com.J_Test.XMLParserTest”

    android:versionCode=“1”

    android:versionName=“1.0” >

 

    <uses-sdk

        android:minSdkVersion=“8”

        android:targetSdkVersion=“17” />

    <uses-permission android:name=“android.permission.INTERNET” />

    <application

        android:allowBackup=“true”

        android:icon=“@drawable/ic_launcher”

        android:label=“@string/app_name”

        android:theme=“@style/AppTheme” >

        <activity

            android:name=“com.J_Test.XMLParserTest.Main”

            android:label=“@string/app_name” >

            <intent-filter>

                <action android:name=“android.intent.action.MAIN” />

                <category android:name=“android.intent.category.LAUNCHER” />

            </intent-filter>

        </activity>

    </application>

</manifest>

 

 

[Android] 要學會的關鍵技術—XML的讀取(2)

device-2012-03-23-142254  

系列文章:

[Android] 要學會的關鍵技術—XML的讀取(1) 

[Android] 要學會的關鍵技術—XML的讀取(2) 

[Android] 要學會的關鍵技術—XML的讀取(3)

 


上篇講清楚XML的讀取方式之後,接下來上程式碼

 

之前說了,我比較喜歡設計一個類別(Class)把解析完的內容塞進去

 

新聞類別 RssNews.java

package com.J_Test.XMLParserTest;

import java.io.Serializable;

/*
 * <rss version=”2.0″>
 * <channel version=”2.0″>
 * <title> 中央氣象局警報、特報 </title>
 * <link>http://www.cwb.gov.tw/</link>
 * <description> 中央氣象局 RSS服務 </description>
 * <language>zhtw</language>
 * <lastBuildDate>Sat, 03 Sep 2011 19:00:02 GMT</lastBuildDate>
 * <ttl>1</ttl>
 * <item>
 * <pubDate>Sat, 03 Sep 2011 13:34:26 GMT</pubDate>
 * <title>09/03 21:30 解除大雨特報發布</title>
 * <link>http://www.cwb.gov.tw/V7/prevent/warning/w26.htm?&id=20110904030002</link>
 * <description>(…)</description>
 * </item>
 * </channel>
 * </rss>
 */

@SuppressWarnings(“serial”)
public class RssNews implements Serializable

{

     private String title = null;

     private String link = null;

     private String pubDate = null;

 

     public void setTitle(String title)

     {

           this.title = title;

     }

 

     public String getTitle()

     {

           return title;

     }

 

     public void setLink(String link)

     {

           this.link = link;

     }

 

     public String getLink()

     {

           return link;

     }

 

     public void setPubDate(String pubDate)

     {

           this.pubDate = pubDate;

     }

 

     public String getPubDate()

     {

           return pubDate;

     }

 

     @Override

     public String toString()

     {

           return “RssNews [title=” + title + “, link=” + link + “, pubDate=” + pubDate + “]”;

     }

}

 

嗯,這複習了一下資料類別的寫法
我只記錄RSS文章的標題、連結、摘要…等我要的訊息
大多程式碼給eclipse自己產生,沒甚麼特別

繼承Serializable 只是為了到時候方便寫入到檔案而已,可以不寫

 

 

XML剖析器 SimpleXMLParser.java

package com.J_Test.XMLParserTest.Module;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

 

public class SimpleXMLParser

{

     protected SimpleXMLParsingHandler xmlParsingHandler;

     /**
      * 建構子,必須將xmlParsingHandlernew出來
      *
      */

     public SimpleXMLParser(SimpleXMLParsingHandler parser)

     {

           xmlParsingHandler = parser;

     }

 

     /**
      * XML的剖析出物件
      *
      * @param inputStream
      *            來源的FileInputStream
      * @return回傳包含物件陣列的資料 (回傳可以不只一個物件陣列)
      * @throws SAXException
      * @throws ParserConfigurationException
      * @throws IOException
      */

     public Object[] getData(InputStream inputStream) throws SAXException,

                IOException, ParserConfigurationException

     {

           Object[] data;

           /* 產生SAXParser物件 */

           SAXParserFactory spf = SAXParserFactory.newInstance();

           SAXParser sp = spf.newSAXParser();

           /* 產生XMLReader物件 */

           XMLReader xr = sp.getXMLReader();

           /* 設定自定義的MyHandlerXMLReader */

           if (xmlParsingHandler == null)

           {

                throw new NullPointerException(“xmlParsingHandler is null”);

           } else

           {

                xr.setContentHandler(xmlParsingHandler);

                /* 解析XML */

                xr.parse(new InputSource(inputStream));

                /* 取得RSS標題與內容列表 */

                data = (Object[]) xmlParsingHandler.getParsedData();

           }

           inputStream.close();

           return data;

     }

 

     /**
      * XML的剖析出物件 (多載方法)
      *
      * @param urlPath
      *            url網址
      * @throws IOException
      * @throws SAXException
      * @throws ParserConfigurationException
      */

     public Object[] getData(String urlPath) throws SAXException, IOException,

                ParserConfigurationException

     {

           URL url = new URL(urlPath);

           HttpURLConnection uc = (HttpURLConnection) url.openConnection();

           uc.setConnectTimeout(15000);

           uc.setReadTimeout(15000); // 設定timeout時間

           uc.connect(); // 開始連線

           int status = uc.getResponseCode();

           if (status == HttpURLConnection.HTTP_OK)

           {

                Object[] data = getData(url.openStream());

                return data;

           }

           return null;

     }

}

 

好了,這裡就是XML讀取的核心程式

只有二個方法,一個輸入InputStream,另一個是網址

這樣預留,到時候可以 讀取XML檔案

這裡提的是網路抓取嘛,所以當然是使用網址的方法摟

 

這裡有出現一個

uc.connect();

所以說,這是要放在另一個執行緒去執行的  (Android 4.0以後的環境,直接跑絕不會給過)

至於SimpleXMLParsingHandler是甚麼?等等就會看見了

 

 

XML剖析處理細節 SimpleXMLParsingHandler.java

package com.J_Test.XMLParserTest.Module;

import java.util.Stack;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import android.util.Log;

 

/**
 * 處理XML的方法細節的Class 有四個方法必須覆寫而且要呼叫super方法
 */

public abstract class SimpleXMLParsingHandler extends DefaultHandler

{

     protected static final String TAG = “ParsingHandler”;

     /** XML解析Node的堆疊 */

     private Stack<String> in_node;

     public Stack<String> getInNode()

     {

           return in_node;

     }

 

     /** 除錯模式(手動設定成true會顯示Log) */

     private boolean debugMode = false;

     /**
      * 將轉換的資料回傳
      */
     public abstract Object getParsedData();

     /**
      * XML文件開始解析時呼叫此method,這裡要加上new出自訂的物件的程式
      */

     @Override
     public void startDocument() throws SAXException

     {

           in_node = new Stack<String>();

     }

 

     /**
      * XML文件結束解析時呼叫此method
      */

     @Override
     public void endDocument() throws SAXException

     {

     }

 

     /**
      * 解析到Element的開頭時呼叫此method
      */

     @Override
     public void startElement(String namespaceURI, String localName,

                String qName, Attributes atts) throws SAXException

     {

           if (isDebugMode())

           {

                Log.v(TAG, “startElement:    qName=” + qName);

                for (int i = 0; i < atts.getLength(); i++)

                {

                     Log.v(TAG, “tt atts[“ + i + “]getQName=” + atts.getQName(i));

                     Log.v(TAG, “tt atts[“ + i + “]getValue=” + atts.getValue(i));

                }

           }

           in_node.push(qName);

     }

 

     /**

      * 解析到Element的結尾時呼叫此method

      */

     @Override

     public void endElement(String namespaceURI, String localName, String qName)

                throws SAXException

     {

           if (isDebugMode())

                Log.v(TAG, “endElement:    qName=” + qName);

           in_node.pop();

     }

 

     /** 取得Element的開頭結尾中間夾的字串 */

     @Override

     public void characters(char ch[], int start, int length)

     {

           String fetchStr = new String(ch).substring(start, start + length);

           // printNodePos();

           if (isDebugMode())

                Log.v(TAG, “t characters:    ch=” + fetchStr);

           characters(fetchStr);

     }

 

     /**
      * 取得Element的開頭結尾中間夾的字串這裡需要做「新增Node的上所有資料」
      *
      * @param fetchStr
      *            取得到的字串
      */

     public void characters(String fetchStr)

     {

     }

 

     // ————————————————————————————–

     /**

      * 印出現在Node的位置,除錯用。例如:rss -> channel -> title 

      */

     public String printNodePos()

     {

           StringBuffer sb = new StringBuffer();

           // 印出現在Node的位置

           for (int i = 0; i < in_node.size(); i++)

           {

                if (i > 0)

                     sb.append(” -> “);

                sb.append(in_node.get(i));

           }

           sb.append(“n”);

           return sb.toString();

     }

 

     /**

      * 在參數堆中找到我要的參數

      */

     public static String findAttr(Attributes atts, String findStr)

     {

           int i;

           for (i = 0; i < atts.getLength(); i++)

           {

                if (atts.getQName(i).compareToIgnoreCase(findStr) == 0)

                {

                     break;

                }

           }

           return atts.getValue(i);

     }

 

     public void setDebugMode(boolean debugMode)

     {

           this.debugMode = debugMode;

     }

 

     public boolean isDebugMode()

     {

           return debugMode;

     }

}

 

這個class呢…因為有abstract,所以必須要繼承實作 (當做函式庫了嘛)

其中加了很多不錯的函式,例如:

public static String findAttr(Attributes atts, String findStr)

找到我要的屬性

public String printNodePos()

印出路徑等等

 

路徑的概念就是上篇所說的,用個堆疊(Stack) 就可以搞定!

眼尖的你會發現,怎麼會有個

public void characters(String fetchStr)

然後甚麼都沒寫的放在那裡

其實在標準的

public void characters(char ch[], int start, int length)

就可看出端倪,我只是把擷取到的文字直接去呼叫只有String的參數的方法
到時候便於判斷

到目前為止,跟我們的RSS沒甚麼關連….

 

 

RSS新聞資料處理 RssNewsXMLParsingHandler.java

package com.J_Test.XMLParserTest.ParsingHandler;

import java.util.Stack;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import android.util.Log;
import com.J_Test.XMLParserTest.RssNews;
import com.J_Test.XMLParserTest.Module.SimpleXMLParsingHandler;

 

/**

 * 記錄著Rss新聞資料的解析XML處理方式的class (繼承了SimpleXMLParsingHandler

 */

public class RssNewsXMLParsingHandler extends SimpleXMLParsingHandler

{

     private static final String TAG = “RssNews ParsingHandler”;

     /** 用來儲存Rss新聞的物件 */

     private RssNews newsItem;

     /** 用來儲存Rss新聞的物件Stack(堆疊) */

     private Stack<RssNews> mNewsItem_list;

 

     /** 建構子 */

     public RssNewsXMLParsingHandler()

     {

     }

 

     /**

      * @return回傳RssNews[]。程式會將讀到的物件{ RssNews[] }包成Object[]然後回傳

      */

     @Override

     public Object[] getParsedData()

     {

           RssNews[] Arr_RssNews = (RssNews[]) mNewsItem_list

                     .toArray(new RssNews[mNewsItem_list.size()]);

           // 解析結果回報

           Log.v(TAG, String.format(“RssNews Count=%d”, Arr_RssNews.length));

           return new Object[] { Arr_RssNews };

     }

 

     /**

      * XML文件開始解析時呼叫此method

      */

     @Override

     public void startDocument() throws SAXException

     {

           super.startDocument();

           // 在文件開始的時候,宣告出該RssNews形態的Stack(堆疊)

           mNewsItem_list = new Stack<RssNews>();

     }

 

     /**

      * XML文件結束時呼叫此method

      */

     @Override

     public void endDocument() throws SAXException

     {

           super.endDocument();

     }

 

     /**

      * 解析到Element的開頭時呼叫此method

      */

     @Override

     publicvoid startElement(String namespaceURI, String localName,

                String qName, Attributes atts) throws SAXException

     {

           super.startElement(namespaceURI, localName, qName, atts);

           // 若搞不清楚現在在哪裡的話可以用printNodePos();

           // printNodePos();

           if (getInNode().size() >= 3
                     && getInNode().get(getInNode().size() – 3).equals(“rss”)
                     && getInNode().get(getInNode().size() – 2).equals(“channel”)
                     && getInNode().get(getInNode().size() – 1).equals(“item”))

           {

                // rss -> channel -> item這個位置中

                // 新增一個RssNews

                newsItem = new RssNews();

           }

     }

 

     /**

      * 解析到Element的結尾時呼叫此method

      */

     @Override

     public void endElement(String namespaceURI, String localName, String qName)

                throws SAXException

     {

 

           if (getInNode().size() >= 3
                     && getInNode().get(getInNode().size() – 3).equals(“rss”)
                     && getInNode().get(getInNode().size() – 2).equals(“channel”)
                     && getInNode().get(getInNode().size() – 1).equals(“item”))

           {

                // rss -> channel -> item這個位置中

                // 新增一筆新聞資料到 Stack(堆疊)

                mNewsItem_list.add(newsItem);

                newsItem = null;

           }

           super.endElement(namespaceURI, localName, qName);

     }

 

     /**

      * 取得Element的開頭結尾中間夾的字串

      */

     @Override

     public void characters(String fetchStr)

     {

           if (getInNode().size() >= 4
                     && getInNode().get(getInNode().size() – 4).equals(“rss”)
                     && getInNode().get(getInNode().size() – 3).equals(“channel”)
                     && getInNode().get(getInNode().size() – 2).equals(“item”))

           {

                // rss -> channel -> item -> XXX這個位置中

 

                // 新增Node的上所有資料

 

                // rss -> channel -> item -> title這個位置中

                if (getInNode().lastElement().equals(“title”))

                     // 設定標題

                     newsItem.setTitle(fetchStr);

                // rss -> channel -> item -> link這個位置中

                else if (getInNode().lastElement().equals(“link”))

                     // 設定連結

                     newsItem.setLink(fetchStr);

                // rss -> channel -> item -> pubDate這個位置中

                else if (getInNode().lastElement().equals(“pubDate”))

                     // 設定發佈日期

                     newsItem.setPubDate(fetchStr);

           }

     }

}

 

這就是我們的重點了,因為有我們自訂的SimpleXMLParsingHandler幫忙

程式碼簡潔多了

我們只要判斷 getInNode() 裡面的內容就行了

配合characters(String fetchStr)endElement()

就可以把資料塞進物件裡然後依序排好

 

順帶一提,最後

public Object[] getParsedData()

會把整理好的物件陣列,用包陣列的方式回傳

到時候只要強制轉型(cast)到指定物件格式就可以了

[Android] 要學會的關鍵技術—XML的讀取(1)

device-2012-03-23-142254  

系列文章:

[Android] 要學會的關鍵技術—XML的讀取(1) 

[Android] 要學會的關鍵技術—XML的讀取(2) 

[Android] 要學會的關鍵技術—XML的讀取(3) 

 

在Android開發之中,很重要的就是跟網路連線

今天談論XML的資料格式的傳遞

在Android的XML解析上有二種方式:

  1. DOM (Document Object Model),他會把整份XML檔案載入,然後成為一個樹狀物件

  2. SAX (Simple API for XML),照順序從頭向下讀,其中讀到一個節點、屬性…等,就採用事件的方式處理

很多效能測試上,SAX比DOM更有效率
這次的範例也是用SAX做的

 

這要配合XML格式來看

XML無所不在,最常用的RSS、你的Android的版面檔…

舉個RSS的例子好了,RSS也是用XML去做的

例如 Yahoo!奇摩 旅遊新聞

http://tw.news.yahoo.com/rss/travel

你用Chrome打開可能會長這樣

2013-01-06 22 32 32   

那是Chrome已經幫你整理過了,所有的元素(element)旁都有個箭頭可以縮放

這樣還是看不懂,沒關係,我來幫你整理一下
一個旅遊新聞RSS大概長這樣
(以下內容有部份元素省略)

 

<?xml version=“1.0” encoding=“utf-8”?>

<rss version=“2.0” >

    <channel>

        <title>旅遊新聞頭條新聞 – Yahoo!奇摩新聞</title>

        <link>http://tw.news.yahoo.com/travel/</link>

        <description>(…)</description>

        <language>zh-Hant-TW</language>

        <pubDate>Sun, 06 Jan 2013 05:30:00 +0800</pubDate>

        <ttl>5</ttl>

        <item>

            <title>冬日泡湯香港客愛北投</title>

                <link>http://tw.news.yahoo.com/(…)-024412185.html</link>

            <pubDate>Sun, 06 Jan 2013 10:44:12 +0800</pubDate>

                <description>(…)</description>

        </item>

    </channel>

</rss>

 

就如從剛剛所提到,RSS是照著XML的格式規範走的
開頭第一行就有XML的宣告,之後的內容就跟HTML感覺很像啦

這文件包含了RSS的channel(頻道)、頻道的名字、連結、頻道介紹、語言別、更新日期…等

item裡面的東西比較重要,代表一個RSS項目(Maybe是一篇文章、新聞),它的標題、連結、時間、簡介…等

 


再看一個例子好了,例如小弟部落格的RSS

http://feed.pixnet.net/blog/posts/rss/j796160836

內容節錄在這:

<?xml version=“1.0” encoding=“UTF-8”?>

<rss xmlns:content=“http://purl.org/rss/1.0/modules/content/” xmlns:atom=“http://www.w3.org/2005/Atom” version=“2.0”>

  <channel>

    <title><![CDATA[清新下午茶 :: 痞客邦 PIXNET ::]]></title>

    <link>http://j796160836.pixnet.net/blog</link>

    <description><![CDATA[夏天的午後,來杯下午茶,分享你我的心。]]></description>

    <pubDate>Thu, 15 Nov 2012 08:11:58 +0000</pubDate>

    <copyright>Copyright 2003-2013 Johnny ,Pixnet Digital Media Coporation. All rights reserved.</copyright>

    <generator>PIXNET Media Digital Coporation</generator>

    <language>zh</language>

    <docs>http://blogs.law.harvard.edu/tech/rss</docs>

    <atom:link rel=“hub” href=“http://pubsubhubbub.appspot.com:80”/>   

    <item>

      <title><![CDATA[[Android] 使用HTTPPOST方式和網頁表單溝通 (加上資料庫、執行緒)]]></title>

      <link>http://j796160836.pixnet.net/blog/post/30577968</link>

      <guid>http://j796160836.pixnet.net/blog/post/30577968</guid>

      <description><![CDATA[  (…) ]]></description>

      <content:encoded><![CDATA[  (…]]></content:encoded>

      <pubDate>Thu, 05 Apr 2012 16:19:35 +0000</pubDate>

      <category>Android</category>

      <comments>http://j796160836.pixnet.net/blog/post/30577968#comments</comments>

    </item>

  </channel>

</rss>

 

雖然內容比較多,但很多只要看重點就可以了

從剛剛的例子知道

要找這個頻道的名稱要找

rss -> channel -> title

要找一個項目(文章)的標題,就

rss -> channel -> item -> title

(其實這只是方便理解,表示路徑有正規的寫法,叫XPath …有興趣可以google一下)

這裡多的xmlns:contentxmlns:atomatom:link

都只是宣告不重要

但這裡多了個<content:encoded></content:encoded>標籤
它跟<description></description>的差別

只在於content:encoded是用HTML標籤格式化過的

description是純文字

 

眼尖的你應該有發現<![CDATA[   ]]>符號

它是告訴剖析器(parser),用這符號括起來的內容,沒有做任何的跳脫處理

例如:< 符號要寫成 &lt; 等等

請視為整段文字做處理

 

因為它是RSS,所以有格式規定

如果是你自己寫XML文件的話,格式都可以自己訂

 


 

剛剛提到了SAX採用事件的方式處理,所以我簡單列出以下的一些事件callback函數

 

文件類:

     * XML文件開始解析時呼叫此method

    public void startDocument() throws SAXException

     * XML文件結束時呼叫此method

    public void endDocument() throws SAXException

節點類:

     * 解析到Element的開頭時呼叫此method

    public void startElement(String namespaceURI, String localName,

            String qName, Attributes atts) throws SAXException 

     * 解析到Element的結尾時呼叫此method

    public void endElement(String namespaceURI, String localName, String qName)

            throws SAXException

節點內容:

     * 取得Element的開頭結尾中間夾的字串

    public void characters(String fetchStr)

 

到時候配上程式碼就大致就會知道了

它到時候要接一個DefaultHandler實做以上方法

 

我的話通常會把RSS資料擺到自己設計的物件(Object)裡面

到時候直接存檔,用ArrayList配合ListView做資料展示都很方便

 

像在startDocument()的時候通常會做一些變數的宣告(ArrayList)

SAX的問題就是:我只知道讀到節點了,但我不知道讀到哪一個節點(多深)

很多書上都是寫用元素的名稱做判斷

但我提出一個更方便更精準的做法

 

我把讀取的歷程用Stack(堆疊)記錄下來

意指在 startElement() 時把qName給push進去

in_node.push(qName); 

到了 endElement() 時把它pop掉

in_node.pop();

這個很簡單的動作我就可以知道我的歷程了

 

 

這篇先講概念,後面的程式碼才會看得比較有重點

[Android] 要學會的關鍵技術—XML的讀取(2) 

[Android] 要學會的關鍵技術—XML的讀取(3)  

 


 

參考資料

 

RSS的介紹

http://zh.wikipedia.org/zh-tw/RSS

http://tw.info.yahoo.com/rss/rookie.html

SAX的剖析方式

http://zh.wikipedia.org/zh-tw/SAX

CDDATA的說明

http://ianjung1974.blogspot.tw/2008/04/cdata-xml.html

Android 解析 XML

http://www.dotblogs.com.tw/nethawk/archive/2011/05/02/24047.aspx

 

 

[Java] Eclipse的偏好設定(操作習慣和好用技巧)

2012-11-15 15 55 03

實在不得不說,Eclipse真的是個很強大的IDE

有些好用快捷鍵在還沒有開始設定偏好設定前先分享一下
這些快捷鍵

Ctrl + Shift + F    自動排版(超好用

Alt + /                 開啟字彙選擇框(自動完成框)
Ctrl + D               刪除一行
Ctrl + /                註解/解除註解多行
Ctrl + B               建置專案
Ctrl + L               到指定行號(一般編輯器都是Ctrl + G)
Ctrl + 1               跳出修正建議框

 

 


其實這篇的產生因為重灌電腦,常常好多Eclipse好用的偏好設定都忘了設定上去
然後選項又超多,分類錯綜複雜 

除了做個備份,也一併分享給大家

這些路徑不用強記,可以憑印象打關鍵字,很多選項就會跳出來了唷

 

 

專案的編碼格式(Encoding)

這我不知為何,Eclipse它的預設值是ANSI

在還沒有專案的時候,可以像我一樣調整成utf-8

但是如果已有專案的話,文字有可能會變亂碼唷

這時候用convertz救援吧

 

路徑:General > Workspace

關鍵字:encoding

2012-11-15 15 57 41

Text file encoding 的地方,文字框打入 utf-8

另外,Build automatically 的地方,我喜歡把勾勾去掉

需要的時候手動按 Ctrl + B 建置專案

 

 

字體大小設定

我雖然沒有老花,但就是不喜歡字體小小的糊在一起,對Eclipse第一個開刀的一定是字體大小

字體大一點,自己看得也舒服

路徑:General > Appearance > Colors and Fonts

關鍵字:font

2012-11-15 15 59 51

在Basic裡的Text Font修改字體大小

如果只是程式碼,其實只要調Text Font就好,其他會跟著Text Font去調整

至於中文字嘛…預設的字型調過了之後,中文字還是很小
這時可能要調字型,至於字型…每個人的適應能力不同

通常是找每個字體間距相等的為佳,這部份留給大家自行嘗試摟 

 

 

自動格式化設定

路徑:Java > Code Style > Formatter

關鍵字:Format

Eclipse最強大的功能就是「自動格式化(Auto Format)」  (灑花)

在coding的時候可以按個快捷鍵 Ctrl + Shift + F

在凌亂的格式,都整得服服貼貼

 

 

因為受大學老師程式碼風格影響,大括弧「 { 」一定要換一行

所以我們就這樣對應調整

2012-11-15 16 03 46

Eclipse預設風格是不給調的,複製一份設定檔即可

按下New,打入一個喜歡的名字

2012-11-15 16 05 23

在Braces裡,除了最後一個之外,其它都設定成Next line
右邊有預覽窗格,可以邊調邊看效果 

 

 

自動完成框

不只是Eclipse,很多整合開發環境(IDE)都會提供自動完成框

尤其是Visual studio,打幾個字就跳出候選字選取框

就像你在用google一樣簡單

因為電腦CPU等等的條件影響,預設不是甚麼鍵都觸發之
但我們可以把他打開

 

路徑:Java > Editor > Content Assist

關鍵字:auto

2012-11-15 16 07 10

這個自動完成的功能,因為受到網路文章的影響

發現大為好用,故分享給大家

我就直接轉載了

 

勾選 "Enable auto-activation" 的選項
Auto activation delay 為提示出現的延遲時間,建議可以設為 0ms (預設是200ms)
Auto activation triggers for Java 為 IDE 遇到何種字元會自動啟動提示,預設只有 dot,請改為 .abcdefghijklmnopqrstuvwxyz(,
Auto activation triggers for Javadoc 在註解區塊中遇到何種字元會啟動提示,預設是 @ 及 #

 

這個Auto activation triggers for Java,如果CPU不夠力的時候,可以調回預設值:點點 「 .

手動按 alt + / 也是會跳出來啦

 

參考:

http://icercat.pixnet.net/blog/post/23671027

 

ADB連接逾時

這個選項是從這裡來的

http://j796160836.pixnet.net/blog/post/29108155

在開發Android,可以用wifi 來做打開除錯 (就像是連接USB一樣)

但這功能需要root

 

最近是遇到當網路環境不穩定時,連接常常逾時(timeout)

所以可以在這裡設定timeout的時間

路徑:Android > DDMS

2012-11-15 15 55 37

 

ADB connection time out (ms): 預設是5000

經由測試,大概改到80000足夠

 

 


將會不定時增加…

[RDP] 遠端桌面使用的常用快捷鍵

因為常常使用遠端桌面,太常忘記了要怎麼按

在遠端桌面按 Ctrl + Alt + Delete 了,就筆記一下

 

本機快速鍵 遠端桌面快速鍵 功能說明
CTRL + ALT + DEL CTRL + ALT + END

顯示 [Windows 安全性] 對話方塊

CTRL + ALT + BREAK

在視窗和全螢幕顯示模式間切換。

Win Key 或 CTRL + ESC

ALT + HOME

顯示 [開始] 功能表。

ALT + TAB

ALT + PAGE UP

從左到右切換視窗
SHIFT + ALT + TAB

ALT + PAGE DOWN

從右到左切換視窗
PrintScreen

CTRL + ALT + 數字鍵上的加號(+)

將遠端的整個螢幕畫面複製回本機。
ALT + PrintScreen

CTRL + ALT + 數字鍵上的減號(-)

將遠端的作用中的螢幕畫面複製回本機。

 

資料來源

http://blog.miniasp.com/post/2008/07/22/The-hotkey-usage-in-Remote-Desktop-environment.aspx

http://windows.microsoft.com/zh-HK/windows-vista/What-shortcut-keys-can-I-use-in-Remote-Desktop-Connection

[JSP] JSP連接MySQL初探

這篇算是因為網友詢問,才會有的一篇文章吧

 

最近也在看JSP的一些寫法

因為還沒有看很懂,所以這一篇一直都沒有寫

用Java跑網頁有二種型態

  • Servlet
  • JSP

Servlet可以算是JSP的前身,可以處理比較複雜的事情
JSP的寫法比較像PHP,那我們就從這裡開始吧

範例不難,但環境設定上頗麻煩的

——————————————————–

環境設定

再開始之前,先講一下環境設定

標題是連MySQL資料庫嘛,所以要有MySQL取得方式我就不細講了

有在寫PHP+MySQL的話,目前在使用的MySQL就大方的借過來用吧

 

 

若是使用整合環境(如appserv、wamp、xampp…等等)

就只需要補上JDK、Tomcat、MySQL Connecter,官方下載在這裡:

JDK

http://www.oracle.com/technetwork/java/javase/downloads/index.html

Tomcat

http://tomcat.apache.org/download-70.cgi

MySQL Connecter for Java

http://www.mysql.com/downloads/connector/j/

選擇你的作業系統看是x86還是x64,選擇對應的檔案安裝

然後用Next大法(一直Next),一路給他裝完

 

如果,你像我一樣覺得這樣裝很凌亂,或是說是新建環境,甚麼都沒有的話

可以採用新版的XAMPP 1.81

http://www.apachefriends.org/zh_tw/xampp.html

這個版本裡面就有附tomcat摟

少一個要補檔的對象

接下來只要下載JDK + MySQL Connecter就行摟!

 

 

個人是建議用JDK+XAMPP的配置,或是整合環境+JDK+官方tomcat

(對了,新版含tomcat的XAMPP不能跟tomcat混裝,路徑會錯亂…)

XAMPP他主要功能有包入Apache HTTP Server、MySQL Server、FileZilla FTP Server、Mail Server、Tomcat Server

細項有php、pear、perl、cgi、phpmyadmin、mbstring、gd….等等(糟糕離題了…)

 

反正,整合環境有他的好處,除了設定檔要自己設定之外

其他大多都設定好了

 

 

MySQL Connector的地方先說明一下

只要下載完畢,解壓縮

取出mysql-connector-java-5.1.22-bin.jar這個檔案就好,壓縮檔裡的其他資料可以不用

(筆者抓到的是Connector/J 5.1.22版本,所以檔案叫做mysql-connector-java-5.1.22-bin.jar

請依照你下載的版本做變化)

然後將它放到tomcat的目錄的lib裡,所以變成

官方Tomcat路徑:

C:\Program Files\Apache Software Foundation\Tomcat 7.0\lib\mysql-connector-java-5.1.22-bin.jar

XAMPP包含tomcat路徑:

C:\xampp\tomcat\lib\mysql-connector-java-5.1.22-bin.jar

 

環境變數

主要有點麻煩的是Java的環境設定

Windows環境變數的方法在這裡:

WinXP在我的電腦按滑鼠右鍵 -> 內容 -> (上方頁籤)進階 -> 環境變數

Win7是在開始 -> 我的電腦按右鍵 -> 內容 -> (在左側欄)進階系統設定 -> (上方頁籤)進階 -> 環境變數

 

要添加這些環境變數

純JAVA環境
———————
JAVA_HOME
C:\Program Files\Java\jdk1.6.0_35
CLASSPATH
.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\jre;%JAVA_HOME%\src
Path
.;%JAVA_HOME%\bin

JAVA環境+Tomcat網頁伺服器環境
———————
JAVA_HOME
C:\Program Files\Java\jdk1.6.0_35
CATALINA_HOME
(官方Tomcat路徑)
C:\Program Files\Apache Software Foundation\Tomcat 7.0
 
(XAMPP包含tomcat路徑)
C:\xampp\tomcat
(二者依環境,擇其一使用) 

CLASSPATH
.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\jre;%JAVA_HOME%\src;%CATALINA_HOME%\lib\servlet-api.jar;%CATALINA_HOME%\lib\mysql-connector-java-5.1.22-bin.jar
Path
.;%JAVA_HOME%\bin

有些地方要注意

如果裡面有值的話(像是Path),打個分號 ; 再連接上去

藍字的地方是他的版本號,要依照你的版本做變化(查看一下該路徑是否有東西)

設定完畢要重新開機(使用者登出再登入)才會生效

這樣就設定完成了

 

弄到這裡可以先測試一下

phpmyadmin是否能正常連線MySQL?(代表php+MySQL正常)

tomcat是否正常啟動? http://localhost:8080/ 有沒有東西?

 

—————————————————————————-

建立範例DB

終於回到程式面了,可以開個資料庫名字叫test_jspdb

執行以下SQL;

CREATE TABLE IF NOT EXISTS `employee` 
`emp_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`emp_name` varchar(100) NOT NULL,
`emp_age` int(11) NOT NULL,
PRIMARY KEY (`emp_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3;

INSERT INTO `employee` (`emp_id`, `emp_name`, `emp_age`) VALUES
(1, ‘mary’, 20)
(2, ‘amy’, 22);

 

資料表內容很簡單,就只有員工姓名,員工年齡而已

—————————————————————-

 

JSP範例

這時候可以建立一個連線的範例來做了

網站的根目錄在:

C:\xampp\tomcat\webapps\ROOT

C:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps\ROOT

在那裡建立一個空檔案db_test.jsp然後貼上以下程式碼。

然後瀏覽 http://localhost:8080/db_test.jsp 看看能不能使用

如果出現can’t load mysql driver代表說MySQL Connector的設定有問題

查看檔案位置是否正確及環境變數設定是否有更新

 

 

 

<%@ page contentType=”text/html;charset=utf-8″%>

<%@ page import=”java.sql.*”%>
<%
try
{
//讀取mysqlDriver驅動程式
Class.forName(“org.gjt.mm.mysql.Driver”).newInstance();

try
{
//連接mysql資料庫

// 資料庫名稱”zend_test”,帳號”root”,密碼”123456″,
// 使用Unicode編碼”true”,字元集”UTF-8″
String db_user=”root”;
String db_pwd=”12345″;
String db_database=”test_jspdb”;
Connection conn= DriverManager.getConnection(“jdbc:mysql://localhost:3306/”+db_database+”?user=”+db_user+”&password=”+db_pwd+”&useUnicode=true&characterEncoding=UTF-8″);

try
{
//建立statement
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
try
{
//建立SQL查詢
String sql=”select * from album”;
ResultSet rs = stmt.executeQuery(sql);

%>

<h2>Employee</h2>
<table border=1>
<tr><th>id</th><th>artist</th><th>title</th></tr>
<%
//顯示資料

while(rs.next())
{
%>
<tr>
<td><%=rs.getString(“id”)%></td><td><%=rs.getString(“artist”)%></td><td><%=rs.getString(“title”)%></td>
</tr>
<%
}
%>
</table>
<%

// 關閉連線
rs.close();
rs = null;
stmt.close();
stmt = null;
conn.close();

}
catch (Exception ex)
{
out.println(“can’t read data”);
out.println(ex.toString());
}
}
catch (Exception e)
{
out.println(“can’t create statement”);
out.println(e.toString());
}
}
catch(Exception e)
{
out.println(“can’t content mysql database”);
out.println(e.toString());
}

}
catch(Exception e)
{
out.println(“can’t load mysql driver”);
out.println(e.toString());
}

%>

 

 寫法跟PHP差不多吧!有個重點要提一下

 

其餘的update insert delete指令可以這樣寫)

String sql = “INSERT INTO `employee` (`emp_name`, `emp_age`) VALUES
(‘mary’, 20),”;

// 執行SQL語法
Statement stmt = conn.createStatement();
stmt.executeUpdate(sql);

 

你可能會疑惑createStatement這個方法

ResultSet.TYPE_FORWARD_ONLY (預設值)

就只能使用next()方法取得下一筆(指標順序定位)

 

ResultSet.TYPE_SCROLL_INSENSITIVE與 ResultSet.TYPE_SCROLL_SENSITIVE

能使用afterLast()、previous()、absolute()、relative()其他方法

有 ResultSet.CONCUR_READ_ONLY與ResultSet.CONCUR_UPDATABLE兩個參數可以設定,前者表示只能讀取 ResultSet的資料,後者表示可以直接使用ResultSet來操作資料庫

(這個部份還沒有驗證,我想應該跟update insert delete指令無關)

 

如果有誤煩請指正

 

參考資料

http://caterpillar.onlyfun.net/Gossip/JavaGossip-V2/ResultSetCursor.htm

http://jjnnykimo.pixnet.net/blog/post/21585335-jsp%E9%80%A3%E7%B5%90mysql%E8%B3%87%E6%96%99%E5%BA%AB%E7%AF%84%E4%BE%8B

http://blog.yam.com/carl44/article/14825336

http://blog.alumni.nctu.edu.tw/plate/web/papermsg.jsp?UI=markcool&PI=96 

[MySQL] 數字10以下的中文數字排序(或是列表排序)

這是網路上參考別人寫的方式,靈機一動想到的

因為想到這個方法覺得很BG且好笑
就當個茶餘飯後的笑話分享給大家

在這之前還是先呼籲一下,

在建立DB的時候,數字就應該用數字的格式儲存

 

不要像我犯同樣的錯誤
拿小寫的中文數字(一二三四五六七八九) 
或是大寫的中文數字(壹貳參肆伍陸柒捌玖拾)

去儲存數字,然後自找苦吃

因為它的ASCII的code大小也沒照順序(所以資料庫的文字排序失效) 

————————————————————

網路上對於MSSQL有個解法
就是使用列表比對的方式

也有人使用自訂函數去parse中文數字然後轉換成對應的數字

也可以利用一個對應的轉換表,用inner join的方式去做

————————————————————

在MySQL裡,我找到一個還不錯的做法:

http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_locate

Locate函數:

Locate(欄位名稱, 搜尋比對的字串)

找尋字串中,第一個出現的位置,並回傳其位置

而這位置就是我們要的順序結果(反正多大也不重要,至少相對順序是對的)

如果我有一張表table01

todo  week 
寫作業  一 
買東西  三 
聚餐  二 
看電影  四 

想照星期排序(這就中文數字了吧….Orz)

就這樣下

select *, LOCATE( week,  ‘一二三四五六日’ ) from table01 order by LOCATE( week,  ‘一二三四五六日’ );

聰明的你,就會在phpmyadmin看到這個結果,然後就會跟我一樣大笑XDD

todo  week  LOCATE( week,  ‘一二三四五六日’ )
寫作業  一  1
聚餐  2
買東西  三  3
看電影  四  4

 

理論上,只要是不重複的字串應該都可以適用

拜託鞭小力點…

[Fedora 14-17] 架設VPN Server (pptpd)

安裝PPTPD及相關服務

yum install -y rp-pppoe gcc pptp pptp-setup  ppp ppp-devel
 
安裝方式有二種:
 
RPM安裝(要依照Linux的版本安裝)
 
例如Fedora 14 (32bit)
wget http://poptop.sourceforge.net/yum/stable/fc14/i386/pptpd-1.3.4-2.fc14.i686.rpm
rpm -ivh pptpd-1.3.4-2.fc14.i686.rpm
 
Fedora 14 (64bit)
wget http://poptop.sourceforge.net/yum/stable/fc14/x86_64/pptpd-1.3.4-2.fc14.x86_64.rpm
rpm -ivh pptpd-1.3.4-2.fc14.x86_64.rpm
 
YUM安裝(要依照Linux的版本安裝)
 
rpm -ivh http://poptop.sourceforge.net/yum/stable/fc14/pptp-release-current.noarch.rpm
yum install pptpd
 
 
下載並安裝核心模組
 
 
wget http://sourceforge.net/projects/poptop/files/mppe%20module%20builder/kernel_ppp_mppe-1.0.2%20dkms-2.0.6/kernel_ppp_mppe-1.0.2-3dkms.noarch.rpm/download
 
wget http://downloads.sourceforge.net/project/poptop/mppe%20module%20builder/kernel_ppp_mppe-1.0.2%20dkms-2.0.6/kernel_ppp_mppe-1.0.2-3dkms.noarch.rpm?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fpoptop%2Ffiles%2Fmppe%2520module%2520builder%2Fkernel_ppp_mppe-1.0.2%2520dkms-2.0.6%2F&ts=1341655470&use_mirror=nchc
 
wget http://downloads.sourceforge.net/project/poptop/mppe%20module%20builder/kernel_ppp_mppe-1.0.2%20dkms-2.0.6/dkms-2.0.6-1.noarch.rpm?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fpoptop%2Ffiles%2Fmppe%2520module%2520builder%2Fkernel_ppp_mppe-1.0.2%2520dkms-2.0.6%2F&ts=1341655518&use_mirror=nchc
 
rpm -ivh dkms-2.0.6-1.noarch.rpm
rpm -ivh kernel_ppp_mppe-1.0.2-3dkms.noarch.rpm
 
 
若沒有按照版本安裝會有類似以下錯誤: 
Error! Bad return status for module build on kernel: 3.4.2-1.fc16.x86_64 (x86_64)
Consult the make.log in the build directory
/var/lib/dkms/kernel_ppp_mppe/1.0.2/build/ for more information.
 
Error! Could not locate ppp_generic.ko for module kernel_ppp_mppe in the DKMS tree.
You must run a dkms build for kernel 3.4.2-1.fc16.x86_64 (x86_64) first.
 
========================================================
 
設定PPTPD
 
 
設定Client看到的伺服器IP,以及DHCP分發的IP範圍
vi /etc/pptpd.conf
加入以下:
localip 10.0.0.1
remoteip 10.0.0.10-100
 
—————————————————-
 
設定pptpd的加密方式和發給Client的DNS
vi /etc/ppp/options.pptpd
refuse-pap
refuse-chap
refuse-mschap
 
require-mschap-v2
require-mppe-128
 
ms-dns 168.95.1.1
 
—————————————————-
 
設定帳號密碼(若使用ppp撥號(xDSL),撥號的帳密也會在這裡)
格式為:
帳號、使用的服務、密碼、接受的IP(通常為*號)
中間用空格隔開
 
vi /etc/ppp/chap-secrets
內容大致為:
# client        server           secret             IP addresses
[email protected]”      *         “your password”
test pptpd 12345 *
 
 
—————————————————- 
 
設定系統IP轉發
vi /etc/sysctl.conf
修改
net.ipv4.ip_forward = 1
 
讓系統重新載入設定值
sysctl -p
 
—————————————————-
 
設定防火牆
 
主要是設定讓PPTP的Client能夠NAT上網
請依照對外連線的網路卡代號取代掉ppp0
ppp+的代表用來連接VPN Client的網卡,不需更動
vi /etc/sysconfig/iptables
 
 
*nat
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -o ppp0 -j MASQUERADE
COMMIT
 
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state –state NEW -m tcp -p tcp –dport 22 -j ACCEPT
# 其他要開啟服務的port依照格式寫在這裡
 
#—-vpn—-
-A INPUT -i ppp0 -p tcp –dport 1723 -j ACCEPT
-A INPUT -i ppp0 -p gre -j ACCEPT
-A FORWARD -i ppp+ -o ppp0 -j ACCEPT
-A FORWARD -i ppp0 -o ppp+ -j ACCEPT
#—-vpn—-
 
-A INPUT -j REJECT –reject-with icmp-host-prohibited
-A FORWARD -j REJECT –reject-with icmp-host-prohibited
COMMIT
 
—————————————————-
 
重啟防火牆(Fedora 14以上使用)
systemctl restart iptables.service
systemctl restart ip6tables.service
 
重啟防火牆(Fedora 14含以下使用)
/etc/init.d/iptables restart

 

 
========================================================
 
啟動PPTPD等服務
 
 
啟動PPTPD服務
/etc/init.d/pptpd start
重啟PPTPD服務
/etc/init.d/pptpd restart
斷除所有VPN連線
/etc/init.d/pptpd restart-kill
 
 
查看相關的Log
tail -n 30 /var/log/messages
 
查看連線情況
netstat -an | grep :1723 | sort
 
========================================================
 

[ASP]在純ASP中操作陣列產生JSON格式

因為專案需求,需要把原本ASP的資料轉成JSON的格式

我知道ASP是大家動態網頁設計的好夥伴(笑)

(迷之音:ASP都出這麼久了,很多都已經轉成ASP.net了幹嘛這麼執著呢?)

就跟你說是專案需求了嘛(巴落去

這只是我的小小筆記,以免有機會又用上找不到怎麼做
尤其是程式語言對於陣列(Array)的操作方式都不大一樣

我盡量強化大家的JSON概念,盡量不特別提程式碼的部份

——————————–

學JSON格式只有二句話:

物件(object)用大括號 { }

陣列(array)用中括號 [ ]

先記住這概念

——————————–

 

ASP要使用JSON要下載此元件:

http://code.google.com/p/aspjson/

我們只需要他的ASP JSON (for production) 就好:
寫文的時候是JSON_2.0.4.asp 

把他放在你的目錄然後用以下方式引用:

<!–#include file=”JSON_2.0.4.asp”–>

這裡有些範例蠻有用的:

http://code.google.com/p/aspjson/wiki/Samples2

 

引用部份範例來說明

物件寫法

<%
Dim o1
Set o1 = jsObject()

      o1(“name”) = “Tom”
      o1(“lastname”) = “Chen”

o1.Flush
%>

顯示

{“name”:”Tom”,”lastname”:”Chen”}

陣列寫法

<%
Dim o2
Set o2 = jsArray()

      o2(Null) = 2
      o2(Null) = 4
      o2(Null) = 6
      o2(Null) = 8

o2.Flush
%>

顯示

[2,4,6,8]

———————

所以我們學到,宣告空白變數使用Dim

決定是何種型態使用 Set 這個字

不要小看這個關鍵字,他可是很有用的

 

 

最後,當你把資料形態設定為jsObject之後

直接像範例一樣 o(“name”) 直接在括號之中放入新的key值,當成變數來指定

 

而資料形態設定為jsArray的時候

可以像範例一樣用o2(Null) 的方式增加值

 

範例集有提到jsArray和jsObject中的對轉,我覺得不是很重要,所以就不引用了

 

再來看比較tricky的

物件包物件

<%
Dim o3
Set o3 = jsObject()

      Set o3(“person”) = jsObject()
            o3(“person”)(“name”) = “Tom”
            o3(“person”)(“lastname”) = “Chen”

      Set o3(“equipment”) = jsObject()
            o3(“equipment”)(“name”) = “keyboard”
            o3(“equipment”)(“type”) = “electronic”

o3.Flush
%>

顯示

{“person”:{“name”:”Tom”,”lastname”:”Chen”},”equipment”:{“name”:”keyboard”,”type”:”electronic”}}

陣列包陣列

<%

Dim o4
Set o4 = jsArray()

      Set o4(Null) = jsArray()
            o4(Null)(Null) = 0
            o4(Null)(Null) = 2
            o4(Null)(Null) = 4
            o4(Null)(Null) = 6

      Set o4(Null) = jsArray()
            o4(Null)(Null) = 1
            o4(Null)(Null) = 3
            o4(Null)(Null) = 5
            o4(Null)(Null) = 7

o4.Flush
%>

顯示

[[0,2,4,6],[1,3,5,7]]

在陣列包陣列的範例中,就會明顯看到
其實程式它是從上到下,照順序執行

雖然 Set o4(Null) = jsArray() 這二行都一樣
但意義不同

難度慢慢增高摟

陣列包物件

<%
Dim o5
Set o5 = jsArray()

      Set o5(Null) = jsObject()
            o5(Null)(“name”) = “Tom”
            o5(Null)(“lastname”) = “Chen”
      Set o5(Null) = jsObject()
            o5(Null)(“name”) = “Amy”
            o5(Null)(“lastname”) = “Lin”

o5.Flush
%>

顯示

[{“name”:”Tom”,”lastname”:”Chen”},{“name”:”Amy”,”lastname”:”Lin”}]

這JSON格式已經接近資料庫撈出來的格式了

物件包陣列

<%
Dim o6
Set o6 = jsObject()
      o6(“name”) = “Tom”
      o6(“lastname”) = “Chen”

      Set o6(“numbers”) = jsArray()
            o6(“numbers”)(Null) = 2
            o6(“numbers”)(Null) = 4
            o6(“numbers”)(Null) = 5
            o6(“numbers”)(Null) = 6

o6.Flush
%>

顯示

{“name”:”Tom”,”lastname”:”Chen”,”numbers”:[2,4,5,6]}

———————

最後跳過中間的步驟,直接開最後的大絕!

陣列包物件包陣列包物件

心理OS:哪那麼多陣列物件呀~

<%
Dim o7
Set o7 = jsArray()

      Set o7(Null) = jsObject()
            o7(Null)(“name”) = “Tom”
            o7(Null)(“lastname”) = “Chen”

            Set o7(Null)(“report”) = jsArray()

                  Set o7(Null)(“report”)(Null) = jsObject()
                        o7(Null)(“report”)(Null)(“subject”)=”Math”
                        o7(Null)(“report”)(Null)(“score”)=80

                  Set o7(Null)(“report”)(Null) = jsObject()
                        o7(Null)(“report”)(Null)(“subject”)=”English”
                        o7(Null)(“report”)(Null)(“score”)=90

      Set o7(Null) = jsObject()
            o7(Null)(“name”) = “Amy”
            o7(Null)(“lastname”) = “Lin”

            Set o7(Null)(“report”) = jsArray()

                  Set o7(Null)(“report”)(Null) = jsObject()
                        o7(Null)(“report”)(Null)(“subject”)=”Math”
                        o7(Null)(“report”)(Null)(“score”)=86

            Set o7(Null)(“report”)(Null) = jsObject()
                        o7(Null)(“report”)(Null)(“subject”)=”English”
                        o7(Null)(“report”)(Null)(“score”)=88

o7.Flush
%>

顯示

[{“name”:”Tom”,”lastname”:”Chen”,”report”:[{“subject”:”Math”,”score”:80},{“subject”:”English”,”score”:90}]},{“name”:”Amy”,”lastname”:”Lin”,”report”:[{“subject”:”Math”,”score”:86},{“subject”:”English”,”score”:88}]}]

看起來很複雜其實並不然

換成XML的格式就長這樣

<data>

    <student>
        <name>Tom</name>
        <lastname>Chen</lastname>

        <report>

            <subject>
                <name>Math</name>
                <score>80</score>
            </subject>
            <subject>
                <name>English</name>
                <score>90</score>
            </subject>

        </report>
    </student>

    <student>
        <name>Amy</name>
        <lastname>Lin</lastname>

        <report>

            <subject>
                <name>Math</name>
                <score>86</score>
            </subject>
            <subject>
                <name>English</name>
                <score>88</score>
            </subject>

        </report>
    </student>

</data>


做成大家看得懂的表格

成績單1

姓名  Tom Chen 
數學 80 
英文  90 

成績單2

姓名  Amy Lin 
數學 86
英文 88 

在回顧一下上面那二個很噁心的寫法
有困難嗎?有任何讓你造成不舒服的感覺嗎? 

 

 

 

===============================================

以下內容看不懂就算了,沒關係

 

最後看看這資料庫的函式QueryToJSON

http://code.google.com/p/aspjson/wiki/SQLtoJSON

FunctionQueryToJSON(dbc, sql)
       
Dim rs, jsa, col
       
Set rs = dbc.Execute(sql)
       
Set jsa = jsArray()
       
WhileNot(rs.EOF Or rs.BOF)
               
Set jsa(Null)= jsObject()
               
ForEach col In rs.Fields
                        jsa
(Null)(col.Name)= col.Value
               
Next
        rs
.MoveNext
       
Wend
       
SetQueryToJSON= jsa
EndFunction

如果上面都看懂的話,只是把欄位名稱和值,用For each印出來,放進jsObject裡而已

rs.Fields就是取得recordset的欄位物件,用

col.Name  取得欄位名
col.Value  取得值

 

若我資料庫有張表

student

s_id  name  lastname 
Tom  Chen 
 Amy Lin 

report

r_id  s_id  subject  score 
Math  80 
English  90
Math  86
English  88

 

是不是我們的資料庫就可以這樣寫呢?

sql = “select * from student”

Set rs = dbc.Execute(sql)
Set jsa = jsArray()
While Not (rs.EOF Or rs.BOF)
   Set jsa(Null) = jsObject()
   For Each col In rs.Fields
      jsa(Null)(col.Name) = col.Value
   Next

   sql2 = “SELECT subject,score FROM report WHERE s_id=”&rs(“s_id”)
   Set rs2 = dbc.Execute(sql2)

   Set jsa(Null)(“report”) = jsArray()
   While Not (rs2.EOF Or rs2.BOF)
      Set jsa(Null)(“report”)(Null) = jsObject()

      For Each col2 In rs2.Fields
          jsa(Null)(“report”)(Null)(col2.Name) = col2.Value
      Next

      rs2.MoveNext
   Wend

   rs.MoveNext
Wend

[Windows Phone]解決Windows Phone SDK抓不到VS2010完整版的問題

意興來潮來玩一下Windows Phone芒果機的開發

在開發環境的部分,除了有Windows 7

還要另外安裝Windows Phone SDK

 

Windows Phone SDK官網下載:

http://www.microsoft.com/zh-tw/download/details.aspx?id=27570

安裝之後,如果沒有Visual Studio 2010的話,他會很貼心的幫你安裝

Visual Studio 2010 Express供你使用


各位版大,不知道是否像我一樣

本身已經安裝好了Visual Studio 2010

 

在安裝之後仍然出現Express版,而本身完整版卻沒有安裝完成

可以遵循以下步驟:

相關樣版,而這問題可透過以下方式解決

要複製二個地方

 

第一個地方,C#版本的Silverlight for Windows Phone資料夾:

C:Program Files (x86)Microsoft Visual Studio 10.0Common7IDEProjectTemplatesCSharpSilverlight for Windows Phone

整個Silverlight for Windows Phone資料夾複製到:

C:Users你的使用者名稱DocumentsVisual Studio 2010TemplatesProjectTemplatesVisual C#


第二個地方,VB版本的Silverlight for Windows Phone資料夾:

C:Program Files (x86)Microsoft Visual Studio 10.0Common7IDEProjectTemplatesVisualBasicSilverlight for Windows Phone

整個Silverlight for Windows Phone資料夾複製到:

C:Users你的使用者名稱DocumentsVisual Studio 2010TemplatesProjectTemplatesVisual Basic

 

注意路徑中Visual Basic的空格,一個有一個沒有

若你的Win7版本是32位元的,把紅字中的(x86)字樣拿掉就是你的路徑

紅字的使用者名稱代換成你的使用者名稱

所以最後你的

C:Users你的使用者名稱DocumentsVisual Studio 2010TemplatesProjectTemplates

的 Visual Basic 和 Visual C# 資料夾都會有同名的但內容不一樣的 Silverlight for Windows Phone 資料夾

2012-06-26 10 42 15  

 

 

然後在開始選單中找到 所有程式 > Microsoft Visual Studio 2010 > Visual Studio Tools > Visual Studio 命令提示字元 (2010)

2012-06-26 09 14 22    

在指令鍵入

devenv.exe /setup

不做這個動作的話,在新增的頁面可以看到但不能建立

2012-06-26 10 07 12  


再重開VS2010即可

在檔案 > 新增 > 專案 之中

就會看到新的專案從你的VS2010出現摟

2012-06-26 10 37 12  

 

參考資料:

http://www.dotblogs.com.tw/ian/archive/2012/02/15/69380.aspx

http://mnc363eo.iteye.com/blog/1351962