總網頁瀏覽量

2013年3月26日 星期二

JSP response request物件

JSP:JavaServerPage

JSP重要的東西:request與response物件

一、request物件
client端輸入網址,這時就是所謂的發出請求給伺服器
伺服器接收到請求會產生所謂的request物件。
這個request物件裡面夾帶clientIP client端資訊   Map物件  屬性物件。
servlet可以從request物件得到client端的資訊,
client的IP、http的方法、browser送來的表單資料

我們可以用request.getParameter("Form標籤<input>的name屬性值")
request.getParameterValues("Form標籤<input>的name屬性值")
讀出使用者輸入的資料。

在接收這些參數以前,程式必須說明瀏覽器所送的文字資料編碼,如此一來程式才能將文字資料正確無誤轉為unicode
request.setCharacterEncoding("UTF-8");


簡單網頁流程:
使用者在網頁輸入資料後,會包裝在request物件裡面,容器接收到請求物件,
經過servlet處理
在網頁秀出結果

準備:
Jsp檔案:準備<input>標籤,種類有checkbox、text,且有name屬性值。
servlet(.java):
從request物件取出使用者輸入的資料,並宣告變數接收從request物件取出的資料
String name = request.getParameter("input標籤的name值");
String[] arrays= request.getParameterValues("input標籤的name值")

取出資料後將資料塞入Bean物件裡面
Bean物件是含有setXXX(),getXXX()的類別所new的物件
OOOOBean obj = new OOOOBean(name,arrays);


 將Bean物件暫存到請求物件內,成為它的屬性物件,屬性物件可以與別的程式共用。
        request.setAttribute("customer",Object obj);

//使用配接器指定目的地網頁      
RequestDispatcher rd = request.getRequestDispatcher("/ch02/displayCustomerInfo.jsp");
//將response與request物件交給目的地網頁
rd.forward(request, response);




二、response物件
由request物件取出資料後,可以利用response物件
產生回應資料給瀏覽器顯示給client看

其中產生回應的資料分成
1.文字性的資料
2.非文字性的資料(圖檔)

1.產生文字資料的回應
必須先宣告要產生什麼文字資料以及回應編碼
本例子設定回應資料格式為text/html 回應的編碼是UTF-8
response.setContentType("text/html; charset=UTF-8");

接著由response取出PrintWriter型別的物件,切記不可與上面setContentType顛倒
PrintWriter output = response.gerWriter();


接著產生回應資料 output.print("這裡跟在html打標籤沒兩樣,同樣地用法跟System.out.print一樣可以印變數");

輸出完畢記得close
output.close();



2. servlet產生非文字性的資料
以圖檔為例。
a.準備圖檔,放在該放的資料夾。

b.準備一個.jsp,秀圖用的
打上<img>tag,src設定為servlet(.java檔案)
<IMG width='640' height='480' SRC="ShowPictureServlet">

c. servlet輸出圖檔

作法跟java SE一樣
也是用InputStream is = new FileInputStream();
read()圖檔,
再利用OutputStream os = new FileOutputStream
write()圖檔

差別在於JSP的圖檔放在每個專案的webcontent目錄底下,java SE圖檔放在硬碟資料夾中
因此讀取檔案的路徑要告訴servlet圖檔放在WebContent底下的目錄路徑。

因為圖檔完整路徑包含使用者電腦名稱,例如:

C:\Users\電腦名稱\JSP\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\example\\images\


所以程式碼要移植到其他電腦上勢必要更動路徑名稱
因此,servlet有彈性獲得檔案路徑的方法,如下
//獲取整個專案的根目錄所在路徑
String imageDir = getServletContext().getRealPath("/");

//底下是專案example根目錄所在的完整路徑 (tmp0稱為整個系統的佈署環境,wtpwebapps存放測試中的應用系統(專案),
C:\Users\XXXX\JSP\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\example\

如果圖檔直屬於webcontent資料夾那麼可以直接用inputstream打開圖檔
InputStream is = new FileInputStream(imageDir+"檔名");


假設圖檔放在WebContent/images/底下:
上面InputStream要改成
InputStream is = new FileInputStream(imageDir+"\\images\\"+檔名);
(雙反斜線避免escape character)

 
servlet要Output圖檔以前必須告訴servlet該回應(response)給瀏覽器什麼樣的資料
response.setContextType("image/jpeg"); //"image/gif"
這行不可以省略
(jpg,jpeg都是用image/jpeg)

之後還必須
從response物件取出OutputStream物件
OutputStream os = new response.getOutputStream();
這行也不可以省略。


最後一步驟:讀取InputStream物件的圖檔
寫到OutputStream物件裡面,因為這個OutputStream物件屬於response物件
所以會列印到瀏覽器上

  byte[] b = new byte[1024];

   int len ;
   while( ( len = is.read(b) ) != -1 ){
   os.write(b, 0, len);
   }





範例:
首先告訴servlet圖檔路徑,而且不將路徑、檔名寫死。

//利用陣列存放檔案名稱,用InputStream讀檔時不將檔名寫死
//宣告存放檔案名稱的字串陣列

 String[] pics = {"autumn_fs.jpg" , "fs.jpg", "m001.jpg"};
//要給pics陣列用的索引
 int num = (int)(Math.random() * pics.length) + 0;

//取得檔案路徑
  String deployDir = getServletContext().getRealPath("/");
              // imageDir : 存放圖片檔的資料夾,它位於專案部署資料夾之下的images資料夾    
String imageDir = deployDir + "\\images\\" ;

//告訴servlet檔案的名稱以及路徑,將檔案放進inputstream物件裡面
       InputStream is = new FileInputStream(imageDir + pics[num]);

           response.setContentType("image/jpeg");
  OutputStream os = response.getOutputStream();


以1024byte讀圖檔
  byte[] b = new byte[1024];
  int len ;
  while( ( len = is.read(b) ) != -1 ){
  os.write(b, 0, len);
  }
  is.close();
  os.close();
}
}






2013年3月23日 星期六

ListView

Adapter:
連接後端資料與前端View的配接器




SimpleAdapter:可以自由擴充listItem格式
ArrayAdapter:listitem只能顯示一行



ListView讓手機頁面秀出垂直條列式項目。

約有三種方式:
一、

1.
首先在xml貼上<ListView>標籤,
<ListView
    android:id="@+id/lv"
        android:layout_width="fill_parent"
      android:layout_height="fill_parent"
  ></ListView>
預覽頁面會是下面這樣:

2.定義Item長相:
Item也是layout一種,一般新增一個xml來做Item版面配置。
假如我們希望Item長相如下:
有Icon,有title以及說明內容。


那麼新增一個item.xml,用來描繪Item的長相
上圖用兩個LinearLayout以及一個ImageView以及兩個TextView實作。

<?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="wrap_content"
    android:orientation="horizontal"
    >
    <ImageView
        android:id="@+id/item_img"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_weight="1"
  android:src="@drawable/TVClose"  //圖片所屬資料夾以及檔名
        />
    <LinearLayout
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:layout_weight="4"
     android:orientation="vertical"
        >
        <TextView
            android:id="@+id/item_title"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="TVclose"
      android:textSize="24dip"
      android:textStyle="bold"
            />
        <TextView
            android:id="@+id/item_content"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="電視收播圖像"
      android:textSize="12dip"
            />
        </LinearLayout>
</LinearLayout>


在drawable放圖片檔案:
另外要在res資料夾裏頭,新增資料夾drawable,裡面放想要呈現在listview的圖片,放在res的檔案android會自動配置參考地址(int 型態)。在java要取用時可以打R.drawable.圖片檔名。

在.java宣告
private ListView lv;
lv=(ListView)findViewbyId(R.id.lv)

常見作法用ArrayList以及HashMap配合和泛型實作ListView
ArrayList表示ListView容器本身,HashMap表示一個Item。
ArrayList可以裝多個HashMap。
HashMap可以裝Item的資訊、圖檔

 ArrayList<HashMap<String,Object>> list = new ArrayList<HashMap<String,Object>>();
//宣告ArrayList,這個ArrayList可以裝下多個HashMap

//以HashMap實作ListView的Item
//String:是key、index,也可以屬性來比喻他,方便開發者更好寫程式。Object是資料,可以用值來比喻。
HashMap<String,Object> data1 = new HashMap<String,Object>();
data1.put("item_img",R.drawable.freezer );//存放圖檔
data1.put("item_title", "Freezer");//Item圖檔在listview的名字
data1.put("item_content", "佛利沙,過去在宇宙為人人聞之色變的惡魔");
//Item說明
list.add(data1);//將Item塞入listview(將HashMap塞入Arraylist物件)

HashMap<String,Object> data4 = new HashMap<String,Object>();
data4.put("item_img", R.drawable.tvclose);
data4.put("item_title", "TVclose");
data4.put("item_content", "電視收播,以前電視台休息收播會出現影像");
list.add(data4);


//上面已經宣告listview設定,尚未告訴android
//main_activity.java的item與item.xml怎樣連接
//也沒告訴.java的listview與xml的listview連接
//底下實作之

String[] from = {"item_img","item_title","item_content"};
//HashMap的key,為了底下SimpleAdapter使用

int[] to = {R.id.item_img,R.id.item_title,R.id.item_content};
//Item.xml的標籤id
//注意int陣列中元素所代表的物件要正確對應到String的每個字串所代表的物件,例如R.id.item_title在item.xml代表TextView物件,而String[] from的"item_title"在activity.java裡面代表HashMap的字串,所以順序擺放要
正確,否則無法正確顯示listview

如果將順序改成如下,那麼顯示的listView如圖:
//int[] to = {R.id.item_content,R.id.item_title,R.id.item_img};


SimpleAdapter adapter = new SimpleAdapter(this, list,R.layout.item, from, to);
//資料與lItem的配接器,參數缺一不可,android才會幫我們接上對應的
//SimpleAdapter(哪個.java的item(context),哪個xml的item,HashMap的key,Item.xml版面配置單一選項編號)

lv.setAdapter(adapter);
//設置listview的配接器,item要秀在哪個listview




二、

1.
xml放一個<ListView />


    <ListView
        android:id="@android:id/list"
       @android:id/list意思是調用android系統內建的id(資源)
//而且list只能給ListView用,如果用android:id其他的項目則會發生錯誤
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:drawSelectorOnTop="false"
         />


2.
extends ListActivity

3.
制定listview內容
String[] items = {"Aibo","Brad","Clock","David","Enjoy"};

setListAdapter(new ArrayAdapter(this,android.R.layout.XXXX,items));
//ArrayAdapter(context,listview格式,listview(裡面的textView)內容)
//setListAdapter


String[] items ={"Sherry", "Dorara", "Black", "Int", "Five"};
Button button1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


//list項目
//setListAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,items));
//ArrayAdapter(context , 格式TextViewResourceId(android有內建xml檔案?各式各樣格式,  ,項目內容String[] items);
//普通格式


//setListAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_single_choice,items));
//radiocheck模式
//setListAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_checked,items));
//打勾圖示
setListAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_activated_1,items));
//項目反白

//getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
//getListView()從Activity取得ListView物件
//複選模式
//如果不打上這行,預設為Choice_mode_none
//選擇項目
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
//單選模式


button1=(Button)findViewById(R.id.button1);


}

//callback method
public void onListItemClick(ListView parent,View v, int position, long id){
       button1.setText(items[position]);
   
   }





三、整個activity視為ListView


1.準備一個XML描述ListView單一項目

<!-- <Button
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   />   -->
//若加上這個,每一項目都有button  
   //setOnItemClickListener失效

    <TextView
        android:id="@+id/item_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="6dp"
        android:layout_marginBottom="6dp"
        android:textSize="24sp"
        android:textStyle="bold|italic"
/>

2.新增一個Activity extends ListActivity

3.

宣告陣列存放ListView的項目內容

//例如Listview每一項目有TextView則宣告字串陣列
String[] item = {"one","two","three"};


//如果ListView項目有圖片就宣告 int陣列
int[] photos={R.drawable.photo1,R..drawable.photo2,R.drawable.photo3};


4.
宣告ArrayList為ListView容器
HashMap代表ListView的每一筆紀錄
一筆紀錄有多個屬性(欄位)
(一筆紀錄有textview以及image)


ArrayList<HashMap<String,String>> data = new ArrayList();




5.

String[] from = {"item_title"};
//item的key名稱,
//目的讓adapter做配接用


int[] to ={R.id.item_title};
//對應到描述listview單一項目的Xml檔案,裡面的元件(wedgit)的ID。
 //對應textview的id
//如果xml有TextView以及ImageView元件,元件id分別是R.id.item_title,R.id.pictur
//則宣告int[] to = {R.id.item_title,R.id.picture}



6.將內容塞入HashMap

for(String item:items){

HashMap<String,String> dd = new HashMap();
dd.put(from[0], item);
//將每一筆紀錄第from[0]欄位存放資料內容
data.add(dd);
}



7.將資料與ListView配接


adapter = new SimpleAdapter(this,data,R.layout.activity_main,from,to);
//this 的 data 放在 R.layout.activity_main,hashmap的key(就是from)要與xml的欄位(即to)對應



8.View物件使用配接器

lv=getListView();
//將整個Activity視為listview
//原本lv= (ListView)findViewById(R.id.lv);
lv.setAdapter(adapter);






private ListView lv;
private SimpleAdapter adapter;
private String[] items = {
"LinearLayout", "RelativeLayout",
"TableLayout", "ListView",
"Gallery"
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);


String[] from = {"item_title"};
//item的key
int[] to ={R.id.item_title};
//對應到listItem每項目裡面的元件。    對應textview的id



ArrayList<HashMap<String,String>> data = new ArrayList();

for(String item:items){
HashMap<String,String> dd = new HashMap();
dd.put(from[0], item);
data.add(dd);
}
adapter = new SimpleAdapter(this,data,R.layout.activity_main,from,to);

lv=getListView();
//將整個Activity視為listview
//原本lv= (ListView)findViewById(R.id.lv);


lv.setAdapter(adapter);

// lv.setOnClickListener(new OnClickListener(){
//
// @Override
// public void onClick(View v) {
// // TODO Auto-generated method stub
//
// }});

lv.setOnItemClickListener(new OnItemClickListener(){

@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int index,
long arg3) {

doJob(index);

}});



}


private void doJob(int index )
{ switch(index)
{
case 0:
Toast.makeText(this, "LinearLayout", Toast.LENGTH_SHORT).show();
break;
case 1:
Toast.makeText(this, "RelativeLayout", Toast.LENGTH_SHORT).show();
break;
}
}






2013年3月21日 星期四

ActivityLifeCycle (II)

準備兩個Layout
兩個Activity(.java繼承Activity)
兩個都Override
oncreate(),onstart(),onresume(),onrestart()
,onpause(),ondestory(),finish()
並且在各自method裡面寫上
Log.i("log+tag","method_name");




啟動程式後進入第一頁:
會自動執行
OnCreate()
OnStart()
OnResume()
之後
按下Button跳到第二頁
第一頁執行
OnPause();
之後第二頁開始執行
onCreate2()
onStart2()
onResume2()
第二頁有開啟成功,第一頁執行
onStop();
目前人在第二頁,跳出第二頁
第二頁執行
finish2()
onPause2()
,跳回第一頁,執行
OnRestart()
Onstart()
onresume()

第二頁執行
OnStop2()
OnDestroy2()

android切換視窗,Activity之間傳遞接收資料

一、切換視窗
功能:
按下View或Button
跳到另外一頁(activity)


以Intent實作

button1.setOnClickListener(new OnClicklistener(){
public void onClick(View arg0) {
    Intent intent = new Intent();
//    intent.setClass(this, Page2.class);
intent.setClass(MainActivity.this,Page2.class);
//setClass:設定標的activity,將目前activity的context傳遞進去。
//因為這是寫在匿名內部類別所以要加上MainActivity
//否則this只代表OnClickListner物件
startActivity(intent);//class Activity的method
//啟動新的activity
 }});



在Page2.java裡面:
要與page2.xml連接
setContentView(R.layout.page2);

去Mainifest.xml
Application Node 新增Activity
Name部分按下browser會自動搜尋,之後與.java檔案關聯
或直接貼上<activity android:name="Page2"></activity>


二、Activity之間傳遞資料與接收資料
甲、傳遞過去(A→B):
上面步驟完成之後
在第一個Activity的Itent下面加上
intent.putExtra(String name,String Value);
intent.putExtra("HP", "18"); 回傳Intent
意思是新增一個叫做HP的data,HP的值是18

官網文件是
Add extended data to the intent. The name must include a package prefix, for example the app com.android.contacts would use names like "com.android.contacts.ShowAll".
name要加上套件名稱


在第二個Activity加上
Intent intent = getIntent();
//這裡getIntent()是Activity的method,接收第一頁傳來的Intent物件
  String name =intent.getStringExtra( "HP");
// 取出字串物件
  page2_msg.append(name);
//將字串顯示在TextView上面


Activity之間傳遞資料可以透過intent.putXXX(String name,XXX型別資料)傳遞。

下一個Activity則是呼叫Activity的method,getItent()接收上一個Activity傳過來的intent物件。接著呼叫Intent類別物件的getXXXExtra(String name);取得上一個Activity所傳遞的資料。

乙、傳回資料(B→A)
功能:從B頁面(Activity ),回到A頁面(Activity)。B頁面傳回資料給A。A可以利用這些資料做運算處理。

(1).單純的callback

要達到以上功能,我們切換頁面的method,要用startActivityForResult(Intent,int RequestCode)替代上面的startActivity(Intent),而且要在Activity A改寫(override) onActivityResult()方法。當頁面切換回來Activity A時,Activity A會自動呼叫onActivityResult()。回傳ResultCode、Intent以及RquestCode。
RequestCode的值用來作為Activity的標籤,如此一來Activity A才可以知道是哪個Activity回傳。使用者可以自己指派RequestCode的value。

如果Activity B 要傳遞資料回去給Activit A, 那麼Activity B要改寫finish(),並且在finish呼叫setResult(ResultCode,intent);傳回intent以及ResultCode給原本Activity(即Activity A)繼續處理。ResultCode也可自訂。

在Activity A , override onActivityResult

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//如果切換的Activity沒有setResult();那麼Intent data=null、resultCode=0
  super.onActivityResult(requestCode, resultCode, data);
  main_msg.append("RequestCode:" + requestCode+"ResultCode"+resultCode);
  main_msg.append("Data :"+data.getStringExtra("from"));


}


在Activit B 改寫finish():
public void finish() {
  Intent intent = new Intent();
  intent.putExtra("from", "PAGE2");//塞資料到intent,key為from,value為PAGE2的資料
  setResult(4,intent);//將intent以及ResultCode回傳
  super.finish();
 }




textView印字串可以用
textview1.append("字串"+變數);

2013年3月20日 星期三

Context

官網定義:

Interface to global information about an
 application environment. 
This is an abstract class whose implementation is provided by the Android system. 
It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc.



看來Context好像網路的session
又好像java的collection
Context儲存Activity的資訊


分成兩種context

Application context:
Application:一整個應用程式
打開應用程式之後會先create()

Activity context
Activity:一個頁面或應用程式中一小段功能


1.
實作切換視窗時候,會用到context
setClass(context,XXX.class);



新增Application
1. .java 要extends Application
2.在Mainifest註冊自己寫的Aplication
在Application標籤的屬性添加android:name=".MainApplication"




main.xml是vertical的linearLayout
button的width設為match_parent
不知為何extends linearLayout
button顯示效果是wrap_content,文字分成兩行
用extends relative layout
butoon顯示效果是wrap_content,文字為一行
用extends framelayout
button顯示才會跟linearlayout且效果是match_parent





Context在android應該被翻譯為"場景",一個Activity就是一個Context,一個Service也是一個context.

Context是一個抽象類別。
使用者和OS每一次交互作用都是一個場景。
一個應用程式中有多少個activity或service就會有多少個context物件






2013年3月17日 星期日

eclipse JavaEE 設定

eclipse設定JSP/servlet

1.
首先jdk1.7裝好還有tomcat 7.0也裝好
(tomcat在裝netbean JavaEE版時就給我裝好了)

2.下載java EE juno版的eclipse
開啟eclipse,如果載入不了jvm,那麼可能是jdk是裝32bits版的
eclipse是裝64bits的,改下載eclipse 32bit版的就OK了

3.
設定web container。我的web container採用湯姆貓tomcat
window→preference→server→Runtime Environment
將tomcat安裝的路徑,告訴eclipse
路徑:C:\Program Files (x86)\Apache Software Foundation\Apache Tomcat 7.0.34

原本左邊項目有deployment descriptor ,後來莫名消失。只要新增generate deployment descriptor stub就可以了。如果無法新增先將web.xml刪掉吧。

開發jsp/servlet有三個區塊為重心
部署檔案  web.xml
servlet檔案  xxx.java
網頁檔案 xxx.jsp


第一步新增一個.jsp檔案測試看看
記得要run as → run on server
如果可以正常顯示那麼表示tomcat安裝成功並且確實啟動伺服器

第二步新增servlet
注意super class部分要改為繼承HttpServlet
之後在視窗空白處點右建
source→override
選doGet doPost
寫好.java檔案不能run
因為要靠jsp檔案以及部暑檔案才可run



(在netbean新建一個servlet後,裡面已經有override doGet() doPost()以及新建一個processRequest(request,response)。
netbean預設執行processRequest??有待確認)

processRequest是使用者自訂的method,在eclipse要自己create一個processRequest method,而netbean自動建立method,看樣子這種寫法好像已經成為約定俗成的架構。





第三步
部署檔
要在<web-app>之間新增
<servlet>與<servletmap>兩個標籤
<servlet>簡單來說是給servlet檔案取個外號。
<servletmap>就是servlet的外號對應到jsp的form action或者<a href ....>網址
以<a href>呼叫servlet預設以get方法執行
(HTTP協定最好用POST方法傳遞資料,較安全)

<servlet>
<servlet-name>Servlet在web.xml的名字,名稱自訂不可重複</servlet-name>
<servlet-class>說明該servlet檔案的完整名稱(包含套件類別名稱)。容器載入類別時就是看這裡資訊</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>同上</servlet-name>
<url-pattern>說明client端提出何種請求會連到本Servlet</url-pattern>
</serlet-mapping>





2013年3月13日 星期三

Map

Map:跟Collection相似,屬於物件容器,一次必須放兩個物件,一個表示鍵(key),一個表示該key所對應的值(value),兩個物件合起來稱作key-value-pair。key就好比是index,value好比是物件、儲存內容。

key是set類別物件。可以當作索引。
value是collection類別或子類別的物件。

Map是介面,
由Hashtable、HashMap實作,由SortedMap繼承
TreeMap實作SortedMap

TreeMap內容會依key值順序排序。



一、HashMap實作

import java.util.*;
public class HashMapTest {
    public static void main(String[] args) {
//宣告HashMap,key為Integer型態,value是String型態
HashMap<Integer,String> hmap= new HashMap<Integer,String>();
hmap.put(1001, "Kaiba");//新增資料,put(key,value)
hmap.put(100, "Conan");
hmap.put(345, "Dorara");

System.out.println(hmap.size());//map大小
System.out.println(hmap);//列印map key以及value
System.out.println(hmap.get(100));//取得key為100的value,傳回型態:泛型

System.out.println("hmap是否有關鍵值1001:");
System.out.println(hmap.containsKey(1001));
System.out.println(hmap.containsKey(199));

System.out.println("hmap是否有對應值Conan:");
System.out.println(hmap.containsValue("Conan"));
System.out.println(hmap.containsValue("Detective"));
   
System.out.println("================");
Set<Integer> set1 = hmap.keySet();//將所有的key set轉成實作set介面的物件
System.out.println(set1);
   
//String removeStr = hmap.remove(1001);
//    System.out.println(removeStr);
hmap.put(1999, "Conan");
Collection collobj=hmap.values();
//將map所有的value轉成實作collection介面的物件
//無法塞入List
System.out.println(collobj);  
    }
}



泛型Generics

類別裡面的變數若宣告為String那麼只能儲存字串型態的值,不能儲存數字、boolean值。
,如果想要一個變數可以儲存整數型態也可以儲存字串型態,java有一種功能可以讓我們自訂變數的型態。這就是泛型(Generics)基本功能。
(本質上並非讓使用者自訂變數型態,而是將變數包裝成Object的型態)

class Book<T>{//宣告類別並且裡面的變數跟method可以宣告為T型態,這邊T可以隨意亂打
private T price;//宣告T型態的變數,表示使用泛型(不限定資料類型)
public void setPrice(T price){
this.price=price;
}
public T getPrice(){
return price;
}}

public class Generics {

public static void main(String[]arg ){
Book<Integer> book1= new Book<Integer>();//<>裡面寫Integer表示,要將T指定為Integer,也就是說Book類別內容只要有T的地方都要換成Integer。
book1.setPrice(100);//所以這裡只能傳入整數,傳入其他型態的變數會編譯失敗
System.out.println(book1.getPrice());

Book book3 = new Book();//如果不指定T的類型,那就表示price什麼類型都可以接受
book3.setPrice(true);//傳入boolean值,自動轉型為Object型態
System.out.println(book3.getPrice());

book3.setPrice(11.8);//傳入double值,自動轉型為Object型態
System.out.println(book3.getPrice());
}}


執行結果:
100
true
11.8





class Book採用泛型宣告,相當於寫完所有基本型態變數的宣告,如同寫完下面的宣告:

class Book{
private Integer price;
public void setPrice(Integer price){
this.price=price;
}
public Integer getPrice(){
return price;
}}


class Book{
private String price;
public void setPrice(String price){
this.price=price;
}
public String getPrice(){
return price;
}}

二、泛型的進階設定-----限制變數型態的範圍。
比方說Book<? extends Number>

表示Book如果使用泛型,他的資料類型必須是Number類別或Number子類別。
Number子類別有Integer,Byte,Short,Long,Float,Double。

class Book<T>{
T price;
public void show(){
System.out.println(this.price);
}
public static void show(Book<? extends Number> b){//接收資料類型為Number類別或Number子類別的Book物件。
System.out.println(b.price);
}}
public class Generics {
public static void main(String[]arg ){
Book<Integer> book = new Book<>();
book.price=100;
Book.show(book);

Book<String> book2 = new Book();
book2.price="byebyeworld";
Book.show(book2);//這行會有錯,因為bookk2的泛型採用資料類型是String,不是Nubmer類別的子類別。所以不能傳遞參數。
book2.show();
}
}
三、泛型跟Collection搭配就可以限制元素的資料類型


import java.util.*;
public class CollectionGenerics {
static void showSum(Collection<? extends Integer> c){//宣告Collection,並限定只接收儲存Integer資料類型的物件。
int sum = 0;
for(Integer i: c)//因為c裡面都是Integer,所以取出的類型都是int
sum+=i;//UnautoBoxing後與sum相加
System.out.println(sum);
}
public static void main(String[] args) {
// Collection<Long> c = new ArrayList<Long>();
Collection<Integer> c = new ArrayList<Integer>();//宣告collection c為存放Integer資料類型的ArrayList。c只能存放Integer的資料類型的物件。
c.add(1);
c.add(2);
c.add(3);
   // c.add("ddd");因為我們宣告c為Integer資料類型的arraylist,這行會加入字串會編譯錯誤,因為c只能放Interger的物件
showSum(c);//如果c宣告為Long的ArrayList,這行就會編譯錯誤
}}




2013年3月12日 星期二

Collection's'類別

位於java.util.Collections類別庫之下
提供與collection相關的static方法
ex:排序 搜尋

二分搜尋法
public static int binarySearch(List list,Object key)
使用二分搜尋法以前必須將list排序
list:List集合
key:搜尋標的物

public static void reverse(List list)
反轉List內的物件順序

public static void sort(List list)
讓list內的物件由大到小排序
若要執行排序,collection裡面的物件類型必須一致
否則會因為試圖轉型產生ClassCastException


public static void shuffle(List list)
隨機洗牌

容器物件:Collection



Collection:是一個容器物件,功能和陣列很相似。容器物件裡面可以放多個物件。也有一說collection是動態陣列,透過物件儲存物件。
clllection裡面放的東西都是物件,如果存放基本型別會先autoboxing成對應的物件,放入的物件還會自動轉型成Object類型。
Collection在java中是介面,由List、Set兩個容器物件(也是介面)所繼承。

一、Set:set裡面物件唯一不重複,存放次序由系統自己給定。set也是介面,透過底下的HashSet來實作。

import java.util.*;
//使用collection,必須import java.util.*;
class Human {

    int age = 1;
    int height = 111;

    public void speak() {
        System.out.println("hahaha");

    }
}

public class set {

    public static void main(String[] args) {
        Set set1 = new HashSet();//透過HashSet來實作Set介面
        set1.add("conan");//將""conan物件加入set裡面
        set1.add("Blue");
        set1.add(new Integer(44));//必須將基本型態boxing為物件
        set1.add(new Integer(44));
        set1.add(new Integer(99));
        set1.add(new Double(3.14));
        set1.add(new Human());
        System.out.println("set1=" + set1);
 

Iterator it = set1.iterator();//利用Iterator一一列印物件
while(it.hasNext()){
Object o = it.next();
System.out.print(o+" ");

 }
}

執行結果:可以看到物件排列順序與存放先後時間不一樣,而且物件不重複
set1=[3.14, Blue, 99, conan, collections.Human@78f77c8e, 44]


二、List
List裡面存放的物件可以重複,物件存放順序由add()先後時間來排列。List也是介面,繼承自Collection。List透過底下的ArrayList與LinkedList實作。

1.ArrayList:以陣列實作list。要實作陣列裡面的物件插入與刪除,效能不是那麼好
.remove("物件")//清除特定物件
.clear()//清空list

 List list1 = new ArrayList();//實作List介面
        list1.add("DarkMagician");
        list1.add("Blue eyses");
        list1.add("DarkMagician");
        list1.add(new Integer(33));
        list1.add(new Double(44.4));
        list1.add(new Integer(33));
        System.out.println(list1);


list1.remove("DarkMagicin"); //將物件從Arraylist移除
       for(int i=0;i<list1.size();i++){
        System.out.println(list1.get(i));//list1.get(i)根據序號,列印物件
     
        }
/*或者
        for(Object obj1:list1){//列印單筆物件的foreach寫法
        System.out.println(obj1);
        }


*/



執行結果:  可以看到存放順序以add()時間先後排列

[DarkMagician, Blue eyses, DarkMagician, 33, 44.4, 33]
Blue eyses,DarkMagician,33,44.4,33,DarkMagician

2013年3月11日 星期一

java網路


import java.net.InetAddress;
import java.net.UnknownHostException;
//必須import

 try {
       InetAddress ip = InetAddress.getByName("8.8.8.8");//取的IP,這裡不用new因為記憶體已經有。這行必須用try-catch包住。有可能因為不適當的IP造成例外
        System.out.println(ip.getHostName());//印出google-public-dns-a.google.com
         } catch (UnknownHostException ex) {
         

2013年3月8日 星期五

webview:從javascript呼叫java程式;從java呼叫javascript程式

webview在app顯示自己寫的網頁

網頁html檔案放在assets 底下

可以新增file然後命名為xxx.html
接著open with textedit
我們就可以自行開發網頁
並且在android系統上瀏覽自己開發的網頁


webview1.loadUrl("http://archive.org/web/web.php");
//載入網址,在webview顯示該網址的內容

webview1.loadUrl("file:///android_asset/myweb.html");
//自訂Html檔案

記得:
AndroidManifest.xml的permission中add user premission加上可以上網的權限


做到以上的事情只能瀏覽網頁。
無法執行javascript程式碼


我們必須開放javascript權限,指令如下
webview1.getSetting().setJavaScriptEnabled(true);

也可以先宣告private WebSettings setting;
setting = webview.getSetting();
setting.setJavaScriptEnabled(true);
如此一來可以執行javascript程式
我們可以去jQuery官方網站測試
http://jqueryui.com/hide/
開放javascript之後有出現js特效
不過卻無法出現alert的效果

Websetting存著Webview狀態屬性
其實在Webview物件建立時候會給websetting預設值
webview跟websetting是綁在一塊的
當webview物件消失時,若取用websetting會拋出例外

一、從JavaScript去呼叫Java的物件執行程式


wv1.addJavascriptInterface(new MyJavaScript(MainActivity.this), "yypalert");
//建立javascript與java互動的介面,指定要執行的java物件(MyJavaScript)與執行程式所在地(MainActivity.this),設定介面名稱,讓javascript識別的字串"yypalert"。如此一來JavaScript可以經由yypalert存取.java物件的method。

//MainActivity.this代表MainActivity類別的物件。
//若只寫this代表MainActivity內部類別的物件


wv1.loadUrl("file:///android_asset/myweb.html");
//導至自訂的網頁

//Javascript要執行的code

private class MyJavaScript{
private Context context;//因為Toast要指定toast顯示地方,所以宣告context,接收上面的MainActivity.this物件
MyJavaScript(Context c){
context=c;

}
public void sayYa(String msg){
Toast.makeText(context, msg,Toast.LENGTH_LONG).show();
}}//context:Activity,msg從javascript接收的字串,Toast.LENGTH_LONG指定Toast秀出時間長度。記得要價上.show()


關於MainActivity.this:
「在 Android 程式中, 大多數的程式可能都是在事件處理時執行, 而大多數的事件處理都是寫在匿名的內部類別 (Inner Class) 中, 也就是說, 當事件處理執行時, 所屬的物件是內部類別所產生的物件, 因此若是只寫 this, 那麼所指的其實是這個內部類別的物件, 但我們需要傳遞的是外部 Activity 類別的物件 (Activity 是 Context 的衍生類別), 這時就必須在 this 前冠上外部類別的名稱, 而這也就是你會看到 XXXActivity.this 的原因。」


Context是抽象類別繼承自Object,是Activity的父類別


HTML檔案目前有一個button,以及javascript程式

<input type='button' value='Click1' onClick='ok1()' />

<script>
function ok1()
{
yypalert.sayYa('OK');
}</script>

執行畫面有個按鈕給他按下去之後,觸發onclick事件,跑去執行javascrip的ok1函式,看到yypalert介面名稱跑去.java對應的地方,執行java的method sayYa()並傳入字串'OK',在螢幕上顯示OK字眼


二、從Java(Android)呼叫JavaScript程式

作法很簡單
在MainActivity.java裡面利用.loadUrl()呼叫JavaScript函式:

 
public void toJavaScript(){
wv1.loadUrl("javascript:fromAndroid("+(int)(Math.random()*49)+")");
//呼叫javascript的function fromAndroid()並傳隨機數字。
//執行這行以前務必先打開自己寫的html,再執行這行,否則android是不會自動跳到自己寫的html
}    



在Html裡面準備一個名字叫formAndroid的function

function fromAndroid(msg){

                  document.getElementById('here').innerHTML=msg;
//在Html裡面找到id為here的元件,並且在標籤之間插入字串msg

}

<div id='here'></div>
//執行之後這邊區塊會輸出隨機亂數

在寫javascript時候注意拼字問題,javascript沒有偵錯字功能
如此一來就可以從Android送資料去javascript的function了


2013年3月7日 星期四

巢狀類別Nested Class

巢狀類別:一個類別之內再定義一個類別。
優點:可以存取外部類別的private成員



static 內部類別:
類別裡面再宣告一個static類別。依附於"外部類別"上
特性:只能存取外部類別的static成員,不能存取實體成員。
因為實體成員是物件層級的,static是類別層級的。

內部類別是外部類別的成員。

package nestedclass;
class outer{
static int x = 1;//static 變數
int y=2;
private static int k =4;
public static class inner{
private int z = 3;
public void show(){
System.out.println("outer.x="+outer.x);//存取static變數
//System.out.println("Outer.thix.y="+outer.this.y);//無法存取y
System.out.println(outer.k);//存取private static變數
System.out.println(z);
}}

}
public class staticNestedclass {
    public static void main(String[] args) {
outer.inner inner = new outer.inner();//inner依附於外部"類別",所以以外部類別.內部類別()建立物件
inner.show();
    }}




實體內部類別
類別內部再宣告non-static類別。依附在物件實體上。
內部類別是外部類別的成員。


package nestedclass;
class outer{
   private static int x = 1;
 static int y=2;
 int k= 3;
public class inner{
private int z = 3;
public void show(){
System.out.println("outer.x="+outer.x);//存取private成員,也可在x前面加上this
System.out.println("Outer.thix.y="+outer.this.y);//static成員也可用this去存,this表示outer的物件
System.out.println(this.z);//這裡this表示inner物件
System.out.println(outer.this.k);
}}}
public class staticNestedclass {
    public static void main(String[] args) {
outer.inner inner = new outer().new inner();//實體內部類別依附於物件實體上所以要先new outer()才實體化內部類別物件。
inner.show();    }}




方法內部類別
將類別宣告在外部類別的方法裡面,此時內部類別是方法裡面的類別,不是外部類別的成員。內部類別宣告規則跟方法內變數一樣,不可加static以及存取修飾詞。
方法內部類別可以存取外部類別成員,
但是方法裡面的區域變數必須冠上final修飾詞,才能被內部類別存取
(原因是加上final宣告時強制給予變數初始值)



package nestedclass;
class outerclass{
static int x =1;
int y =2;
private int k=3;
public void outermethod(final int a){
int b=5;

class inner{
 int z = 4;
public void show(){
System.out.println("x="+x);
System.out.println("y="+y);
System.out.println("k="+k);
System.out.println("z="+z);
System.out.println("a="+a);//存取外部類別的方法裡的區域變數
//System.out.println("b="+b);//

}
}
    inner inner = new inner();//物件宣告必須放在,類別宣告之後
    inner.show();  
}}

public class methodinnerclass {
    public static void main(String[] args) {
        outerclass outer = new outerclass();
        outer.outermethod(100);      
    }
}




匿名內部類別
該內部類別只有宣告類別名稱、實作內容但沒有"物件"名稱。
用於實作介面或改寫類別上
可以參考interface文章

EX:

public class anonymous_inner_class {
   public static void main(String[] args) {

//小括號包住,只有new 物件沒有給名字,主要用來補足內部類別Caaa沒有定義到的method

        (
                new Caaa(){
                void set_num(int n){
                num=n;
                System.out.println(num);
                
                }
                
                }).set_num(5);//執行匿名內部類別定義的method
                               
    }  
       
static class Caaa{

        int num;        }
           
}





匿名內部類別常用於撰寫事件(event)。

2013年3月6日 星期三

執行緒

定義:程式碼同時進行數個處理流程。

啟動執行緒:增加程式中的處理流程。

優點:讓程式更有效率進行處理,例如進行要花費N鐘頭的迴圈處理時,可以別的執行緒進行其他處理。

注意:Thread一旦run結束或中斷,就再也無法呼叫start()重新啟動thread



1.執行緒實作方法有三種:
第一、extends Thread建立Thread的子類別obj1


Thread子類別建立物件後,呼叫start()(obj1.start())由Thread繼承而來)啟動執行緒,之後跑run()裡面的程式。如此一來可以分別建立物件,每個物件可以有自己執行緒。




第二、宣告類別obj並且implement Runnable,宣告執行緒類別,以obj為引數建立執行緒物件。

class CTest implements Runnable{
public run(){.....}}

public static main(String args[]){

CTest obj = new CTest();
CTest obj2 =new CTest();

Thread t1 = new Thread(obj);//產生執行緒物件
Thread t2 =new Thread(obj2);
t1.start();
t2.start();

}

第三、使用匿名內部類別




以上必須override run() method。
run()裡面的東西就是新處理流程的起點。

可以利用sleep(1000)暫時停止執行緒,這是暫停一秒。




class multi_thread implements Runnable{//實作thread第一步,implements Runnable

    @Override
    public void run() {//第二步改寫run(),
      for(int i=1;i<=10;i++){
      System.out.print("i="+i);//執行緒在這裡可能被插隊
     System.out.println("name="+Thread.currentThread().getName());

            try {
                Thread.sleep(1500);//可以用Thread.sleep();讓執行緒進入blocked狀態(休息)
1500表示1.5秒,.sleep必須寫例外處理否則不給編譯過。
            } catch (InterruptedException ex) {            
            }            }  
}}

public class runnable {
  public static void main(String[] args)  {
     
            multi_thread obj = new multi_thread();
            Thread thread1 = new Thread(obj,"Taiwan");//建立執行緒,thread1去跑obj的程式,並且將thread1的名稱命名為Taiwan
            Thread thread2 = new Thread(obj,"Formosa");
         
            thread1.setPriority(Thread.MIN_PRIORITY);//thread權限,括號裡面是int型態
            thread2.setPriority(Thread.MAX_PRIORITY);
           
            thread1.start();//啟動thread
            thread2.start();
         
        try{  
            thread1.join();//.join()必須跟try-catch或throws InterruptedException配合
//thread1執行緒結束才會繼續執行try-catch之外的程式
            thread2.join();//thread2執行緒執行完之後才會執行下面的程式
        }catch(InterruptedException ex){}
        System.out.println("finished");
          }  
}



同步synchronized
執行緒存取變數或物件時將資料lock住,禁止其他執行緒進行存取。

使用時機:多個執行緒在同一時間存取同一個變數或物件


避免資料不一致、插隊情形,避免互相等待造成死結。

常常與notify() wait()配合
notify():通知waiting狀態的執行緒,如果有多個thread則隨意喚醒其中一個

wait():執行去進入waiting狀態,必須等待其他執行緒呼叫notify()才能將它喚醒


以下是沒有synchronized的程式碼以及執行結果
某家公司有兩個司機,位公司開車賺錢,宣告company類別管理這兩名司機賺來的錢,兩名司機賺的錢交回公司。

class Company{
    private int sum = 0;

    public void add(int a){//若要正確結果,在這邊加上synchronized修飾
    int tmp = sum;
    System.out.println("目前合計金額"+tmp+"dollars");
    System.out.println("賺到"+a);
    tmp=tmp+a;
    System.out.println("合計金額是"+tmp+"dollars");
    sum=tmp;
    }
}
class Driver implements Runnable{
    private Company comp;
    public Driver(Company c){
            comp=c;
    }
    @Override
    public void run(){
    for(int i=0;i<3;i++)
    {
     System.out.println(Thread.currentThread().getName());//列印執行緒名字
        comp.add(50);
    }
}       
}

public class synchron2 {
    public static void main(String[] args) {
        Company cmp = new Company();
        Driver drv1= new Driver(cmp);
        Thread thread1 = new Thread(drv1);
        thread1.start();
       
       
        Driver drv2=new Driver(cmp);
        Thread thread2 = new Thread(drv2);
        thread2.start();
    }
}


執行結果:

Thread-0
目前合計金額 0dollars
賺到50
合計金額是50dollars
Thread-1
Thread-0
目前合計金額 50dollars  //Thread1與Thread0幾乎同時讀取資料  
目前合計金額 50dollars //這裡可以看到Thread1讀取到Thread0改過後的資料
賺到50
賺到50
合計金額是100dollars
Thread-0
目前合計金額100dollars
合計金額是100dollars
Thread-1
賺到50
目前合計金額100dollars
賺到50
合計金額是150dollars
合計金額是150dollars
Thread-1
目前合計金額150dollars
賺到50
合計金額是200dollars             //正確金額應該是300元

2013年3月4日 星期一

資料串流、資料讀寫

what:
輸入:將檔案內容由磁碟機讀入後暫存到記憶體內
輸出:將記憶體內暫存資料寫入到檔案中或者將訊息顯示在螢幕上

在java裡面,資料的輸出與輸入皆以串流(stream)的概念進行。串流的資料是由chracters與bit組成。

在處理IO時候要說清楚資料的來源(source)與目的地(sink)

注意stream型態
分成byte stream以及 character stream

byte stream以1byte為單位(位元為主)傳輸資料,長相InputStream/OutputStream;
除了可用於文字檔輸出入之外
也可用於非文字檔(二進位檔案binary file)、圖形檔的輸入輸出

character stream以字元為單位傳輸資料,長相reader/writer
用於文字檔的輸出輸入,避免產生亂碼。


which:

以下IO類別皆放在java.io類別庫之下。
架構如下:

java.io套件:
一、File //管理目錄底下的檔案與目錄。
二、InputStream//以byte為單位輸入
       1.FileInputStream//讀取檔案可讀文字檔也可讀圖檔
       2.ObjectInputStream
三、OutputStream//以byte為單位輸出
       1.FileOutputStream//輸出成檔案
       2.ObjectOutputStream
四、Reader//以字元為單位輸入
       1.InputStreamReader
           a.FileReader
       2.BufferedReader
五、Writer//以字元為單位輸出
       1.OutputStreamWriter
           a.FileWriter
       2.BufferedWriter



一、File



查詢檔名、size、修改日期。
不可存取檔案內容。資料夾也是一種檔案。
File file1 = new File("路徑");
File file2 = new File(File 變數或String 路徑,String 檔案名稱);
list():列出資料夾內的檔名
delete():刪除檔案,如果資料夾內有檔案,必須先刪除

 

 

二、InputStream/OutputStream

1.FileInputStream/FileOutputStream
FileInputStream fis = new FileInputStream("路徑+檔名");
fis.read():以1byte為單位讀取的檔案內容,回傳整數值。
如果沒有讀到任何字元則會回傳-1。

FileOutputStream fos = new FileOutputStream("路徑檔名");
fos.write(int變數或byte陣列);//將檔案內容寫入fos
fos.close();//關閉檔案,如果不關閉會留在記憶體之中

tip:
1.
輸出到文字檔案以附加方式輸出
FileOutputStream fos = new FileOutputStream("路徑檔名",true);
不過用這樣方式輸出圖檔無法以附加方式輸出

2.
int available();//傳回所讀的檔案bytes大小。
這個method是FileInputStream僅有的
可以寫出檔案時事先知道檔案的大小。


  FileInputStream fi=new FileInputStream("D:/java/train.txt");//讀取檔案來源
        System.out.println("file size"+fi.available());//取得檔案大小
        byte ba[]=new byte[fi.available()];//宣告符合檔案大小的byte陣列
    fi.read(ba);//將檔案內容讀到ba
    System.out.println(new String(ba));//轉成字串,列印
    fi.close();


BufferedInputStream/BufferedOutputStream

在記憶體設立緩衝區,批次處理檔案的輸出與輸入,如此一來減少硬碟的讀取次數。
用法:BufferedInputStream bis = new BufferedInputStream(InputStream類別變數或者new InpuStream("路徑檔名"));




FileReader/FileWriter

用法與FileInputStream一樣
英文的文字檔傳輸沒有問題,ANSI檔案的中文字會發生亂碼,UTF8才可以正常輸出,傳輸圖檔會開不起來。


char data[] = new char[128];
    FileReader fr = new
            FileReader("D:\\java\\train.txt");
     int num=fr.read(data);   //將檔案傳入自原陣列,回傳讀的字元數目。
        //ANSI的中文字視為兩個字元(我這個字是為一個字元,UTF8檔案中文視為一個字元)
     System.out.println(num);//列印檔案讀去的字元數
     System.out.println("-------------------------");
     System.out.println(data);//列印陣列的內容
     
String str = new String(data,0,num);
//String(char[],起始點,轉換長度);

System.out.println(str);
//轉換字串後列印結果跟轉換前是一樣的
 
}
}



BufferedReader/BufferedWriter

用法跟BufferedInputStream一樣

BufferedReader除了read()方法之外也可以用
readLine()從檔案抓取文字,一次抓取一行,readLine回傳字串值。

將檔案輸出到新的文字檔並不會自動換行
要用BufferedWriter的方法newLine()才會換行


PrintWriter

官方文件說這是格式化輸出。目前不知道何謂格式化輸出?
句法跟BufferedWrtier一樣,照樣造句
PrintWriter bw1=new PrintWriter(new FileWriter(路徑));
用bw1.println(String變數)
輸出文字到檔案,會自動換行


DataInputStream/DataOutputStream



ObjectInputStream/ObjectOutputStream

以物件型式讀入、讀出資料。

原本資料是物件(ex:在程式碼裡面宣告類別建立物件),以文字型式將資料寫入檔案內,之後取出來便無法以物件方式取出。所以無法直接取得類別的屬性值。

要使用ObjectOutputStream類別將物件寫入檔案,該物件必須是可序列化(serializable)物件。該物件以及該物件內所屬的類別必須實作Serializable介面。否則會產生NotSerializableException事件。
ObjectInputStream則是用反序列化將物件從檔案讀取。
序列化:將物件內所有的屬性以及相關資料依照一定的順序轉成byte型式後寫入檔案。

如果有屬性不想被序列化那麼要在屬性前面加上transient或者static修飾詞。


(將資料輸出檔案用文字編輯器開啟是亂碼,看起來前面部分是描述物件的schema,後面部分是描述個物件的屬性值)

應用:檔案存取、網路資料傳送、影像檔案傳送


範例:
class book implements Serializable{//即將被序列化所以要實作Serializable
String name;//這個name也是物件,類別庫裡面已經實作介面所以我們不用再對他實作
double price;//同上
String author;//同上
public book(String name,double price,String author){
this.name=name;
this.price=price;
this.author=author;
}
public void show(){
System.out.println("書名"+name);
System.out.println("定價"+price);
System.out.println("作者"+author);
}}

File file = new File("D:/temp/kaiba.txt");//隨便準備一個檔案,作為輸出檔案
      book[] books = new book[2];//宣告類別陣列
      books[0]=new book("Conan",100.0,"formosa");
      books[1]=new book("Doraemon",99.9,"FFFF");
   
      FileOutputStream fos = new FileOutputStream(file);//將檔案(file)與OutputStream串接
      ObjectOutputStream oos = new ObjectOutputStream(fos);//串接
      for(Object book:books)//foreach
    oos.writeObject(book);//將物件寫入outputstream,而且被轉換成Object類型
 
      oos.close();
      fos.close();
      //-------------------以下讀取檔案--------------------//
      FileInputStream fis= new FileInputStream(file);//將剛剛的檔案與inputStream串接
      ObjectInputStream ois = new ObjectInputStream(fis);//串接
      System.out.println(file.getName()+"檔案內容如下");
      System.out.println("-----------------");
      try{
    while(true){ 
      ((book)ois.readObject()).show();
//讀取物件並轉換成book(因為讀出的是object物件),並呼叫show method
    }
      }catch(Exception e){
//處理例外,讀到沒有物件時會拋出例外,所以用try catch
      }
      ois.close();
      fis.close();
}

InputStreamReader/OutputStreamWirter

InputStreamReader是byte轉成字元的橋樑。讀取byte轉成字元。
OutputStreamWriter是字元轉成byte的橋樑
轉成什樣字元端看平台的字元預設值。用netbean執行打中文出現亂碼。
因為平台字元預設為utf8處理字元,
我們可以用System.out.println(OSWout.getEncoding());
得知目前用什麼編碼處理字串。
如果處理中文字的話,要加上"big5"指定編碼
InputStreamReader ISRkeyin = new InputStreamReader(InputStream,"big5");
OutputStreamWriter OSWout = new OutputStreamWriter(OutputStream,"big5");
以上兩個缺一不可。


how:
基本操作SOP如下:

1. 指定資料源頭(source)
InputStream keyin = System.in;//源頭來自於使用者鍵盤輸入
InputStreamReader ISRkeyin = new InputStreamReader(keyin,"big5");//byte轉字元。因為System.in是InputStream以byte為單位處理。要丟入以字元為單位處了的buffer所以要轉換。
BufferedReader input = new BufferedReader(ISRkeyin);//字元

2.指定輸出目的地sink
FileOutputStream file = new FileOutputStream("D:/temp/ooxx.txt");//byte完單位
OutputStreamWriter OSWout = new OutputStreamWriter(file,"big5");//字元轉byte
BufferedWriter output = new BufferedWriter(OSWout);

3.
//System.out.println(ISRkeyin.getEncoding());
//System.out.println(OSWout.getEncoding());
String str;
while(( str=input.readLine())!=null) //程式執行到這裡會讓使用者輸入文字,我在這邊又在while這行多打上了分號,結果沒執行下方的程式。
{
if(str.equalsIgnoreCase("Q"))//忽略大小寫,檢查輸入字串
{
input.close();
output.close();
System.exit(-1);//告訴系統結束執行程式。否則仍會繼續執行while,然後拋出例外,也可以打上return ; 也有同樣效果
}

output.write(str);
//OSWout.write(str);//不用buffer也可以將文字輸出到檔案
output.newLine();
System.out.println("你剛才打的文字是:"+str);
}
4.關閉stream
input.close();
output.close();

    }



PS:若省略BufferedReader、BufferedWriter就無法直接讀取輸入String型態的串流\
BufferedReader沒有readLine()

2013年3月3日 星期日

asp.net大綱

一,web控制項:
textbox
droplist
button
label
二連結資料庫:
SqlDataSource
GridView
FormView
Datalist
三使用者控制項
Application
Session
Cookie

Back&Forth
Master_Page

四,ADO.net
Connection
DataAdapter
DataSet
BindingSource
  WriteXml
  ReadXml
AddCustomeersRow
五、command 物件介紹
資料圖表整理
多個資料及回傳的處理
多個command組合transaction

資料驗證
Requiredfield Validator
Compare
Custorm
Range
RangeExpression
ValidationSummary
連到Excel
streamwriteer
streamreader
system.io
file
file info
get file

例外處理

what:程式在"執行階段時"發生的錯誤,之後中斷執行程式。發生這種例外時又稱為拋出例外。例外發生時JVM會自動建立例外物件,將錯誤訊息存在物件內,如果沒有使用例外處理機制,會將物件內儲存的錯誤訊息輸出



which :
1.例外是java類別庫中java.lang底下的Throwable類別之子類別的物件
2.自訂例外


when:
編譯程式碼時不會找到的bug,執行程式時才會出現

1.執行處理檔案的程式,但找不到指定的檔案(NullPointException)
2.執行將使用者輸入的文字轉換成整數的程式,
但使用者輸入整數之外的值(NumberFormatException)

3.存取陣列時,陣列的索引超過陣列範圍
(ArrayIndexOutOfBoundException)

why:
防止例外發生時程式中途結束,繼續執行完程式。


how:
利用try...catch...finally處理,當例外發生時程式會執行catch區塊的程式。


try{
..........指定檢查是否發生例外部分.......
} catch(例外的類別 變數名稱){
......例外發生時,
例外的類別變數檢查例外發生事件是否符合宣告的類別。
之後執行這裡的程式。
}finally{
.......這裡可以省略不寫,不管有沒有例外發生一定會執行這邊......
如果有不管有無發生例外都要執行的程式時,就一定要寫在這邊
否則例外發生時會讓程式中斷
}



自訂例外類別:
1.宣告自訂例外類別,必須繼承Exception。
2.在想拋出例外的方法(method)名稱後面加上"throws 自訂的例外類別"。
3.在例外可能發生之處,利用"throw 代表物件的變數;"來拋出例外(踢皮球),丟給外呼叫此方法的方法。
throw new MyException();
(如果method 後面沒加上throws 例外類別的話,method內不可以加上 throw new MyException();)
4.在外一層方法(method)裡寫try....catch(MyException e),將例外處理掉

System.out.println(e);會列印例外外名稱以及發生所在行數

class MyException extends Exception{
}



處理不了例外,就會將例外丟改該方法的呼叫者處理,如果丟到main(),仍沒處理掉那麼就會中斷程式執行








Exception分成
RuntimeException、非RuntimeException(checked exception)

RuntimeException有自動拋出(throws)例外功能,如果method內產生RuntimeException例外物件
即使不使用throws拋出也會自動拋出,不必自己寫throws也不用try catch也可以編譯成功
但是不加上try catch執行階段如果產生RuntimeException就會輸出預設發生例外訊息


CheckedException:除了RuntimeException都是此類。
IOException(FileNotFoundException) InterruptedException
這類的例外沒有自動throws的功能,
如果產生例外事件
那麼要自己撰寫throws將其拋出或使用try catch否則會編譯失敗
像是Thread.sleep();  或者FileOutputStream這些東西

介面interface

介面:
長相與抽象類別相似

宣告方式跟宣告類別很像,有屬性與方法,但是沒有建構式。
無法建立物件。
只是介面宣告以interface
interface Univers{
public static final int age = 120;
abstract void show();
}

//以下是錯誤寫法,interface宣告為public那麼表示檔名要跟interface名稱一樣
//不可加上static,static是修飾method與基本型態變數
//不可加上final,介面是要給類別實作的。
public static final interface career{
int age =20;
abstract void show();

}



特性:
1.有成員變數與方法但是沒有建構式,成員變數必須初始化;方法一律為abstract
2.成員前面一般不加修飾子
3.介面的成員變數預設加上public static final;方法則是加上abstract即抽象方法,介面只有抽象方法,而且只能宣告為public。(抽象類別的method可以宣告public protected default,不可宣告為private)
由此可知介面無法變更成員變數的值,成員變數一定要是定值。無法在介面定義方法的內容。

4.介面無法建立物件
可以宣告介面型態的變數,存取實作介面類別的物件

(抽象類別可以有建構式)



實作(implement):
介面和類別一起使用,稱為實作。類似extends。
class detective implements career{

}
上面程式碼以detective實作carrer介面,如此一來detective類別就繼承carrer介面所擁有的成員變數與方法。


如果要建立detective類別的物件,必須在detective類別中,定義介面中所有的方法,換句話說,就是在detictive類別裡面將career裡面所有的方法,改寫一遍。而成員變數可以在實作類別裡面另行宣告,或者沿用介面的。但是不可更改介面的成員變數的值。



介面解決了java的類別無法多重繼承的問題,
一個類別不可有兩個父類別,如同一個兒子不能有兩個爸爸
但是可以有多個義父、師父。
介面讓類別實現了多重繼承。


以下以神鵰俠侶主角楊過為例子:

interface 歐陽鋒{void 蛤蟆功();}
interface 洪七公{void 打狗棒法();}
interface 郭靖{void 九陰真經();}

class 楊過 implements 洪七公,歐陽鋒,郭靖{

void 打狗棒法(){
.............
}
void 蛤蟆功(){
............
}
void 九陰真經(){......}

}

類別楊過,實作洪七公 歐陽鋒 郭靖三個介面
因此必須改寫override打狗棒法、蛤蟆功、九陰真經。


介面之間可以是繼承的關係。
例如表示成這樣:
interface 郭靖 extends 江南七怪,丘處機
{
.......
}



雖然介面機制類似抽象類別。
介面贏過抽象類別的地方是,抽象類別不可多重繼承。
抽象類別終究還是類別。




也可以用匿名內部類別實作介面的方法

interface Book{
void show();
}

class AnonymouClass{
public static void main(String[] args){
Book book =new Book(){
//----匿名內部類別的內容---
public void show(){System.out.println("ByeBye World");}
};
book.show();
}}


看起來很像new一個Book的物件


我們可以book.getClass().toString得知
book是class interfaceimplement.anonymousclass$1
book是實作匿名類別

抽象類別

abstract class
宣告類別時,在class前面加上abstract。
特性:
1.抽象類別無法透過new建立物件,因為她的抽象函數只有宣告,如果建立物件則物件根本不知要如何使用此抽象函數。通常是透過衍生類別來建立物件,建立的物件必須override抽象類別的方法。
2.抽象類別裡面可以宣告抽象方法(abstract method),抽象方法就是沒有實作內容的method。ex: abstract void show();抽象方法不可以宣告為private以便子類別可以繼承。當然也可以宣告一般的method。
3.若有宣告子類別的話,必須override抽象方法,否則編譯不過。


abstract class的子類別的method
名稱、型態、參數與父類別一樣時,
我們也可以利用父類別變數存取子類別的物件
但是父類別變數,無法呼叫子類別獨有的method



abstract class 也有constructor。