<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    KevinGong

      BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
      15 Posts :: 1 Stories :: 9 Comments :: 0 Trackbacks

    #

    /*
    ?* 簡單的讀/寫文本文件的示例
    ?* 這里包含了三個(gè)例子,即
    ?* 1. 將文件讀入到內(nèi)存(這里是StringBuffer)的例子
    ?* 2. 將內(nèi)容中的文本寫到文件
    ?* 3. 將一個(gè)文件的內(nèi)容讀出來寫入另一個(gè)文件中
    ?*??? 同時(shí)也展示了如果從輸入流中讀出來內(nèi)容寫入輸出流中(僅限文本流)
    ?* 三個(gè)例子可以獨(dú)立存在,所以根據(jù)需要只看其中一個(gè)就行了。
    ?*/

    import java.io.BufferedReader;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.io.PrintStream;
    import java.io.PrintWriter;

    public final class AccessTextFile {

    ??? /**
    ???? * 1. 演示將流中的文本讀入一個(gè) StringBuffer 中
    ???? * @throws IOException
    ???? */
    ??? public void readToBuffer(StringBuffer buffer, InputStream is)
    ??????? throws IOException {
    ??????? String line;??????? // 用來保存每行讀取的內(nèi)容
    ??????? BufferedReader reader = new BufferedReader(new InputStreamReader(is));
    ??????? line = reader.readLine();?????? // 讀取第一行
    ??????? while (line != null) {????????? // 如果 line 為空說明讀完了
    ??????????? buffer.append(line);??????? // 將讀到的內(nèi)容添加到 buffer 中
    ??????????? buffer.append("\n");??????? // 添加換行符
    ??????????? line = reader.readLine();?? // 讀取下一行
    ??????? }
    ??? }

    ??? /**
    ???? * 2. 演示將 StringBuffer 中的內(nèi)容讀出到流中
    ???? */
    ??? public void writeFromBuffer(StringBuffer buffer, OutputStream os) {
    ??????? // 用 PrintStream 可以方便的把內(nèi)容輸出到輸出流中
    ??????? // 其對象的用法和 System.out 一樣
    ??????? // (System.out 本身就是 PrintStream 對象)
    ??????? PrintStream ps = new PrintStream(os);??
    ??????? ps.print(buffer.toString());
    ??? }

    ??? /**
    ???? * 3*. 從輸入流中拷貝內(nèi)容到輸入流中
    ???? * @throws IOException
    ???? */
    ??? public void copyStream(InputStream is, OutputStream os) throws IOException {
    ??????? // 這個(gè)讀過過程可以參閱 readToBuffer 中的注釋
    ??????? String line;
    ??????? BufferedReader reader = new BufferedReader(new InputStreamReader(is));
    ??????? PrintWriter writer = new PrintWriter(new OutputStreamWriter(os));
    ??????? line = reader.readLine();
    ??????? while (line != null) {
    ??????????? writer.println(line);
    ??????????? line = reader.readLine();
    ??????? }
    ??????? writer.flush();???? // 最后確定要把輸出流中的東西都寫出去了
    ??????????????????????????? // 這里不關(guān)閉 writer 是因?yàn)?os 是從外面?zhèn)鬟M(jìn)來的
    ??????????????????????????? // 既然不是從這里打開的,也就不從這里關(guān)閉
    ??????????????????????????? // 如果關(guān)閉的 writer,封裝在里面的 os 也就被關(guān)了
    ??? }

    ??? /**
    ???? * 3. 調(diào)用 copyStream(InputStream, OutputStream) 方法拷貝文本文件
    ???? */
    ??? public void copyTextFile(String inFilename, String outFilename)
    ??????? throws IOException {
    ??????? // 先根據(jù)輸入/輸出文件生成相應(yīng)的輸入/輸出流
    ??????? InputStream is = new FileInputStream(inFilename);
    ??????? OutputStream os = new FileOutputStream(outFilename);
    ??????? copyStream(is, os);???? // 用 copyStream 拷貝內(nèi)容
    ??????? is.close(); // is 是在這里打開的,所以需要關(guān)閉
    ??????? os.close(); // os 是在這里打開的,所以需要關(guān)閉
    ??? }

    ??? public static void main(String[] args) throws IOException {
    ??????? int sw = 1;???? // 三種測試的選擇開關(guān)
    ??????? AccessTextFile test = new AccessTextFile();
    ???????
    ??????? switch (sw) {
    ??????? case 1: // 測試讀
    ??????? {
    ??????????? InputStream is = new FileInputStream("E:\\test.txt");
    ??????????? StringBuffer buffer = new StringBuffer();
    ??????????? test.readToBuffer(buffer, is);
    ??????????? System.out.println(buffer);???? // 將讀到 buffer 中的內(nèi)容寫出來
    ??????????? is.close();
    ??????????? break;
    ??????? }
    ??????? case 2: // 測試寫
    ??????? {
    ??????????? StringBuffer buffer = new StringBuffer("Only a test\n");
    ??????????? test.writeFromBuffer(buffer, System.out);
    ??????????? break;
    ??????? }
    ??????? case 3: // 測試拷貝
    ??????? {
    ??????????? test.copyTextFile("E:\\test.txt", "E:\\r.txt");
    ??????? }
    ??????????? break;
    ??????? }
    ??? }

    }

    posted @ 2007-02-03 21:58 KevinGong 閱讀(31692) | 評論 (0)編輯 收藏

    這一章我主要介紹X系統(tǒng)用的主要配置文件XF86Config-4,我采用了對照的方法介紹,一邊貼出我的XF86Config-4文件,一邊介紹具體的內(nèi)容。這篇文章對于大家沒有什么立桿見影的幫助,不果可以讓你對于X的只是有一個(gè)基本的了解。

    XF86Config-4文件是X系統(tǒng)的主要配置文件。在Redhat 8以前版本中都叫做XF86Config-4這個(gè)名字,Redhat 8已經(jīng)不再叫做這個(gè)名字。

    編輯這個(gè)文件需要小心謹(jǐn)慎一點(diǎn),因?yàn)橐稽c(diǎn)錯(cuò)誤,你的X將不能啟動(dòng)。不果沒關(guān)系啦,改回來就是了學(xué)習(xí)Linux最好的辦法當(dāng)然還是求助于男人(man),大家有什么問題盡管看看man的幫助就是了。如果你要?jiǎng)h除文件中的內(nèi)容,最好不要直接的刪除,而應(yīng)該在前面加上#符號把它變成注釋。

    在Redhat 8以前的版本中,X的配置工具是Xconfigurator,在Debian中X的配種方法是:
    dpkg-reconfigure xserver-xfree86
    當(dāng)然你都得用root的身份來運(yùn)行。

    在/usr/share/doc/xfree86-common/FAQ.gz文件中你可以看到具體的技巧。


    第一段是Files段,這個(gè)部分用來配置X系統(tǒng)說能夠使用的字體,每一行都代表一個(gè)目錄,保存了具體的字體和字體的配置信息。
    代碼:

    Section "Files"
    ? ?? ???FontPath? ?? ???"/usr/X11R6/lib/X11/fonts/xp"
    ? ?FontPath? ?? ???"/usr/X11R6/lib/X11/fonts/XChinese"
    ? ?FontPath? ?"unix/:7100"? ?? ?? ?# 這是本地字體服務(wù)器
    ? ?# 如果本地字體服務(wù)器出了問題,我們可以使用下面的配置
    ? ?FontPath? ?"/usr/lib/X11/fonts/misc"
    ? ?FontPath? ?"/usr/lib/X11/fonts/cyrillic"
    ? ?FontPath? ?"/usr/lib/X11/fonts/100dpi/:unscaled"
    ? ?FontPath? ?"/usr/lib/X11/fonts/75dpi/:unscaled"
    ? ?FontPath? ?"/usr/lib/X11/fonts/Type1"
    ? ?FontPath? ?"/usr/lib/X11/fonts/Speedo"
    ? ?FontPath? ?"/usr/lib/X11/fonts/100dpi"? ?#這兩個(gè)字體是每一個(gè)X
    ? ?FontPath? ?"/usr/lib/X11/fonts/75dpi"? ?#系統(tǒng)都必需安裝的英文字體
    EndSection

    下面的是模塊段,用來配置X系統(tǒng)加載的模塊。
    代碼:

    Section "Module"
    ? ?Load? ?"xtt"? ?? ?#gtk1使用的字體引擎,效果好,速度稍慢
    ? ?Load? ?"GLcore"? ?#如果你是用的是Nvidia的顯卡,似乎一定要注消掉這一行
    ? ?Load? ?"bitmap"
    ? ?Load? ?"dbe"
    ? ?Load? ?"ddc"
    ? ?Load? ?"dri"
    ? ?Load? ?"extmod"
    #? ?Load? ?"freetype"? ?#如果你使用了xtt模塊,那么freetype模塊就需要注消掉
    ? ?Load? ?"glx"
    ? ?Load? ?"int10"
    ? ?Load? ?"record"
    ? ?Load? ?"speedo"
    ? ?Load? ?"type1"
    ? ?Load? ?"vbe"
    EndSection


    下面的段是用來配置你的鍵盤的,屬于“輸入設(shè)備”
    代碼:

    Section "InputDevice"
    ? ?Identifier? ?"Generic Keyboard"? ?#這是你的鍵盤的名字,隨便你啦
    ? ?Driver? ?? ?"keyboard"? ?? ?#鍵盤的驅(qū)動(dòng)…哇,鍵盤也有驅(qū)動(dòng)
    ? ?Option? ?? ?"CoreKeyboard"? ?? ?#如果你有多個(gè)鍵盤,那么你需要在這里指定哪一個(gè)鍵盤是主要的鍵盤
    ? ?Option? ?? ?"XkbRules"? ?"xfree86"
    ? ?Option? ?? ?"XkbModel"? ?"pc104"? ?#鍵盤的分布格式,一般來說
    ? ?Option? ?? ?"XkbLayout"? ?"us"? ?#美國104鍵盤是大家通用的。
    EndSection


    這里配置你的鼠標(biāo),當(dāng)然你可以配置兩個(gè)鼠標(biāo),如果你有的話
    代碼:

    Section "InputDevice"
    ? ?Identifier? ?"Configured Mouse"? ?#鼠標(biāo)的名字
    ? ?Driver? ?? ?"mouse"? ?? ?? ?#鼠標(biāo)的驅(qū)動(dòng)
    ? ?Option? ?? ?"CorePointer"? ?? ?
    ? ?Option? ?? ?"Device"? ?? ?"/dev/input/mice"
    ? ?#注意,這里很重要,這是鼠標(biāo)的設(shè)備文件
    ? ?#我的鼠標(biāo)是光電鼠標(biāo),用的USB接口,對應(yīng)的鼠標(biāo)文件是/dev/input/mice
    ? ?#如果你的鼠標(biāo)是普通的滾輪鼠標(biāo),用的是PS2接口,那么你應(yīng)該使用
    ? ?#/dev/mouse或者/dev/psaux或者/dev/ttys0這個(gè)設(shè)備
    ? ?Option? ?? ?"rotocol"? ?? ?"ImPS/2"
    ? ?#這是鼠標(biāo)的類型,如果不是是滾輪鼠標(biāo),那么使用PS/2
    ? ?Option? ?? ?"Emulate3Buttons"? ?"true"
    ? ?#在Linux系統(tǒng)中,鼠標(biāo)的第三個(gè)鍵非常有用,
    ? ?#如果你的鼠標(biāo)沒有第三個(gè)鍵,那么我們應(yīng)該允許使用雙鍵同時(shí)點(diǎn)擊來模擬
    ? ?Option? ?? ?"ZAxisMapping"? ?? ?"4 5"
    EndSection


    下面的設(shè)備是顯卡,這是最頭痛的設(shè)備了,如果你的顯卡太新潮,很有可能不能支持哦。Nvidia的GForce2顯卡就必需自己編譯顯卡的驅(qū)動(dòng)程序才能使用
    代碼:

    Section "Device"
    ? ?Identifier? ?"Generic Video Card"
    ? ?Driver? ?? ?"ati"? ?? ?#如果你是Nivida的顯卡,這里應(yīng)該是"nvidia"
    EndSection



    這個(gè)設(shè)備是顯示器。
    代碼:

    Section "Monitor"
    ? ?Identifier? ?"Generic Monitor"? ?#顯示器的名字
    ? ?HorizSync? ?30-60? ?? ?? ?#顯示器的頻率,一半來說你的顯示器
    ? ?VertRefresh? ?50-75? ?? ?? ?#應(yīng)該可以達(dá)到我的這個(gè)水平
    ? ?? ?? ?? ?? ?? ?#因?yàn)槲业娘@示器是15"的老顯示器了
    ? ?? ?? ?? ?? ?? ?#大家的電腦都比我的好吧?
    ? ?Option? ?? ?"DPMS"
    EndSection


    下面是綜合以上你的配置的設(shè)備的各種顯示效果
    代碼:

    Section "Screen"
    ? ?Identifier? ?"Default Screen"? ?#效果的名字
    ? ?Device? ?? ?"Generic Video Card"? ?#你可以指定你的顯卡的名字
    ? ?Monitor? ?? ?"Generic Monitor"? ?#指定你的顯示器的名字
    ? ?DefaultDepth? ?24? ?? ?? ?#默認(rèn)的顏色深度
    ? ?SubSection "Display"
    ? ?? ?Depth? ?? ?1
    ? ?? ?Modes? ?? ?"1024x768"
    ? ?EndSubSection
    ? ?SubSection "Display"
    ? ?? ?Depth? ?? ?4
    ? ?? ?Modes? ?? ?"1024x768"
    ? ?EndSubSection
    ? ?SubSection "Display"
    ? ?? ?Depth? ?? ?8
    ? ?? ?Modes? ?? ?"1024x768"
    ? ?EndSubSection
    ? ?SubSection "Display"
    ? ?? ?Depth? ?? ?16
    ? ?? ?Modes? ?? ?"1024x768"? ?#在這里你可以指定掃描頻率例如
    ? ?? ?? ?? ?? ?? ?#"1024x768 @ 85"就是用85mhz的頻率
    ? ?EndSubSection
    ? ?SubSection "Display"
    ? ?? ?Depth? ?? ?24
    ? ?? ?Modes? ?? ?"1024x768"
    ? ?EndSubSection
    EndSection



    最終你必需定義下面的段用來告訴X服務(wù)器你使用的配置
    代碼:

    Section "ServerLayout"
    ? ?Identifier? ?"Default Layout"? ?#剛才我們給我們的配置取的名字
    ? ?Screen? ?? ?"Default Screen"? ?#給我們的效果取的名字
    ? ?InputDevice? ?"Generic Keyboard"? ?#我們的鍵盤的名字
    ? ?InputDevice? ?"Configured Mouse"? ?#我們的鼠標(biāo)的名字
    ? ?? ?? ?? ?? ?#這些名字一定要在前面的配置中已經(jīng)定義
    EndSection

    Section "DRI"
    ? ?Mode? ?0666
    EndSection



    一般來說我們X啟動(dòng)時(shí)候會(huì)遇到的問題是:
    1:no screen found
    這有可能是你沒有正確的定義所需要的效果,也有可能是你的其他部分定義出錯(cuò)倒置你的效果不能實(shí)現(xiàn)
    2:xtt和freetype的沖突,注消一個(gè)就可以了
    3:驅(qū)動(dòng)沒有找到,如果你的顯卡非常的新潮,那么多半是這個(gè)錯(cuò)誤了,編譯你的驅(qū)動(dòng)吧…

    posted @ 2006-10-29 14:26 KevinGong 閱讀(279) | 評論 (0)編輯 收藏

    現(xiàn)在請輸入你的用戶名和密碼,當(dāng)然,我們輸入root,這樣獲得一切管理權(quán)限!

    你一定非常希望立刻看到那些非常漂亮的圖形界面,但是也許我要讓你失望了。我建議在沒有使用圖形界面以前,首先熟練的掌握基本的Linux命令,這樣才是一個(gè)真正的Linuxer。從哪里開始呢?

    1. ls 列出文件和目錄的命令

    你一定很想知道你的電腦里面有哪些東西,現(xiàn)在執(zhí)行命令ls,啊,怎么什么都沒有?當(dāng)然啦,這是你第一次登錄到這個(gè)系統(tǒng),你的默認(rèn)位置是你的個(gè)人目錄,而不是系統(tǒng)根目錄。你還沒有在這個(gè)目錄里面存放任何的個(gè)人文件,當(dāng)然什么都沒有啦。如果你是用root用戶登錄的話,你的個(gè)人目錄就是/root目錄;如果你是用普通用戶登錄,比如叫做kris,那么kris的個(gè)人目錄是/kris。前面的/是什么意思呢?就是“根”的意思,就是最前面的那個(gè)目錄,在根目錄下面建立有很多的子目錄,我們在第一章已經(jīng)討論過了。

    ls命令有很多的選項(xiàng),常用的是:

    -A 選項(xiàng)用來列出所有的文件,包括那些隱藏的文件。為什么我們要隱藏文件呢?道理和你為什么要把情書藏起來不讓爸媽發(fā)現(xiàn)是一樣的。就是為了保密啊。現(xiàn)在執(zhí)行l(wèi)s -A看看?是不是有一個(gè)隱藏文件“.bashrc”被顯示出來啦?聰明的你一定奇怪的發(fā)現(xiàn)這個(gè)文件名前面有一個(gè)點(diǎn),對!記住,只要文件名前面第一個(gè)字符是一個(gè)“.”,這個(gè)文件就是隱藏文件。一個(gè)目錄名前面的第一個(gè)字符如果是“.”這個(gè)目錄就是隱藏目錄。
    -l 這個(gè)選項(xiàng)用來顯示一個(gè)列表,包含了這個(gè)目錄下面所有的文件的絕大部分屬性的列表。你可以每個(gè)文件的大小,所有者,你的權(quán)限還有修改日期等等。
    -R R的意思就是recursive遞歸,明顯這個(gè)選項(xiàng)讓系統(tǒng)顯示出這個(gè)目錄下面的所有文件以外,還要顯示出所有子目錄下面的文件。也就是把我們那一大堆水果全部抖出來。
    --color 這個(gè)選項(xiàng)特別有用,我估計(jì)大家的顯示器都是彩顯吧,什么?你的顯示器還是黑白的?天哪!既然是彩顯,那么我們可以讓ls命令用不同的眼色代表不同的文件類型。比如可執(zhí)行文件用綠色,普通文件是白色,目錄是藍(lán)色。也許你會(huì)問,目錄也是文件嗎?對的,在Linux里面一切都是文件,所有的硬件設(shè)備都用一個(gè)文件來代替,比如你的軟驅(qū),就是用/dev/fd0來代替的。目錄也是一個(gè)文件。
    --help 這個(gè)選項(xiàng)幾乎是每一個(gè)Linux命令都有的,用來顯示出該命令的幫助信息。

    2. cd 和 mkdir 以及 rm 改變當(dāng)然所在目錄,建立新目錄以及刪除目錄命令

    趁熱打鐵的,剛才說了目錄,我們每一次登錄都有一個(gè)默認(rèn)目錄就是我們的個(gè)人用戶目錄。我們怎么才能到其他的目錄去呢?cd就是用來改變當(dāng)前所在的目錄的。前面我們說過,“/”代表根目錄,那么執(zhí)行cd /就可以進(jìn)入根目錄。不試一下嗎?
    讓我們看看根目錄下面有哪些文件和子目錄吧,執(zhí)行l(wèi)s,我們發(fā)現(xiàn),根目錄下面有一個(gè)目錄名子特別變態(tài),叫做usr,進(jìn)去看看,cd usr,看看這里面有什么?你會(huì)發(fā)現(xiàn)一個(gè)更psycho(變態(tài))的目錄叫做src,進(jìn)入src目錄看看?沒什么好玩的。那么我們現(xiàn)在回到剛才的usr目錄,怎么做?是不是cd usr?執(zhí)行試一下,好像不行,系統(tǒng)報(bào)告出錯(cuò) cd: usr: No such file or directory。這是怎么搞的?問題在于我們現(xiàn)在所在的目錄是/usr/src下,我們執(zhí)行cd usr的意思是進(jìn)入/usr/src/usr目錄而不是/usr目錄。正確的方法是cd /usr。
    就好比你在中華美食的籮筐里面看到一個(gè)四川的籮筐,里面有一個(gè)成都的小籮筐,現(xiàn)在你進(jìn)入以后發(fā)現(xiàn)成都的小籮筐里面有一種叫做“麻辣燙”的很辣的食品。你大飽口福以后想要吃一些甜點(diǎn),于是準(zhǔn)備去福州。你能站在成都的籮筐里面去福州嗎?當(dāng)然不行,福州并不在成都的籮筐里面啊,你應(yīng)該進(jìn)入“/中華美食/福州”而不是“/中華美食/四川/成都/福州”對不對?
    好的,一個(gè)問題出現(xiàn)了,難道我每一次進(jìn)入一個(gè)目錄,都要用/usr/src...這么復(fù)雜的方式來表示嗎?不一定。我們用“..”的方式來表示上一層目錄。如果你現(xiàn)在在/usr/src目錄下,進(jìn)入/usr目錄有兩種辦法:cd /usr和cd ..他們是一樣的。

    怎樣才能知道我現(xiàn)在在哪個(gè)目錄?用命令pwd,這個(gè)命令沒有什么好說的,執(zhí)行一次就知道了。

    現(xiàn)在我想在我自己的個(gè)人目錄里面建立一個(gè)目錄叫做LoveLetter。我應(yīng)該首先回到我自己的目錄,這里有一個(gè)簡單的方法,就是直接運(yùn)行cd不帶任何參數(shù),這樣就可以回到自己的目錄,當(dāng)然也可以cd /root或者cd /home/kris,看你是用什么用戶登錄的。
    進(jìn)入我自己的目錄以后,建立新目錄的命令是
    mkdir 新目錄名
    我執(zhí)行 mkdir LoveLetter 就可以建立一個(gè)新的叫做LoveLetter的目錄。進(jìn)入這個(gè)目錄看看?什么都沒有。不著急,慢慢來。我都不著急你急什么?
    突然我想起這臺(tái)電腦我的爸媽也要使用,他們看到我的情書目錄怎么辦?你忘了剛才我說的可以用加一個(gè)點(diǎn)“.”在前面的方法來隱藏目錄和文件的?我們可以改變這個(gè)目錄的名字,但是這個(gè)命令我準(zhǔn)備等會(huì)兒講,現(xiàn)在我們用一個(gè)很無聊的辦法來完成這個(gè)要求。這個(gè)辦法就是刪掉剛才建立的oveLetter目錄在新建一個(gè).LoveLetter目錄,之所以說這個(gè)辦法很無聊,是因?yàn)槲覀儸F(xiàn)在是在做實(shí)驗(yàn),如果來真的,你原意刪掉你的情書嗎?是不是另有新歡啦?哈哈。

    刪除目錄的命令其實(shí)也可以刪除文件,就是rm。
    rm 待刪除的文件名/目錄名
    我記得Redhat會(huì)提示你是不是真的要?jiǎng)h除。按y就是確定,按n就是取消。如果Redhat沒有提示你,那么等會(huì)請根據(jù)我說的方法修改一下系統(tǒng)讓它提示咱們。免得以后心痛。刪除一個(gè)文件很簡單。麻煩的是刪除一個(gè)目錄,如果一個(gè)目錄里面已經(jīng)有文件,rm是不讓直接刪除的,你必需先把目錄里面的所有文件刪除,再刪除目錄。但是有一個(gè)參數(shù)可以改變一下,就是 -rf ,這個(gè)參數(shù)有一定的危險(xiǎn)性,因?yàn)榧词瓜到y(tǒng)本來要提醒一下是不是真的刪除目錄,加上這個(gè)參數(shù)也不會(huì)有提示了。執(zhí)行rm 目錄 -rf會(huì)在一眨眼的時(shí)間里面讓你的資料下課!
    那么我現(xiàn)在就刪除LoveLetter目錄了:rm LoveLetter -rf
    建立一個(gè)新的目錄mkdir .LoveLetter
    現(xiàn)在ls看看,是不是看不到LoveLetter目錄了?但是ls -A還是能看到的。所以這種隱藏方式只能偏偏自己,真正讓你的文件安全的方式還是以后再講吧。

    3. mv 改變文件名和目錄名的命令
    cp 復(fù)制文件和目錄命令
    man 命令使用方法參考工具

    mv 老文件名 新文件名
    mv 老目錄名 新目錄名
    就可以改變文件或者目錄的名字。
    我現(xiàn)在想要把剛才的這個(gè)目錄.LoveLetter改名回去,因?yàn)檫@種無聊的隱藏方式很變態(tài),我們有更高級的方法來做這樣一件事情:就是不要告訴爸媽你的密碼!!!
    mv .LoveLetter LoveLetter

    cp命令用來把一個(gè)文件復(fù)制成為一個(gè)新的文件,

    cp 老文件名 新文件名

    這個(gè)老文件明和新文件名如果在同一個(gè)目錄下面,那么當(dāng)然需要名字不一樣,很簡單的道理,如果文件名一樣何必建立兩個(gè)文件?如果新老文件在不同的目錄,我們就可以讓它們有相同的名子。下面的例子說明了這一點(diǎn):

    cp LoveLetter LoveLetter_yesterday 新的文件LoveLetter_yesterday和舊的LoveLetter在同一個(gè)目錄,所以名子不一樣。
    cp LoveLetter /home/LoveLetter 新的文件在/home目錄下面,但是舊的文件LoveLetter在某一個(gè)用戶的個(gè)人目錄下面,當(dāng)然兩者名子可以相同。

    cp命令也可以復(fù)制整個(gè)目錄,但是現(xiàn)在我們暫時(shí)不講這么復(fù)雜。其實(shí)cp還有rm以及l(fā)s這些命令不僅是整個(gè)Linux的基本命令,更包含了非常多的功能。如果大家有興趣,可以使用man

    man 命令名字

    比如man ls,這樣就可以看到所有l(wèi)s命令和參數(shù)的詳悉解釋,尤其是一部分常用的命令的man幫助已經(jīng)由志愿者翻譯了,大家看起來更容易。

    一點(diǎn)幽默

    好了,說了好多東西了,我想休息一下,給大家說一個(gè)有趣的事情,我們說了好多命令和目錄的名子,你們是不是覺得有點(diǎn)奇怪。說實(shí)在話,我第一次看到usr這個(gè)目錄時(shí)也不知道是什么意思,后來才發(fā)現(xiàn)以下對應(yīng)關(guān)系:
    usr ->; user
    ls ->; list
    mkdir ->; make dir
    rm ->; remove
    src ->; source
    mv ->; move
    cp ->; copy

    是不是很有趣,在UNIX世界,包括Linux世界,人們的想象力就是這么無敵!簡寫居然能簡寫成這樣子。大家一般的想法是取一個(gè)單詞的前三個(gè)或者前四個(gè)字母作為簡寫,可是UNIX的牛人就是喜歡把move簡寫成為mv,真不知道他們怎么想的。大家一起捉摸吧

    4. nano 和 vi編輯文件的命令 和 cat 以及 more顯示文本文件

    nano是一個(gè)小巧自由,并且友好的編輯器,我認(rèn)為nano更適合初學(xué)Linux的朋友使用。我們現(xiàn)在只學(xué)習(xí)怎樣編輯一個(gè)文件以及怎樣保存。

    nano 文件名

    如果你寫的文件名已經(jīng)存在,那么就打開并且編輯,否則就建立一個(gè)新的文件。編輯的方法還用說嗎?呵呵,當(dāng)你想要退出的時(shí)候,按ctrl+x,nano會(huì)問你是不是保存編輯的文件。按Y就是保存,按N就不保存。

    nano最大好處在于用戶可以不用記憶太多的操作鍵,大部分常用的功能的操作方法都在屏幕下放列出了。新手需要注意的是“^X”就是按住ctrl鍵不放再按X的意思。

    下面簡單的介紹vi。vi是一個(gè)非常強(qiáng)大的編輯軟件。它太龐大了,足夠?qū)懸槐緯鴮iT來講解。我們這里從使用的角度出發(fā),講一下vi的用法。
    vi有兩種模式,一種是命令模式,一種是編輯模式。進(jìn)入vi以后,默認(rèn)處于命令模式。

    現(xiàn)在我們執(zhí)行vi LoveLetter。進(jìn)入以后,按一下鍵盤上的Insert功能鍵或者i鍵可以進(jìn)入編輯狀態(tài),可以插入字符,再按一下Insert變成復(fù)蓋模式,這兩種模式的區(qū)別很容易體現(xiàn),大家嘗試一下就可以了。上下左右四個(gè)方向鍵可以移動(dòng)光標(biāo)。基本的編輯命令和Windows里面沒有區(qū)別。是不是很容易呢?當(dāng)你把需要的內(nèi)容輸入完成以后,我們要保存,這時(shí)候按一下ESC鍵從編輯模式回到命令模式,首先輸入一個(gè)冒號“:”,也就是按住SHIFT鍵不放再按分號“;”這樣首先輸入一個(gè)“:”,然后,輸入w,回車,就可以保存我們編輯的內(nèi)容到LoveLetter文件。現(xiàn)在我們按一下Insert就可以繼續(xù)編輯。再按ESC,輸入“:”,再按w又可以保存。可是現(xiàn)在我們不需要保存,我們想要不保存就退出,怎么做呢?當(dāng)我們輸入w的時(shí)候是write的意思,保存,那么我們輸入q就是quit退出的意思。好,輸入q,回車,vi提示我們剛才進(jìn)行的修改還沒有保存,所以記住!一旦需要放棄我們的修改,不能直接用q命令退出,而需要用“q!”命令。輸入q!,好了,退出了。
    我們想看看我們剛才編輯的LoveLetter是不是真的保存好了,再vi LoveLetter,ok,看到了吧?現(xiàn)在我們想要直接退出,就可以只輸入“:q”就可以了,不用輸入那個(gè)“!”因?yàn)槲覀儧]有修改文件內(nèi)容。如果我們修改一下這篇文章,我們在退出的時(shí)候可以輸入“ESC : wq”就可以了。不需要把w和q分成兩次輸入。

    vi的最最基本用法說到這里差不多了,要是你還想多了解一些vi的知識,在進(jìn)入vi以后直接按F1就可以了,有詳悉的幫助和教學(xué)。

    其實(shí)剛才我們想要看一下編輯的LoveLetter是不是保存好了,不用再vi進(jìn)去的,只需要用命令

    cat LoveLetter

    就可以了。cat就是用來顯示文本文件內(nèi)容的命令。如果我們的文本文件很長,一個(gè)屏幕顯示不完,cat是不會(huì)自動(dòng)分頁的。我們可以換用命令

    more LoveLetter

    more命令顯示文本文件時(shí),如果內(nèi)容過多,會(huì)自動(dòng)的在每一頁結(jié)束時(shí)暫停下來,等到用戶按一下空格鍵再繼續(xù)。

    5. 最重要的命令:halt reboot 關(guān)機(jī)和重新啟動(dòng)命令

    在Linux里面,不能夠直接用電源按鈕關(guān)機(jī),也不能直接用reset按鈕重新啟動(dòng),這對系統(tǒng),尤其是硬盤有比較大的影響。關(guān)機(jī)命令是halt,重啟動(dòng)命令是reboot。其實(shí)還有shutdown命令完成類似功能,需要的話,請用今天學(xué)會(huì)的man命令學(xué)習(xí)使用。
    posted @ 2006-10-29 14:17 KevinGong 閱讀(436) | 評論 (1)編輯 收藏

    http://www.m-heaven.com/dreamweaver/
    posted @ 2006-09-22 14:23 KevinGong 閱讀(499) | 評論 (2)編輯 收藏

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "<html xmlns="<head>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
    <title>無標(biāo)題文檔</title>
    </head>

    <body>
    <p>
    ? <object id="player" style="display:none" height="400" width="400" classid="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6">
    ??? <param name="invokeURLs" value="-1">
    ??? <param NAME="AutoStart" VALUE="-1">
    ??? <param name="currentPosition" value="0">
    ??? <param name='uiMode' value='mini'>
    ??? <param NAME="url" VALUE="test.mpg">
    ? </object>
    </p>
    <input name="submit" type="submit" onclick="getInfo()">
    <p>
    ?
    <script language="javascript">
    ?var time;
    ? function getInfo(){
    ??var pl=document.getElementById("player");
    ?? time=pl.currentMedia.durationString;
    ?? alert(parseInt(pl.currentMedia.durationString.substring(0,2)*60));
    ?? //alert(parseInt(pl.currentMedia.durationString.substring(3,5)));
    ??alert(parseInt(pl.currentMedia.durationString.substring(0,2)*60)+parseInt(pl.currentMedia.durationString.substring(3,5)));
    ?}
    </script>
    </p>
    </body>
    </html>

    posted @ 2006-09-14 14:49 KevinGong 閱讀(4667) | 評論 (1)編輯 收藏

    ??? 首先,我們必須明確,為什么要使用J2EE?J2EE優(yōu)點(diǎn)是什么?使用J2EE的主要原因是多層結(jié)構(gòu),傳統(tǒng)的兩層C/S結(jié)構(gòu)難于維護(hù),穩(wěn)定性極差,界面代碼和數(shù)據(jù)庫代碼混淆在一起,牽一動(dòng)百,多層結(jié)構(gòu)使得界面和數(shù)據(jù)庫完全分離,并且誕生了中間件這樣的技術(shù),如下圖:

    Web+EJB能組成真正的多層結(jié)構(gòu)

      為什么使用EJB我原先認(rèn)為這不是一個(gè)討論的話題,因?yàn)镋JB是J2EE重要的組成部分,可以說沒有EJB的J2EE只是一種Web系統(tǒng),這樣的系統(tǒng)非常容易喪失了多層結(jié)構(gòu)的大部分優(yōu)點(diǎn)(仔細(xì)想想那些混合多種層次功能JavaBeans和傳統(tǒng)兩層結(jié)構(gòu)有什么區(qū)別?)。

      當(dāng)然,可以人為地在Javabeans之間進(jìn)行層次劃分,例如Hibernate算數(shù)據(jù)持久層,某些JavaBeans是業(yè)務(wù)核心層,但是因?yàn)槎际瞧胀↗avaBeans,這種劃分沒有一種強(qiáng)制性和明顯標(biāo)志性,這樣的系統(tǒng)更換了主創(chuàng)人員或設(shè)計(jì)師,可能就會(huì)被新的程序員修改得非常混亂。

      我們先看看一個(gè)包含EJB的J2EE系統(tǒng)是如何清晰地表達(dá)層次。如下圖:

      Web完全只是一個(gè)MVC模式的實(shí)現(xiàn),關(guān)鍵業(yè)務(wù)核心是在EJB的服務(wù)層實(shí)現(xiàn),這樣做的優(yōu)點(diǎn)是,Web只負(fù)責(zé)界面相關(guān)部分,因?yàn)椋绻且粋€(gè)智能客戶端,如Swing或J2ME,在不需要修改任何業(yè)務(wù)核心的情況下能夠方便地更換。同樣,提供Web Services功能,也只是在 Web層修改,不會(huì)涉及EJB方面的修改,同樣保證了系統(tǒng)的穩(wěn)定性,保證了系統(tǒng)升級和未來的擴(kuò)展性。

      如果不使用EJB,在EJB服務(wù)層實(shí)現(xiàn)的業(yè)務(wù)核心將由普通JavaBeans實(shí)現(xiàn),使用何種架構(gòu)或設(shè)計(jì)能夠保證負(fù)責(zé)MVC的JavaBeans和負(fù)責(zé)業(yè)務(wù)核心的JavaBeans清晰地分開,又如何保證在新的程序員不會(huì)破壞和打亂你精心布局的JavaBeans架構(gòu)?

    EJB提供性能優(yōu)化支持

      最主要的是性能問題,由于以前國內(nèi)中文Java網(wǎng)站有些人彎曲EJB,認(rèn)為EJB性能低,其實(shí)這是一種非常膚淺錯(cuò)誤的認(rèn)識,我們首先看看在一般Java環(huán)境中是如何提高性能。

      假定一個(gè)JavaBeans為A,那么一般使用這個(gè)JavaBeans命令如下:

      A a = new A();

      但是,在高訪問量的環(huán)境中,new A()其實(shí)是很費(fèi)時(shí)消耗系統(tǒng)性能的,因此,能不能在軟件系統(tǒng)啟動(dòng)時(shí)候就預(yù)先建立一些對象,這樣,系統(tǒng)運(yùn)行時(shí),從這些已經(jīng)生成的對象池中借用一個(gè),這樣,就無需在使用時(shí)進(jìn)行New,節(jié)約了開銷,提高了性能,因此,真正成熟性能解決方案都是需要對象池等支持。

      在一個(gè)純Web結(jié)構(gòu)的系統(tǒng)(也就是只能運(yùn)行在Tomat環(huán)境中),例如Struts + Hibernate等這樣的系統(tǒng),除非自己動(dòng)手做,一般是沒有對象池技術(shù)支持的,因此他們的性能只能算是Demo演示版本的性能,根本無法承受大容量并發(fā)訪問,也無法稱為一個(gè)成熟的系統(tǒng),所以,我們研究成熟的開源Web系統(tǒng),如Jive、OFBize,LifeRay等,他們都在Web層擁有自己的對象池和緩存池。

      對象池和緩存機(jī)制是J2EE必須的嗎?當(dāng)然,是所有成熟系統(tǒng)必須的,Windows系統(tǒng)如果去掉緩存將會(huì)變得怎樣?

      自己動(dòng)手開發(fā)對象池和緩存機(jī)制并不是一件簡單的事情,需要對多線程以及同步鎖等底層原理有深層次的把握,這其實(shí)也是一門非常深入的Java研究分支,所以,你可以拋開你的客戶焦急的催促,精心研究開發(fā)自己的對象池和緩存池。

      但是,EJB容器(如JBoss)已經(jīng)提供了對象池和緩存機(jī)制,所以,沒有事務(wù)機(jī)制的無狀態(tài)Session Bean的性能肯定要強(qiáng)于普通JavaBeans。EJB容器不但在單機(jī)中提供了對象池和緩存,而且可以跨服務(wù)器實(shí)現(xiàn)動(dòng)態(tài)負(fù)載平衡,這些都無需開發(fā)者自己開發(fā)任何軟件代碼,結(jié)構(gòu)如下:

    EJB組件能提供真正的可重用框架

      每一個(gè)jar包代表一個(gè)EJB組件,一個(gè)系統(tǒng)可以由多個(gè)可重用的EJB組件構(gòu)成,例如:樹形結(jié)構(gòu)EJB組件;自增序號EJB組件;用戶資料EJB組件等,這樣的EJB組件可以象積木一樣搭配在大部分應(yīng)用系統(tǒng)中,提高了系統(tǒng)的開發(fā)效率,保證了開發(fā)質(zhì)量。

      下圖是某個(gè)新的具體系統(tǒng)時(shí)應(yīng)用到的EJB組件圖,在這個(gè)新的應(yīng)用中,由于使用了以前大量可重用的EJB組件,新的開發(fā)工作基本集中在界面設(shè)計(jì)和流程安排上:

    EJB提供了事務(wù)機(jī)制

      事務(wù)機(jī)制對于一些關(guān)鍵事務(wù)是很重要的,例如ATM機(jī)提款,提款有多個(gè)動(dòng)作:修改數(shù)據(jù)庫以及數(shù)錢等,如果這其中有任何一個(gè)環(huán)節(jié)出錯(cuò),那么其它已經(jīng)實(shí)現(xiàn)的操作必須還原,否則,就會(huì)出現(xiàn),提款人沒有拿到錢,但是卡上已經(jīng)扣款等不可思議的事情發(fā)生。

      EJB提供的事務(wù)機(jī)制非常周全,但事務(wù)機(jī)制帶來的缺點(diǎn)是性能的降低,因此,有些人認(rèn)為EJB很重,因?yàn)樵趯?shí)際應(yīng)用中,有的用戶系統(tǒng)可能不需要事務(wù)機(jī)制,只是需要EJB提供的性能優(yōu)化機(jī)制,這樣,如果使用EJB,就象叫一個(gè)人來背東西,他除了背著我要的東西外,還背著我不要的東西。

      除非你是一個(gè)完美主義,在一般企業(yè)應(yīng)用或數(shù)據(jù)庫系統(tǒng)應(yīng)用中,EJB不會(huì)對你構(gòu)成很重的包袱。

    CMP獨(dú)特的優(yōu)點(diǎn)

      開源以及一些數(shù)據(jù)庫持久層技術(shù)崇拜者,一直抨擊CMP,認(rèn)為CMP慢無用,實(shí)際最大的問題是他們的設(shè)計(jì)和使用問題。

      由于EJB容器(如JBoss)對CMP實(shí)現(xiàn)有事務(wù)機(jī)制的緩存優(yōu)化,因此,CMP特別適合多個(gè)用戶同時(shí)更新同一個(gè)數(shù)據(jù)源的情況,CMP這種嚴(yán)格的事務(wù)完整性保證多個(gè)用戶同時(shí)操作一個(gè)數(shù)據(jù)記錄時(shí),能夠保證性能優(yōu)化和數(shù)據(jù)的完整性,如果這個(gè)數(shù)據(jù)記錄是是軟件系統(tǒng)的狀態(tài)標(biāo)志,它的狀態(tài)會(huì)影響系統(tǒng)中很多的環(huán)節(jié),那么狀態(tài)更改的重要性不言而喻。

      如果沒有事務(wù)完整性支持,你的軟件系統(tǒng)在用戶訪問量變大,就會(huì)變得發(fā)生各種不可能發(fā)生的邏輯錯(cuò)誤,查看程序邏輯是正確的,那么問題出在哪里?出在數(shù)據(jù)完整性上。

      由于每個(gè)CMP在內(nèi)存中都有一個(gè)緩存,在實(shí)際應(yīng)用中,如果使用CMP批量讀數(shù)據(jù)庫數(shù)據(jù),幾萬條查詢完畢,內(nèi)存中充滿了幾萬條CMP緩存,如果這時(shí)你的EJB容器設(shè)置不當(dāng)(如使用JBoss缺省配置),那么JVM的垃圾回收機(jī)制就會(huì)頻繁啟動(dòng),導(dǎo)致你的系統(tǒng)變慢甚至死機(jī),這也是一些人抨擊CMP慢的原因所在,其實(shí)他們使用方法不當(dāng),或者沒有正確配置EJB容器CMP緩存。

      對于這種情況,根據(jù)J2EE核心模式,推薦使用DAO+JDBC方式。

    小結(jié)

      除非你對設(shè)計(jì)模式非常精深,能夠?qū)⒆约合到y(tǒng)中的JavaBeans使用模式或某種框架進(jìn)行固定分層,同時(shí),你孜孜不倦研發(fā)出對象池,又熟練于JTA等事務(wù)機(jī)制,你可以選擇沒有EJB的純Web結(jié)構(gòu),就象Jive、OFBiz那樣。當(dāng)然還有一個(gè)前提,老板不懂或者非常有挑戰(zhàn)性(做與IBM SUN 微軟齊名的公司和技術(shù))。

      不要再被TSS那些狂熱的開源先生誤導(dǎo),他們有時(shí)間有保障可以做他們喜歡的事情,作為專業(yè)的J2EE程序員,按照J(rèn)2EE標(biāo)準(zhǔn)去學(xué)習(xí)去行動(dòng),也不要認(rèn)為,只要使用了J2EE其中某個(gè)技術(shù)如Jsp或JavaBeans就心安理得認(rèn)為自己的系統(tǒng)是J2EE了。

      當(dāng)然,我并不是說純Web系統(tǒng)不能實(shí)現(xiàn)多層結(jié)構(gòu),但是至少在很多方面沒有Web+EJB結(jié)構(gòu)完善和清晰,所以,EJB不是J2EE可以忽視的部分,而是主要的重要的部分,重要業(yè)務(wù)功能核心都封裝在EJB中,相反Web層是一種次要的、和界面相關(guān)的層次。

      補(bǔ)充:什么情況下不需要EJB,在SUN的SECA架構(gòu)師試卷中回答:小型系統(tǒng)和不需要事務(wù)。另外過去那種認(rèn)為“EJB有性能問題”根本是一種繆誤,具體可參考下面有關(guān)問題。

    posted @ 2006-09-11 14:56 KevinGong 閱讀(294) | 評論 (0)編輯 收藏

    java文件上傳,介紹幾種常用的方法,也是經(jīng)過本人親手調(diào)試過的
    1.jspsmartupload
    這個(gè)組件用起來是挺方便的,不過就是只適合小文件上傳,如果大文件上傳的話就不行,查看了一下他的代碼,m_totalBytes = m_request.getContentLength();?m_binArray = new byte[m_totalBytes];居然把整個(gè)上傳文件都讀到內(nèi)存去了,那如果是上傳幾十M的文件,同時(shí)幾個(gè)用戶上傳,服務(wù)器穩(wěn)掛,不過如果只是上傳5M以內(nèi)的小文件,這個(gè)組件還是挺實(shí)用的

    下面是源代碼:
    File類
    /*
    ?* 創(chuàng)建日期 2006-7-29
    ?*
    ?* 更改所生成文件模板為
    ?* 窗口 > 首選項(xiàng) > Java > 代碼生成 > 代碼和注釋
    ?*/
    package com.kinstar.issuing.file;

    /**
    ?* @author gongyifeng
    ?*
    ?* 更改所生成類型注釋的模板為
    ?* 窗口 > 首選項(xiàng) > Java > 代碼生成 > 代碼和注釋
    ?*/
    import java.io.ByteArrayInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.math.BigInteger;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Date;

    import javax.servlet.ServletException;

    // Referenced classes of package com.jspsmart.upload:
    // SmartUploadException, SmartUpload

    public class File{
    ?private SmartUpload m_parent;
    ?private int m_startData;
    ?private int m_endData;
    ?private int m_size;
    ?private String m_fieldname;
    ?private String m_filename;
    ?private String m_fileExt;
    ?private String m_filePathName;
    ?private String m_contentType;
    ?private String m_contentDisp;
    ?private String m_typeMime;
    ?private String m_subTypeMime;
    ?private String m_contentString;
    ?private boolean m_isMissing;
    ?public static final int SAVEAS_AUTO = 0;
    ?public static final int SAVEAS_VIRTUAL = 1;
    ?public static final int SAVEAS_PHYSICAL = 2;

    ?File(){
    ??m_startData = 0;
    ??m_endData = 0;
    ??m_size = 0;
    ??m_fieldname = new String();
    ??m_filename = new String();
    ??m_fileExt = new String();
    ??m_filePathName = new String();
    ??m_contentType = new String();
    ??m_contentDisp = new String();
    ??m_typeMime = new String();
    ??m_subTypeMime = new String();
    ??m_contentString = new String();
    ??m_isMissing = true;
    ?}

    ?public void saveAs(String s) throws IOException, SmartUploadException{
    ??saveAs(s, 0);
    ?}

    ?public void saveAs(String s, int i) throws IOException, SmartUploadException{
    ??String s1 = new String();
    ??s1 = m_parent.getPhysicalPath(s, i);
    ??if(s1 == null)
    ???throw new IllegalArgumentException("There is no specified destination file (1140).");
    ??try
    ??{
    ???java.io.File file = new java.io.File(s1);
    ???FileOutputStream fileoutputstream = new FileOutputStream(file);
    ???fileoutputstream.write(m_parent.m_binArray, m_startData, m_size);
    ???fileoutputstream.close();
    ??}
    ??catch(IOException ioexception)
    ??{
    ???throw new SmartUploadException("File can't be saved (1120).");
    ??}
    ?}

    ?public void fileToField(ResultSet resultset, String s) throws ServletException, IOException, SmartUploadException, SQLException{
    ??long l = 0L;
    ??int i = 0x10000;
    ??int j = 0;
    ??int k = m_startData;
    ??if(resultset == null)
    ???throw new IllegalArgumentException("The RecordSet cannot be null (1145).");
    ??if(s == null)
    ???throw new IllegalArgumentException("The columnName cannot be null (1150).");
    ??if(s.length() == 0)
    ???throw new IllegalArgumentException("The columnName cannot be empty (1155).");
    ??l = BigInteger.valueOf(m_size).divide(BigInteger.valueOf(i)).longValue();
    ??j = BigInteger.valueOf(m_size).mod(BigInteger.valueOf(i)).intValue();
    ??try
    ??{
    ???for(int i1 = 1; (long)i1 < l; i1++)
    ???{
    ????resultset.updateBinaryStream(s, new ByteArrayInputStream(m_parent.m_binArray, k, i), i);
    ????k = k != 0 ? k : 1;
    ????k = i1 * i + m_startData;
    ???}
    ???
    ???if(j > 0)
    ????resultset.updateBinaryStream(s, new ByteArrayInputStream(m_parent.m_binArray, k, j), j);
    ??}catch(SQLException sqlexception){
    ???byte abyte0[] = new byte[m_size];
    ???System.arraycopy(m_parent.m_binArray, m_startData, abyte0, 0, m_size);
    ???resultset.updateBytes(s, abyte0);
    ??}catch(Exception exception)
    ??{
    ???throw new SmartUploadException("Unable to save file in the DataBase (1130).");
    ??}
    ?}

    ?public boolean isMissing(){
    ??return m_isMissing;
    ?}
    ?
    ?public String getFieldName(){
    ??return m_fieldname;
    ?}
    ?
    ?public String getFileName(){
    ??DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
    ??String date = df.format(new Date());
    ??
    ??return date+m_filename;
    ?}
    ?
    ?public String getFilePathName(){
    ??return m_filePathName;
    ?}
    ?
    ?public String getFileExt(){
    ??return m_fileExt;
    ?}
    ?
    ?public String getContentType(){
    ??return m_contentType;
    ?}
    ?
    ?public String getContentDisp(){
    ??return m_contentDisp;
    ?}
    ?
    ?public String getContentString(){
    ??String s = new String(m_parent.m_binArray, m_startData, m_size);
    ??return s;
    ?}
    ?
    ?public String getTypeMIME() throws IOException{
    ??return m_typeMime;
    ?}
    ?
    ?public String getSubTypeMIME(){
    ??return m_subTypeMime;
    ?}
    ?
    ?public int getSize(){
    ??return m_size;
    ?}
    ?
    ?protected int getStartData(){
    ??return m_startData;
    ?}
    ?
    ?protected int getEndData(){
    ??return m_endData;
    ?}
    ?
    ?protected void setParent(SmartUpload smartupload){
    ??m_parent = smartupload;
    ?}
    ?
    ?protected void setStartData(int i){
    ??m_startData = i;
    ?}
    ?
    ?protected void setEndData(int i){
    ??m_endData = i;
    ?}
    ?
    ?protected void setSize(int i){
    ??m_size = i;
    ?}
    ?
    ?protected void setIsMissing(boolean flag){
    ??m_isMissing = flag;
    ?}
    ?
    ?protected void setFieldName(String s){
    ??m_fieldname = s;
    ?}
    ?
    ?protected void setFileName(String s){
    ??m_filename = s;
    ?}
    ?
    ?protected void setFilePathName(String s){
    ??m_filePathName = s;
    ?}
    ?
    ?protected void setFileExt(String s){
    ??m_fileExt = s;
    ?}
    ?
    ?protected void setContentType(String s){
    ??m_contentType = s;
    ?}
    ?
    ?protected void setContentDisp(String s){
    ??m_contentDisp = s;
    ?}
    ?
    ?protected void setTypeMIME(String s){
    ??m_typeMime = s;
    ?}
    ?
    ?protected void setSubTypeMIME(String s){
    ??m_subTypeMime = s;
    ?}
    ?
    ?public byte getBinaryData(int i){
    ??if(m_startData + i > m_endData)
    ???throw new ArrayIndexOutOfBoundsException("Index Out of range (1115).");
    ??if(m_startData + i <= m_endData)
    ???return m_parent.m_binArray[m_startData + i];
    ??else
    ???return 0;
    ?}?
    }

    Files類
    /*
    ?* 創(chuàng)建日期 2006-7-29
    ?*
    ?* 更改所生成文件模板為
    ?* 窗口 > 首選項(xiàng) > Java > 代碼生成 > 代碼和注釋
    ?*/
    package com.kinstar.issuing.file;

    /**
    ?* @author gongyifeng
    ?*
    ?* 更改所生成類型注釋的模板為
    ?* 窗口 > 首選項(xiàng) > Java > 代碼生成 > 代碼和注釋
    ?*/
    import java.io.IOException;
    import java.util.*;

    // Referenced classes of package com.jspsmart.upload:
    // File, SmartUpload

    public class Files{

    ?private SmartUpload m_parent;
    ?private Hashtable m_files;
    ?private int m_counter;
    ?
    ?Files(){
    ??m_files = new Hashtable();
    ??m_counter = 0;
    ?}
    ?
    ?protected void addFile(File file){
    ??if(file == null)
    ??{
    ???throw new IllegalArgumentException("newFile cannot be null.");
    ??} else?{
    ???m_files.put(new Integer(m_counter), file);
    ???m_counter++;
    ???return;
    ??}
    ?}
    ?
    ?public File getFile(int i)
    ?{
    ?if(i < 0)
    ??throw new IllegalArgumentException("File's index cannot be a negative value (1210).");
    ?File file = (File)m_files.get(new Integer(i));
    ?if(file == null)
    ??throw new IllegalArgumentException("Files' name is invalid or does not exist (1205).");
    ?else
    ??return file;
    ?}
    ?
    ?public int getCount()
    ?{
    ??return m_counter;
    ?}
    ?
    ?public long getSize() throws IOException
    ?{
    ??long l = 0L;
    ??for(int i = 0; i < m_counter; i++)
    ??l += getFile(i).getSize();
    ??
    ??return l;
    ?}
    ?
    ?public Collection getCollection()
    ?{
    ??return m_files.values();
    ?}
    ?
    ?public Enumeration getEnumeration()
    ?{
    ??return m_files.elements();
    ?}
    }

    Request類
    /*
    ?* 創(chuàng)建日期 2006-7-29
    ?*
    ?* 更改所生成文件模板為
    ?* 窗口 > 首選項(xiàng) > Java > 代碼生成 > 代碼和注釋
    ?*/
    package com.kinstar.issuing.file;

    /**
    ?* @author gongyifeng
    ?*
    ?* 更改所生成類型注釋的模板為
    ?* 窗口 > 首選項(xiàng) > Java > 代碼生成 > 代碼和注釋
    ?*/
    import java.util.Enumeration;
    import java.util.Hashtable;

    public class Request
    {

    ?private Hashtable m_parameters;
    ?private int m_counter;
    ?
    ?Request(){
    ??m_parameters = new Hashtable();
    ??m_counter = 0;
    ?}
    ?
    ?protected void putParameter(String s, String s1)?{
    ??if(s == null)
    ???throw new IllegalArgumentException("The name of an element cannot be null.");
    ??if(m_parameters.containsKey(s))
    ??{
    ???Hashtable hashtable = (Hashtable)m_parameters.get(s);
    ???hashtable.put(new Integer(hashtable.size()), s1);
    ??} else{
    ???Hashtable hashtable1 = new Hashtable();
    ???hashtable1.put(new Integer(0), s1);
    ???m_parameters.put(s, hashtable1);
    ???m_counter++;
    ??}
    ?}
    ?
    ?public String getParameter(String s){
    ?if(s == null)
    ??throw new IllegalArgumentException("Form's name is invalid or does not exist (1305).");
    ?Hashtable hashtable = (Hashtable)m_parameters.get(s);
    ?if(hashtable == null)
    ??return null;
    ?else
    ??return (String)hashtable.get(new Integer(0));
    ?}
    ?
    ?public Enumeration getParameterNames()
    ?{
    ??return m_parameters.keys();
    ?}
    ?
    ?public String[] getParameterValues(String s)
    ?{
    ??if(s == null)
    ???throw new IllegalArgumentException("Form's name is invalid or does not exist (1305).");
    ??Hashtable hashtable = (Hashtable)m_parameters.get(s);
    ??if(hashtable == null)
    ???return null;
    ??String as[] = new String[hashtable.size()];
    ??for(int i = 0; i < hashtable.size(); i++)
    ???as[i] = (String)hashtable.get(new Integer(i));
    ??
    ??return as;
    ?}
    }

    SmartUpload類
    /*
    ?* 創(chuàng)建日期 2006-7-29
    ?*
    ?* 更改所生成文件模板為
    ?* 窗口 > 首選項(xiàng) > Java > 代碼生成 > 代碼和注釋
    ?*/
    package com.kinstar.issuing.file;

    /**
    ?* @author gongyifeng
    ?*
    ?* 更改所生成類型注釋的模板為
    ?* 窗口 > 首選項(xiàng) > Java > 代碼生成 > 代碼和注釋
    ?*/
    import java.io.*;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.Vector;
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.jsp.JspWriter;
    import javax.servlet.jsp.PageContext;

    // Referenced classes of package com.jspsmart.upload:
    // Files, Request, SmartUploadException, File

    public class SmartUpload
    {

    ?protected byte m_binArray[];
    ?protected HttpServletRequest m_request;
    ?protected HttpServletResponse m_response;
    ?protected ServletContext m_application;
    ?private int m_totalBytes;
    ?private int m_currentIndex;
    ?private int m_startData;
    ?private int m_endData;
    ?private String m_boundary;
    ?private long m_totalMaxFileSize;
    ?private long m_maxFileSize;
    ?private Vector m_deniedFilesList;
    ?private Vector m_allowedFilesList;
    ?private boolean m_denyPhysicalPath;
    ?private boolean m_forcePhysicalPath;
    ?private String m_contentDisposition;
    ?public static final int SAVE_AUTO = 0;
    ?public static final int SAVE_VIRTUAL = 1;
    ?public static final int SAVE_PHYSICAL = 2;
    ?private Files m_files;
    ?private Request m_formRequest;
    ?
    ?public SmartUpload()
    ?{
    ??m_totalBytes = 0;
    ??m_currentIndex = 0;
    ??m_startData = 0;
    ??m_endData = 0;
    ??m_boundary = new String();
    ??m_totalMaxFileSize = 0L;
    ??m_maxFileSize = 0L;
    ??m_deniedFilesList = new Vector();
    ??m_allowedFilesList = new Vector();
    ??m_denyPhysicalPath = false;
    ??m_forcePhysicalPath = false;
    ??m_contentDisposition = new String();
    ??m_files = new Files();
    ??m_formRequest = new Request();
    ?}
    ?
    ?public final void init(ServletConfig servletconfig) throws ServletException
    ?{
    ??m_application = servletconfig.getServletContext();
    ?}
    ?
    ?public void service(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse)throws ServletException, IOException
    ?{
    ??m_request = httpservletrequest;
    ??m_response = httpservletresponse;
    ?}
    ?
    ?public final void initialize(ServletConfig servletconfig, HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse)throws ServletException
    ?{
    ??m_application = servletconfig.getServletContext();
    ??m_request = httpservletrequest;
    ??m_response = httpservletresponse;
    ?}
    ?
    ?public final void initialize(PageContext pagecontext)throws ServletException
    ?{
    ??m_application = pagecontext.getServletContext();
    ??m_request = (HttpServletRequest)pagecontext.getRequest();
    ??m_response = (HttpServletResponse)pagecontext.getResponse();
    ?}
    ?
    ?public final void initialize(ServletContext servletcontext, HttpSession httpsession, HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse, JspWriter jspwriter) throws ServletException
    ?{
    ??m_application = servletcontext;
    ??m_request = httpservletrequest;
    ??m_response = httpservletresponse;
    ?}
    ?
    ?public void upload()throws ServletException, IOException, SmartUploadException
    ?{
    ??int i = 0;
    ??boolean flag = false;
    ??long l = 0L;
    ??boolean flag1 = false;
    ??String s = new String();
    ??String s2 = new String();
    ??String s4 = new String();
    ??String s5 = new String();
    ??String s6 = new String();
    ??String s7 = new String();
    ??String s8 = new String();
    ??String s9 = new String();
    ??String s10 = new String();
    ??boolean flag2 = false;
    ??m_totalBytes = m_request.getContentLength();
    ??m_binArray = new byte[m_totalBytes];
    ??int j;
    ??for(; i < m_totalBytes; i += j)
    ??try
    ??{
    ???m_request.getInputStream();
    ???j = m_request.getInputStream().read(m_binArray, i, m_totalBytes - i);
    ??}
    ??catch(Exception exception)
    ??{
    ???throw new SmartUploadException("Unable to upload.");
    ??}
    ??
    ??for(; !flag1 && m_currentIndex < m_totalBytes; m_currentIndex++)
    ??if(m_binArray[m_currentIndex] == 13)
    ???flag1 = true;
    ??else
    ???m_boundary = m_boundary + (char)m_binArray[m_currentIndex];
    ??
    ??if(m_currentIndex == 1)
    ???return;
    ??for(m_currentIndex++; m_currentIndex < m_totalBytes; m_currentIndex = m_currentIndex + 2)
    ??{
    ???String s1 = getDataHeader();
    ???m_currentIndex = m_currentIndex + 2;
    ???boolean flag3 = s1.indexOf("filename") > 0;
    ???String s3 = getDataFieldValue(s1, "name");
    ???if(flag3)
    ???{
    ????s6 = getDataFieldValue(s1, "filename");
    ????s4 = getFileName(s6);
    ????s5 = getFileExt(s4);
    ????s7 = getContentType(s1);
    ????s8 = getContentDisp(s1);
    ????s9 = getTypeMIME(s7);
    ????s10 = getSubTypeMIME(s7);
    ???}
    ???getDataSection();
    ???if(flag3 && s4.length() > 0)
    ???{
    ????if(m_deniedFilesList.contains(s5))
    ?????throw new SecurityException("The extension of the file is denied to be uploaded (1015).");
    ????if(!m_allowedFilesList.isEmpty() && !m_allowedFilesList.contains(s5))
    ?????throw new SecurityException("The extension of the file is not allowed to be uploaded (1010).");
    ????if(m_maxFileSize > 0L && (long)((m_endData - m_startData) + 1) > m_maxFileSize)
    ?????throw new SecurityException("Size exceeded for this file : " + s4 + " (1105).");
    ????l += (m_endData - m_startData) + 1;
    ????if(m_totalMaxFileSize > 0L && l > m_totalMaxFileSize)
    ?????throw new SecurityException("Total File Size exceeded (1110).");
    ???}
    ???if(flag3)
    ???{
    ????com.kinstar.issuing.file.File file = new com.kinstar.issuing.file.File();
    ????file.setParent(this);
    ????file.setFieldName(s3);
    ????file.setFileName(s4);
    ????file.setFileExt(s5);
    ????file.setFilePathName(s6);
    ????file.setIsMissing(s6.length() == 0);
    ????file.setContentType(s7);
    ????file.setContentDisp(s8);
    ????file.setTypeMIME(s9);
    ????file.setSubTypeMIME(s10);
    ????if(s7.indexOf("application/x-macbinary") > 0)
    ?????m_startData = m_startData + 128;
    ?????file.setSize((m_endData - m_startData) + 1);
    ?????file.setStartData(m_startData);
    ?????file.setEndData(m_endData);
    ?????m_files.addFile(file);
    ????} else
    ????{
    ?????String s11 = new String(m_binArray, m_startData, (m_endData - m_startData) + 1);
    ?????m_formRequest.putParameter(s3, s11);
    ????}
    ????if((char)m_binArray[m_currentIndex + 1] == '-')
    ?????break;
    ????}
    ?
    ???}
    ?
    ?public int save(String s)throws ServletException, IOException, SmartUploadException
    ?{
    ??return save(s, 0);
    ?}
    ?
    ?public int save(String s, int i)throws ServletException, IOException, SmartUploadException
    ?{
    ??int j = 0;
    ??if(s == null)
    ???s = m_application.getRealPath("/");
    ??if(s.indexOf("/") != -1)
    ??{
    ???if(s.charAt(s.length() - 1) != '/')
    ????s = s + "/";
    ???} else
    ???if(s.charAt(s.length() - 1) != '\\')
    ????s = s + "\\";
    ???for(int k = 0; k < m_files.getCount(); k++)
    ???if(!m_files.getFile(k).isMissing())
    ???{
    ???m_files.getFile(k).saveAs(s + m_files.getFile(k).getFileName(), i);
    ???j++;
    ??}
    ?
    ??return j;
    ?}
    ?
    ?public int getSize()
    ?{
    ??return m_totalBytes;
    ?}
    ?
    ?public byte getBinaryData(int i)
    ?{
    ??byte byte0;
    ??try
    ??{
    ???byte0 = m_binArray[i];
    ??}
    ??catch(Exception exception)
    ??{
    ???throw new ArrayIndexOutOfBoundsException("Index out of range (1005).");
    ??}
    ??return byte0;
    ?}
    ?
    ?public Files getFiles()
    ?{
    ??return m_files;
    ?}
    ?
    ?public Request getRequest()
    ?{
    ??return m_formRequest;
    ?}
    ?
    ?public void downloadFile(String s) throws ServletException, IOException, SmartUploadException
    ?{
    ??downloadFile(s, null, null);
    ?}
    ?
    ?public void downloadFile(String s, String s1) throws ServletException, IOException, SmartUploadException, SmartUploadException
    ?{
    ??downloadFile(s, s1, null);
    ?}
    ?
    ?public void downloadFile(String s, String s1, String s2)throws ServletException, IOException, SmartUploadException
    ?{
    ??downloadFile(s, s1, s2, 65000);
    ?}
    ?
    ?public void downloadFile(String s, String s1, String s2, int i)throws ServletException, IOException, SmartUploadException
    ?{
    ??if(s == null)
    ???throw new IllegalArgumentException("File '" + s + "' not found (1040).");
    ??if(s.equals(""))
    ???throw new IllegalArgumentException("File '" + s + "' not found (1040).");
    ??if(!isVirtual(s) && m_denyPhysicalPath)
    ???throw new SecurityException("Physical path is denied (1035).");
    ??if(isVirtual(s))
    ???s = m_application.getRealPath(s);
    ??java.io.File file = new java.io.File(s);
    ??FileInputStream fileinputstream = new FileInputStream(file);
    ??long l = file.length();
    ??boolean flag = false;
    ??int k = 0;
    ??byte abyte0[] = new byte[i];
    ??if(s1 == null)
    ???m_response.setContentType("application/x-msdownload");
    ??else
    ??if(s1.length() == 0)
    ???m_response.setContentType("application/x-msdownload");
    ??else
    ???m_response.setContentType(s1);
    ??m_response.setContentLength((int)l);
    ??m_contentDisposition = m_contentDisposition != null ? m_contentDisposition : "attachment;";
    ??if(s2 == null)
    ???m_response.setHeader("Content-Disposition", m_contentDisposition + " filename=" + getFileName(s));
    ??else
    ??if(s2.length() == 0)
    ???m_response.setHeader("Content-Disposition", m_contentDisposition);
    ??else
    ???m_response.setHeader("Content-Disposition", m_contentDisposition + " filename=" + s2);
    ??while((long)k < l)
    ??{
    ???int j = fileinputstream.read(abyte0, 0, i);
    ???k += j;
    ???m_response.getOutputStream().write(abyte0, 0, j);
    ??}
    ??fileinputstream.close();
    ?}
    ?
    ?public void downloadField(ResultSet resultset, String s, String s1, String s2) throws ServletException, IOException, SQLException
    ?{
    ?if(resultset == null)
    ??throw new IllegalArgumentException("The RecordSet cannot be null (1045).");
    ?if(s == null)
    ??throw new IllegalArgumentException("The columnName cannot be null (1050).");
    ?if(s.length() == 0)
    ??throw new IllegalArgumentException("The columnName cannot be empty (1055).");
    ?byte abyte0[] = resultset.getBytes(s);
    ?if(s1 == null)
    ??m_response.setContentType("application/x-msdownload");
    ?else
    ?if(s1.length() == 0)
    ??m_response.setContentType("application/x-msdownload");
    ?else
    ??m_response.setContentType(s1);
    ?m_response.setContentLength(abyte0.length);
    ?if(s2 == null)
    ??m_response.setHeader("Content-Disposition", "attachment;");
    ?else
    ?if(s2.length() == 0)
    ??m_response.setHeader("Content-Disposition", "attachment;");
    ?else
    ??m_response.setHeader("Content-Disposition", "attachment; filename=" + s2);
    ?m_response.getOutputStream().write(abyte0, 0, abyte0.length);
    ?}
    ?
    ?public void fieldToFile(ResultSet resultset, String s, String s1)throws ServletException, IOException, SmartUploadException, SQLException
    ?{
    ??try
    ??{
    ???if(m_application.getRealPath(s1) != null)
    ???s1 = m_application.getRealPath(s1);
    ???InputStream inputstream = resultset.getBinaryStream(s);
    ???FileOutputStream fileoutputstream = new FileOutputStream(s1);
    ???int i;
    ???while((i = inputstream.read()) != -1)
    ????fileoutputstream.write(i);
    ???fileoutputstream.close();
    ??}
    ??catch(Exception exception)
    ??{
    ???throw new SmartUploadException("Unable to save file from the DataBase (1020).");
    ??}
    ?}
    ?
    ?private String getDataFieldValue(String s, String s1)
    ?{
    ??String s2 = new String();
    ??String s3 = new String();
    ??int i = 0;
    ??boolean flag = false;
    ??boolean flag1 = false;
    ??boolean flag2 = false;
    ??s2 = s1 + "=" + '"';
    ??i = s.indexOf(s2);
    ??if(i > 0)
    ??{
    ???int j = i + s2.length();
    ???int k = j;
    ???s2 = "\"";
    ???int l = s.indexOf(s2, j);
    ???if(k > 0 && l > 0)
    ???s3 = s.substring(k, l);
    ??}
    ??return s3;
    ?}
    ?
    ?private String getFileExt(String s)
    ?{
    ??String s1 = new String();
    ??int i = 0;
    ??int j = 0;
    ??if(s == null)
    ???return null;
    ??i = s.lastIndexOf(46) + 1;
    ??j = s.length();
    ??s1 = s.substring(i, j);
    ??if(s.lastIndexOf(46) > 0)
    ???return s1;
    ??else
    ??return "";
    ?}
    ?
    ?private String getContentType(String s)
    ?{
    ??String s1 = new String();
    ??String s2 = new String();
    ??int i = 0;
    ??boolean flag = false;
    ??s1 = "Content-Type:";
    ??i = s.indexOf(s1) + s1.length();
    ??if(i != -1)
    ??{
    ???int j = s.length();
    ???s2 = s.substring(i, j);
    ??}
    ??return s2;
    ?}
    ?
    ?private String getTypeMIME(String s)
    ?{
    ??String s1 = new String();
    ??int i = 0;
    ??i = s.indexOf("/");
    ??if(i != -1)
    ???return s.substring(1, i);
    ??else
    ??return s;
    ?}
    ?
    ?private String getSubTypeMIME(String s)
    ?{
    ??String s1 = new String();
    ??int i = 0;
    ??boolean flag = false;
    ??i = s.indexOf("/") + 1;
    ??if(i != -1)
    ??{
    ???int j = s.length();
    ???return s.substring(i, j);
    ??} else
    ??{
    ???return s;
    ??}
    ?}
    ?
    ?private String getContentDisp(String s)
    ?{
    ??String s1 = new String();
    ??int i = 0;
    ??int j = 0;
    ??i = s.indexOf(":") + 1;
    ??j = s.indexOf(";");
    ??s1 = s.substring(i, j);
    ??return s1;
    ?}
    ?
    ?private void getDataSection()
    ?{
    ??boolean flag = false;
    ??String s = new String();
    ??int i = m_currentIndex;
    ??int j = 0;
    ??int k = m_boundary.length();
    ??m_startData = m_currentIndex;
    ??m_endData = 0;
    ??while(i < m_totalBytes)
    ??if(m_binArray[i] == (byte)m_boundary.charAt(j))
    ??{
    ???if(j == k - 1)
    ???{
    ????m_endData = ((i - k) + 1) - 3;
    ????break;
    ???}
    ???i++;
    ???j++;
    ??} else
    ??{
    ???i++;
    ???j = 0;
    ??}
    ??m_currentIndex = m_endData + k + 3;
    ?}
    ?
    ?private String getDataHeader()
    ?{
    ??int i = m_currentIndex;
    ??int j = 0;
    ??boolean flag = false;
    ??for(boolean flag1 = false; !flag1;)
    ??if(m_binArray[m_currentIndex] == 13 && m_binArray[m_currentIndex + 2] == 13)
    ??{
    ???flag1 = true;
    ???j = m_currentIndex - 1;
    ???m_currentIndex = m_currentIndex + 2;
    ??} else
    ??{
    ???m_currentIndex++;
    ??}
    ??
    ??String s = new String(m_binArray, i, (j - i) + 1);
    ??return s;
    ?}
    ?
    ?private String getFileName(String s)
    ?{
    ??String s1 = new String();
    ??String s2 = new String();
    ??int i = 0;
    ??boolean flag = false;
    ??boolean flag1 = false;
    ??boolean flag2 = false;
    ??i = s.lastIndexOf(47);
    ??if(i != -1)
    ???return s.substring(i + 1, s.length());
    ??i = s.lastIndexOf(92);
    ??if(i != -1)
    ???return s.substring(i + 1, s.length());
    ??else
    ??return s;
    ?}
    ?
    ?public void setDeniedFilesList(String s) throws ServletException, IOException, SQLException
    ?{
    ??String s1 = "";
    ??if(s != null)
    ??{
    ??String s2 = "";
    ??for(int i = 0; i < s.length(); i++)
    ??if(s.charAt(i) == ',')
    ??{
    ???if(!m_deniedFilesList.contains(s2))
    ???m_deniedFilesList.addElement(s2);
    ???s2 = "";
    ??} else
    ??{
    ???s2 = s2 + s.charAt(i);
    ??}
    ??
    ??if(s2 != "")
    ???m_deniedFilesList.addElement(s2);
    ??} else
    ??{
    ???m_deniedFilesList = null;
    ??}
    ?}
    ?
    ?public void setAllowedFilesList(String s)
    ?{
    ??String s1 = "";
    ??if(s != null)
    ??{
    ???String s2 = "";
    ???for(int i = 0; i < s.length(); i++)
    ???if(s.charAt(i) == ',')
    ???{
    ????if(!m_allowedFilesList.contains(s2))
    ????m_allowedFilesList.addElement(s2);
    ????s2 = "";
    ???} else
    ???{
    ????s2 = s2 + s.charAt(i);
    ???}
    ???
    ???if(s2 != "")
    ????m_allowedFilesList.addElement(s2);
    ??} else
    ??{
    ???m_allowedFilesList = null;
    ??}
    ?}
    ?
    ?public void setDenyPhysicalPath(boolean flag)
    ?{
    ??m_denyPhysicalPath = flag;
    ?}
    ?
    ?public void setForcePhysicalPath(boolean flag)
    ?{
    ??m_forcePhysicalPath = flag;
    ?}
    ?
    ?public void setContentDisposition(String s)
    ?{
    ??m_contentDisposition = s;
    ?}
    ?
    ?public void setTotalMaxFileSize(long l)
    ?{
    ??m_totalMaxFileSize = l;
    ?}
    ?
    ?public void setMaxFileSize(long l)
    ?{
    ??m_maxFileSize = l;
    ?}
    ?
    ?protected String getPhysicalPath(String s, int i)throws IOException
    ?{
    ??String s1 = new String();
    ??String s2 = new String();
    ??String s3 = new String();
    ??boolean flag = false;
    ??s3 = System.getProperty("file.separator");
    ??if(s == null)
    ???throw new IllegalArgumentException("There is no specified destination file (1140).");
    ??if(s.equals(""))
    ???throw new IllegalArgumentException("There is no specified destination file (1140).");
    ??if(s.lastIndexOf("\\") >= 0)
    ??{
    ???s1 = s.substring(0, s.lastIndexOf("\\"));
    ???s2 = s.substring(s.lastIndexOf("\\") + 1);
    ??}
    ??if(s.lastIndexOf("/") >= 0)
    ??{
    ???s1 = s.substring(0, s.lastIndexOf("/"));
    ???s2 = s.substring(s.lastIndexOf("/") + 1);
    ??}
    ??s1 = s1.length() != 0 ? s1 : "/";
    ??java.io.File file = new java.io.File(s1);
    ??if(file.exists())
    ???flag = true;
    ??if(i == 0)
    ??{
    ???if(isVirtual(s1))
    ???{
    ????s1 = m_application.getRealPath(s1);
    ????if(s1.endsWith(s3))
    ?????s1 = s1 + s2;
    ????else
    ????s1 = s1 + s3 + s2;
    ?????return s1;
    ???}
    ???if(flag)
    ???{
    ????if(m_denyPhysicalPath)
    ?????throw new IllegalArgumentException("Physical path is denied (1125).");
    ????else
    ?????return s;
    ???} else
    ???{
    ????throw new IllegalArgumentException("This path does not exist (1135).");
    ???}
    ??}
    ??if(i == 1)
    ??{
    ???if(isVirtual(s1))
    ???{
    ????s1 = m_application.getRealPath(s1);
    ???if(s1.endsWith(s3))
    ????s1 = s1 + s2;
    ???else
    ????s1 = s1 + s3 + s2;
    ???return s1;
    ??}
    ??if(flag)
    ???throw new IllegalArgumentException("The path is not a virtual path.");
    ??else
    ???throw new IllegalArgumentException("This path does not exist (1135).");
    ??}
    ??if(i == 2)
    ??{
    ???if(flag)
    ???if(m_denyPhysicalPath)
    ????throw new IllegalArgumentException("Physical path is denied (1125).");
    ???else
    ????return s;
    ???if(isVirtual(s1))
    ????throw new IllegalArgumentException("The path is not a physical path.");
    ???else
    ???throw new IllegalArgumentException("This path does not exist (1135).");
    ??} else
    ??{
    ???return null;
    ??}
    ?}
    ?
    ?public void uploadInFile(String s)throws IOException, SmartUploadException
    ?{
    ??int i = 0;
    ??int j = 0;
    ??boolean flag = false;
    ??if(s == null)
    ???throw new IllegalArgumentException("There is no specified destination file (1025).");
    ??if(s.length() == 0)
    ???throw new IllegalArgumentException("There is no specified destination file (1025).");
    ??if(!isVirtual(s) && m_denyPhysicalPath)
    ???throw new SecurityException("Physical path is denied (1035).");
    ??i = m_request.getContentLength();
    ??m_binArray = new byte[i];
    ??int k;
    ??for(; j < i; j += k)
    ??try
    ??{
    ???k = m_request.getInputStream().read(m_binArray, j, i - j);
    ??}
    ??catch(Exception exception)
    ??{
    ???throw new SmartUploadException("Unable to upload.");
    ??}
    ??
    ??if(isVirtual(s))
    ???s = m_application.getRealPath(s);
    ??try
    ??{
    ???java.io.File file = new java.io.File(s);
    ???FileOutputStream fileoutputstream = new FileOutputStream(file);
    ???fileoutputstream.write(m_binArray);
    ???fileoutputstream.close();
    ??}
    ??catch(Exception exception1)
    ??{
    ???throw new SmartUploadException("The Form cannot be saved in the specified file (1030).");
    ??}
    ?}
    ?
    ?private boolean isVirtual(String s)
    ?{
    ??if(m_application.getRealPath(s) != null)
    ??{
    ???java.io.File file = new java.io.File(m_application.getRealPath(s));
    ???return file.exists();
    ??} else
    ??{
    ???return false;
    ??}
    ?}
    }

    SmartUploadException 類
    /*
    ?* 創(chuàng)建日期 2006-7-29
    ?*
    ?* 更改所生成文件模板為
    ?* 窗口 > 首選項(xiàng) > Java > 代碼生成 > 代碼和注釋
    ?*/
    package com.kinstar.issuing.file;

    /**
    ?* @author gongyifeng
    ?*
    ?* 更改所生成類型注釋的模板為
    ?* 窗口 > 首選項(xiàng) > Java > 代碼生成 > 代碼和注釋
    ?*/
    public class SmartUploadException extends Exception
    {

    ?SmartUploadException(String s)
    ?{
    ??super(s);
    ?}
    }

    上傳的Servlet
    package com.kinstar.issuing.action;

    import java.io.IOException;
    import javax.servlet.Servlet;
    import javax.servlet.ServletException;
    import java.io.*;
    import java.sql.SQLException;
    import java.util.*;
    import java.text.*;
    import javax.servlet.*;
    import javax.servlet.http.*;


    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import com.kinstar.issuing.file.File;
    import com.kinstar.issuing.file.SmartUpload;
    import com.kinstar.issuing.objects.t_user;
    import com.kinstar.issuing.operation.UserOperation;
    import com.kinstar.issuing.program.programService;
    import com.kinstar.issuing.session.SessionGloble;
    import com.kinstar.issuing.util.StringUtil;

    /**
    ?* @version ?1.0
    ?* @author gyf
    ?*/


    public class upload2ProgramAction extends HttpServlet{
    ? private ServletConfig config;
    ? /**
    ? * 初始化Servlet
    ? */
    ? final public void init(ServletConfig config) throws ServletException {
    ??this.config = config;
    ? }
    ? /**
    ? * 處理GET請求
    ? */
    ? public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    ?? doPost(request,response);
    ? }
    ?
    ? /**
    ? * 響應(yīng)POST請求
    ? */
    ? public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {??
    ?? int count=0;
    ?? SmartUpload mySmartUpload = new SmartUpload();
    ?? try {
    ???? // 初始化
    ???? mySmartUpload.initialize(config,request,response);
    ?
    ???? // 上載
    ???? mySmartUpload.upload();
    ???? com.kinstar.issuing.file.File f1 = mySmartUpload.getFiles().getFile(0);
    ?? //? com.kinstar.issuing.file.File f2 = mySmartUpload.getFiles().getFile(1);
    ???? String backPic = f1.getFileName();
    ?? //String name2 = f2.getFileName();
    ???
    ???? long size=0;
    ?????
    ????// 保存上載文件到指定目錄
    ???count=mySmartUpload.save("ads");??
    ???response.sendRedirect("program.jsp?dopass=ture");
    ??
    ??? }?????

    ?????
    ??? catch (Exception e){
    ???? response.sendRedirect("fail.jsp");
    ?? }?
    }

    2.common-fileupload組件
    挺好用的,也能夠上傳大文件,我試過,300M以上的文件上傳本地傳非常快,異地測試也能夠上傳成功.
    首先要下載org.apache.commons.fileupload包和org.apache.commons.io包

    下面是我的servlet
    package com.kinstar.issuing.action;

    import java.io.IOException;
    import javax.servlet.Servlet;
    import javax.servlet.ServletException;
    import java.io.*;
    import java.sql.SQLException;
    import java.util.*;
    import java.text.*;
    import javax.servlet.*;
    import javax.servlet.http.*;
    import java.util.regex.*;


    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.apache.commons.fileupload.DiskFileUpload;
    import org.apache.commons.fileupload.FileItem;
    import org.apache.commons.fileupload.FileUploadException;

    import com.kinstar.issuing.objects.t_user;
    import com.kinstar.issuing.operation.UserOperation;
    import com.kinstar.issuing.program.programService;
    import com.kinstar.issuing.session.SessionGloble;
    import com.kinstar.issuing.util.StringUtil;

    /**
    ?* @version ?1.0
    ?* @author gyf
    ?*/


    public class uploadProgramAction extends HttpServlet{
    ? private static final String CONTENT_TYPE = "text/html; charset=GB2312";
    ?
    ? /**
    ? * 處理GET請求
    ? */
    ? public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    ??? doPost(request,response);
    ? }
    ?
    ? /**
    ? * 響應(yīng)POST請求
    ? */
    ? public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    ?? // 變量定義
    ??? response.setContentType(CONTENT_TYPE);
    ??? HttpSession modifysession=request.getSession();
    ??? SessionGloble logonUser;
    ??? logonUser=(SessionGloble)modifysession.getAttribute("UserInfo");
    ?????? if(logonUser==null){
    ?????? response.sendRedirect("mainindex.jsp");
    ??? }
    ??? t_user userinfo=new t_user();
    ??? UserOperation user=null;
    ??? try {
    ???? user = new UserOperation();
    ??? } catch (Exception e1) {
    ??? // TODO 自動(dòng)生成 catch 塊
    ??? e1.printStackTrace();
    ??? }
    ??? try {
    ???? userinfo=user.getUser(logonUser.getUserId());
    ??? } catch (Exception e2) {
    ??? // TODO 自動(dòng)生成 catch 塊
    ??? e2.printStackTrace();
    ??? }
    ???? //System.out.println("figure="+userinfo.getUserFigure());
    ???? PrintWriter out=response.getWriter();
    ???? DateFormat updf = new SimpleDateFormat("yyyyMMddHHmm");
    ???? String updateTime = updf.format(new Date());
    ???? int isNeed = 0;
    ???? String IsCheck="0";
    ??
    ??? //省農(nóng)行用戶上傳的節(jié)目必需顯示,且審批已經(jīng)合格
    ???? if(userinfo.getUserFigure().equals("1")){
    ???? isNeed = 1;
    ???? IsCheck = "1";
    ???? }
    ???? else{
    ???? isNeed = 0;
    ???? IsCheck = "0";
    ???? }
    ??? int type=0;
    ??? String avaTime="";
    ??? String screen="";
    ??? int fileTime=0;
    ??? int fileTimeReal=0;
    ??? int circle=0;
    ??? String picSwitch="";
    ??? String deleState="1";
    ??? String backPic="";
    ???
    ??? String fieldName="";
    ??? String finalName="";
    ??? String fileNameReal="";
    ??? long size=0;
    ??? String name="";
    ???? try {
    ????DiskFileUpload fu = new DiskFileUpload();
    ????// 設(shè)置允許用戶上傳文件大小,單位:字節(jié),這里設(shè)為2m
    ????fu.setSizeMax(5*1024*1024*1024);
    ????// 設(shè)置最多只允許在內(nèi)存中存儲(chǔ)的數(shù)據(jù),單位:字節(jié)
    ????fu.setSizeThreshold(10*1024*1024);
    ????// 設(shè)置一旦文件大小超過getSizeThreshold()的值時(shí)數(shù)據(jù)存放在硬盤的目錄
    ????fu.setRepositoryPath("C:\\WINDOWS\\Temp\\");
    ????//開始讀取上傳信息
    ????List fileItems = fu.parseRequest(request);
    ????//依次處理每個(gè)上傳的文件
    ????Iterator iter = fileItems.iterator();
    ?
    ??
    ?????? //正則匹配,過濾路徑取文件名
    ????String regExp=".+\\\\(.+)$";
    ?
    ????//過濾掉的文件類型
    ????String[] errorType={".exe",".com",".cgi",".asp"};
    ?????
    ????Pattern p = Pattern.compile(regExp);
    ????StringUtil su = new StringUtil();
    ???? ?
    ????while (iter.hasNext()) {
    ????? FileItem item = (FileItem)iter.next();
    ????
    ?????? if(item.isFormField()) {
    ?????? // 獲得表單域的名字
    ??????? fieldName = item.getFieldName();
    ??????? // 如果表單域的名字是name…
    ??????? if(fieldName.equals("type"))
    ??????? ??? type = Integer.parseInt(item.getString());
    ??????
    ?????? }
    ????? if (!item.isFormField()) {
    ?????? name = item.getName();
    ?????? size = item.getSize();
    ?????? if((name==null||name.equals("")) && size==0)
    ??????? continue;
    ??????? Matcher m = p.matcher(name);
    ??????? boolean result = m.find();
    ??????? if (result){
    ??????? for (int temp=0;temp<errorType.length;temp++){
    ??????? if (m.group(1).endsWith(errorType[temp])){
    ????????throw new IOException(name+": wrong type");
    ??????? }
    ??????? }
    ??????
    ?????? DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
    ??????????????? String date = df.format(new Date());
    ?????? fileNameReal=date+m.group(1);
    ?????? finalName=date+Math.round(Math.random()*10000)+fileNameReal.substring(fileNameReal.indexOf("."));
    ??????? //保存上傳的文件到指定的目錄??
    ??????? //在下文中上傳文件至數(shù)據(jù)庫時(shí),將對這里改寫
    ??????? item.write(new File(getServletContext().getRealPath(".//ads//")+finalName));
    ??????? //out.print(finalName+size);
    ??????? }
    ?????? else
    ?????? {
    ??????throw new IOException("fail to upload");
    ??????
    ?????? }?
    ????? }
    ????? if(item.isFormField()) {
    ?????// 獲得表單域的名字
    ?????fieldName = item.getFieldName();
    ?????if(fieldName.equals("avaTime"))
    ??????avaTime=item.getString();
    ?????if(fieldName.equals("screen"))
    ??????screen=item.getString();
    ?????if(fieldName.equals("fileTime"))
    ??????fileTime = Integer.parseInt(item.getString());
    ?????if(fieldName.equals("fileTimeReal"))
    ??????fileTimeReal = Integer.parseInt(item.getString());
    ?????if(fieldName.equals("circle"))
    ??????circle = Integer.parseInt(item.getString());?
    ?????if(fieldName.equals("switchPic"))
    ??????? picSwitch = item.getString();?
    ??????
    ????? }???
    ?????? }
    ???? }catch (IOException e){
    ???? ??out.println(e);
    ???? }catch (FileUploadException e){
    ???? ??out.println(e);
    ???? } catch (Exception e) {
    ????// TODO 自動(dòng)生成 catch 塊
    ?????e.printStackTrace();
    ???? }
    ???? if(finalName.equals("")){
    ???? ??response.sendRedirect("fail.jsp");
    ???? }
    ???? else{
    ???try {
    ????programService ps = new programService();
    ????ps.insertProgram(userinfo.getUserId(),updateTime,type,finalName,size,isNeed,avaTime,deleState,IsCheck,userinfo.getCity(),backPic,screen,fileTime,fileTimeReal,picSwitch,circle,userinfo.getUserFigure(),new String(fileNameReal.getBytes("GB2312"),"ISO8859-1"));
    ????response.sendRedirect("program.jsp?dopass=true");?
    ???} catch (Exception e3) {
    ???// TODO 自動(dòng)生成 catch 塊
    ????e3.printStackTrace();
    ???}
    ???? }
    ???}
    }
    ?

    posted @ 2006-08-18 16:29 KevinGong 閱讀(1083) | 評論 (1)編輯 收藏

    最近做一個(gè)cts,其中有一個(gè)定時(shí)報(bào)警的需求,網(wǎng)上找了點(diǎn)資料參考!

    如何在Web工程中實(shí)現(xiàn)任務(wù)計(jì)劃調(diào)度

    ???? 好多朋友用過Windows的任務(wù)計(jì)劃,也有不少程序迷自己曾寫過時(shí)鐘報(bào)警、系統(tǒng)自動(dòng)關(guān)機(jī)等趣味程序,可卻很少有朋友在Web工程中實(shí)現(xiàn)過類似功能。今天有空把筆者先前曾在Tomcat上實(shí)現(xiàn)的類似功能,搬出來與大家共享。
    ??? ?早在幾年前,我公司跟某市財(cái)政局合作項(xiàng)目開發(fā),為加強(qiáng)財(cái)政局對所屬單位財(cái)務(wù)狀況的有效監(jiān)管,開發(fā)、實(shí)施了財(cái)政局?jǐn)?shù)據(jù)中心項(xiàng)目。此項(xiàng)目采用B/S加C/S混合結(jié)構(gòu)模式。財(cái)政局Web服務(wù)器上架設(shè)數(shù)據(jù)同步接收裝置,由市屬單位每天下班前把財(cái)務(wù)信息通過HTTP協(xié)議上傳至財(cái)政局中心服務(wù)器,與Web服務(wù)器上的接收裝置對接。財(cái)政局內(nèi)部各部門需要查閱大量財(cái)務(wù)信息,獲取完備的市屬單位當(dāng)前財(cái)務(wù)狀況信息,各部門按職能劃分,需要準(zhǔn)確的獲取各部門各自所關(guān)注的匯總信息,以財(cái)政報(bào)表的形式提供。
    ??? 因財(cái)政數(shù)據(jù)量大,實(shí)時(shí)計(jì)算財(cái)政報(bào)表速度較慢,當(dāng)初就考慮用報(bào)表緩存來減輕服務(wù)器的負(fù)擔(dān),但用緩存需要一個(gè)合理的緩存更新機(jī)制。考慮到各市屬單位每天下班前才把財(cái)務(wù)數(shù)據(jù)上傳,財(cái)政局每天所查看到的財(cái)務(wù)信息其實(shí)并不包括當(dāng)天(除非有某位領(lǐng)導(dǎo)等到所屬單位全部上傳完之后才來查看信息,應(yīng)該已經(jīng)下班了),所以要是能實(shí)現(xiàn)任務(wù)計(jì)劃調(diào)度,在每晚深夜把當(dāng)天及歷史財(cái)務(wù)信息匯總,更新緩存,速度瓶頸不就解決了嗎。
    ??? 當(dāng)時(shí)由于系統(tǒng)核心是基于Web部署的,報(bào)表計(jì)算引擎也相應(yīng)的部署在Tomcat容器上,因此如果想要借用Windows的任務(wù)計(jì)劃來實(shí)現(xiàn)定時(shí)計(jì)算,就需要額外編寫普通桌面應(yīng)用程序接口,稍顯復(fù)雜。于是就琢磨著想在Web上實(shí)現(xiàn),經(jīng)過查閱較多相關(guān)資料,發(fā)現(xiàn)Java定時(shí)器(java.util.Timer)有定時(shí)觸發(fā)計(jì)劃任務(wù)的功能,通過配置定時(shí)器的間隔時(shí)間,在某一間隔時(shí)間段之后會(huì)自動(dòng)有規(guī)律的調(diào)用預(yù)先所安排的計(jì)劃任務(wù)(java.util.TimerTask)。另外,由于我們希望當(dāng)Web工程啟動(dòng)時(shí),定時(shí)器能自動(dòng)開始計(jì)時(shí),在整個(gè)Web工程的生命期里,定時(shí)器能在每晚深夜觸發(fā)一次報(bào)表計(jì)算引擎。因此定時(shí)器的存放位置也值得考查,不能簡單的存在于單個(gè)Servlet或JavaBean中,必須能讓定時(shí)器宿主的存活期為整個(gè)Web工程生命期,在工程啟動(dòng)時(shí)能自動(dòng)加載運(yùn)行。結(jié)合這兩點(diǎn),跟Servlet上下文有關(guān)的偵聽器就最合適不過了,通過在工程的配置文件中加以合理配置,會(huì)在工程啟動(dòng)時(shí)自動(dòng)運(yùn)行,并在整個(gè)工程生命期中處于監(jiān)聽狀態(tài)。
    ??? 下面就Servlet偵聽器結(jié)合Java定時(shí)器來講述整個(gè)實(shí)現(xiàn)過程。要運(yùn)用Servlet偵聽器需要實(shí)現(xiàn)javax.servlet.ServletContextListener接口,同時(shí)實(shí)現(xiàn)它的contextInitialized(ServletContextEvent event)和contextDestroyed(ServletContextEvent event)兩個(gè)接口函數(shù)。考慮定時(shí)器有個(gè)建立和銷毀的過程,看了前面兩個(gè)接口函數(shù),就不容置疑的把建立的過程置入contextInitialized,把銷毀的過程置入contextDestroyed了。
    ??? 我把ServletContextListener的實(shí)現(xiàn)類取名為ContextListener,在其內(nèi)添加一個(gè)定時(shí)器,示例代碼如下所示(為考慮篇幅,僅提供部分代碼供讀者參考):


    ??? private java.util.Timer timer = null;
    ??? public void contextInitialized(ServletContextEvent event) {
    ??????? timer = new java.util.Timer(true);
    ??????? event.getServletContext().log("定時(shí)器已啟動(dòng)");????????
    ???????? timer.schedule(new MyTask(event.getServletContext()), 0, 60*60*1000);
    ??????? event.getServletContext().log("已經(jīng)添加任務(wù)調(diào)度表");
    ??? }
    ??? public void contextDestroyed(ServletContextEvent event) {
    ??????? timer.cancel();
    ??????? event.getServletContext().log("定時(shí)器銷毀");
    ??? }

    ??? 以上代碼中, timer.schedule(new MyTask(event.getServletContext()), 0, 60*60*1000)這一行為定時(shí)器調(diào)度語句,其中MyTask是自定義需要被調(diào)度的執(zhí)行任務(wù)(在我的財(cái)政數(shù)據(jù)中心項(xiàng)目中就是報(bào)表計(jì)算引擎入口),從java.util.TimerTask繼承,下面會(huì)重點(diǎn)講述,第三個(gè)參數(shù)表示每小時(shí)(即60*60*1000毫秒)被觸發(fā)一次,中間參數(shù)0表示無延遲。其它代碼相當(dāng)簡單,不再詳細(xì)說明。
    ?? 下面介紹MyTask的實(shí)現(xiàn),上面的代碼中看到了在構(gòu)造MyTask時(shí),傳入了javax.servlet.ServletContext類型參數(shù),是為記錄Servlet日志方便而傳入,因此需要重載MyTask的構(gòu)造函數(shù)(其父類java.util.TimerTask原構(gòu)造函數(shù)是沒有參數(shù)的)。在timer.schedule()的調(diào)度中,設(shè)置了每小時(shí)調(diào)度一次,因此如果想實(shí)現(xiàn)調(diào)度任務(wù)每24小時(shí)被執(zhí)行一次,還需要判斷一下時(shí)鐘點(diǎn),以常量C_SCHEDULE_HOUR表示(晚上12點(diǎn),也即0點(diǎn))。同時(shí)為防止24小時(shí)執(zhí)行下來,任務(wù)還未執(zhí)行完(當(dāng)然,一般任務(wù)是沒有這么長的),避免第二次又被調(diào)度以引起執(zhí)行沖突,設(shè)置了當(dāng)前是否正在執(zhí)行的狀態(tài)標(biāo)志isRunning。示例代碼如下所示:


    ??? private static final int C_SCHEDULE_HOUR?? = 0;
    ??? private static boolean isRunning = false;
    ???????? private ServletContext context = null;
    ??? public MyTask(ServletContext context) {
    ??????? this.context = context;
    ??? }
    ??? public void run() {
    ??????? Calendar cal = Calendar.getInstance();????????
    ??????? if (!isRunning)? {???????????
    ??????????? if (C_SCHEDULE_HOUR == cal.get(Calendar.HOUR_OF_DAY)) {????????????
    ??????????????????? isRunning = true;????????????????
    ??????????????? context.log("開始執(zhí)行指定任務(wù)");
    ????????????????
    ??????????????? //TODO 添加自定義的詳細(xì)任務(wù),以下只是示例
    ??????????????? int i = 0;
    ??????????????? while (i++ < 10) {
    ??????????????????? context.log("已完成任務(wù)的" + i + "/" + 10);
    ??????????????? }

    ??????????????? isRunning = false;
    ??????????????? context.log("指定任務(wù)執(zhí)行結(jié)束");???????????????
    ??????????? }????????????
    ??????? } else {
    ??????????? context.log("上一次任務(wù)執(zhí)行還未結(jié)束");
    ??????? }
    ??? }

    ??? 上面代碼中“//TODO……”之下四行是真正被調(diào)度執(zhí)行的演示代碼(在我的財(cái)政數(shù)據(jù)中心項(xiàng)目中就是報(bào)表計(jì)算過程),您可以換成自己希望執(zhí)行的語句。
    到這兒,ServletContextListener和MyTask的代碼都已完整了。最后一步就是把ServletContextListener部署到您的Web工程中去,在您工程的web.xml配置文件中加入如下三行:
    ???
    ??????? com.test.ContextListener
    ????
    ??? 當(dāng)然,上面的com.test得換成您自己的包名了。保存web.xml文件后,把工程打包部署到Tomcat中即可。任務(wù)會(huì)在每晚12點(diǎn)至凌晨1點(diǎn)之間被執(zhí)行,上面的代碼會(huì)在Tomcat的日志文件中記錄如下:
    2003-12-05 0:21:39 開始執(zhí)行指定任務(wù)
    2003-12-05 0:21:39 已完成任務(wù)的1/10
    ??? ……
    2003-12-05 0:21:39 已完成任務(wù)的10/10
    2003-12-05 0:21:39 指定任務(wù)執(zhí)行結(jié)束

    posted @ 2006-08-06 21:48 KevinGong 閱讀(285) | 評論 (0)編輯 收藏

    http://www.21tx.com/dev/2004/02/14/19372_3.html
    posted @ 2006-07-27 21:00 KevinGong 閱讀(380) | 評論 (1)編輯 收藏

    最近一個(gè)項(xiàng)目要用到JMF,所以搜集了點(diǎn)資料,以供自己學(xué)習(xí)!
    內(nèi)容表格
    1. 關(guān)于此指南
    2. 一個(gè)簡單的音頻播放器
    3. JMF用戶接口組件
    4. JMF概念
    5. 傳播和接收媒體
    6. 總結(jié)以及資源



    第一節(jié). 關(guān)于此指南

    此指南包含的內(nèi)容?

    Java媒體架構(gòu)(JMF)是一個(gè)令人激動(dòng)的通用的API,它允許Java開發(fā)者用許多不同的方法處理媒體。本指南主要通過使用工作的例子提供一個(gè)JMF的一些主要的特征的概述。閱讀完本指南后,你將會(huì)明白JMF體系結(jié)構(gòu)中的主要播放功能。你同樣能正確的使用JMF,使用現(xiàn)存的例子和可為更多特殊功能擴(kuò)展的源代碼。

    本指南包含著以下主題:
    · 下載和安裝JMF
    · 主要的JMF類以及它們在JMF體系結(jié)構(gòu)中的應(yīng)用
    · 播放本地的媒體文件
    · 為媒體的存取和操作制作以和圖形用戶界面(GUI)
    · 通過網(wǎng)絡(luò)傳播媒體
    · 通過網(wǎng)絡(luò)接收媒體

    幾乎所有的媒體類型的操作和處理都可以通過JMF來實(shí)現(xiàn)。全面的討論JMF所提供的所有特征已經(jīng)超過了本指南的范圍,我們將使用三個(gè)簡單的媒體應(yīng)用程序來學(xué)習(xí)此框架的構(gòu)建模塊。通過這個(gè)方法,本指南將為你未來學(xué)習(xí)和實(shí)施更多特殊的應(yīng)用提供準(zhǔn)備。
    我應(yīng)該使用此指南嗎?

    本指南會(huì)帶你學(xué)習(xí)使用JMF工作的基礎(chǔ)。為完成這些,我們會(huì)創(chuàng)建三個(gè)的獨(dú)立工作的例程序。每個(gè)例子都會(huì)建立前一個(gè)例子的基礎(chǔ)上,顯示JMF功能性的不同方面。
    在本指南中的例子假定你曾經(jīng)使用過并且已經(jīng)熟悉了Java程序語言。除了Java核心和JMF的類之外,我們會(huì)使用一些Java AWT和Swing類(用于創(chuàng)建GUI),也會(huì)有一些Java網(wǎng)絡(luò)類(用于在網(wǎng)絡(luò)中傳輸媒體)。對GUI和網(wǎng)絡(luò)類一些熟悉有助于你更快的明白觀點(diǎn)和這里的例子,但并非是閱讀本指南必須的。

    我們將學(xué)習(xí)的例程序如下
    · 一個(gè)簡單的音頻播放器(JMF的HelloWorld應(yīng)用):這個(gè)字符界面的播放器通過在命令行中簡單的輸入媒體文件的名字就可以播放大多數(shù)的音頻類型。此音頻播放器的演示大體上顯示了JMF的特有的類。
    · 一個(gè)圖形界面的媒體播放器:我們將使用JMF內(nèi)置的接口組件來建立圖形界面,所以在此練習(xí)中必須有一些圖形界面的編程經(jīng)驗(yàn)。這個(gè)媒體閱覽器演示使用了一些Java AWT和Swing類來為用戶顯示圖形組件。
    · 一個(gè)媒體廣播應(yīng)用:此應(yīng)用程序允許一個(gè)本地媒體文件通過網(wǎng)絡(luò)傳播。此程序能靈活的使媒體只傳輸?shù)街付ǖ木W(wǎng)絡(luò)節(jié)點(diǎn),或者傳輸?shù)揭粋€(gè)子網(wǎng)絡(luò)中的所有節(jié)點(diǎn)。此演示使用了一些Java的網(wǎng)絡(luò)APIs來在網(wǎng)絡(luò)中傳輸媒體。
    作為第三個(gè)練習(xí)的一部分,我們將修改圖形界面的播放器,讓其能接收并且播放媒體。
    跳至23頁觀看Resources,文章,指南,和其他參考書目的列表,這會(huì)幫助你學(xué)習(xí)到更到關(guān)于此指南包括的主題。

    安裝需求
    要運(yùn)行此指南中的例程序,你需要如下的工具和組件:
    ·??Java 2 平臺(tái),標(biāo)準(zhǔn)版,編譯和運(yùn)行演示程序
    ·??Java媒體框架,版本2.1.1a或者更高
    · 一塊已經(jīng)安裝并且配置號的適當(dāng)?shù)穆暱?br />· 一臺(tái)或者多臺(tái)測試機(jī)器
    · 演示的源代碼文件在mediaplayer.jar中
    最后的一個(gè)演示應(yīng)用顯示了JMF在網(wǎng)絡(luò)中的應(yīng)用。如果需要,此演示能運(yùn)行在一個(gè)獨(dú)立的機(jī)器上,使用此機(jī)器即是傳輸方也是接收方。可是要觀察到在網(wǎng)絡(luò)中使用JMF的所有功能,你仍然需要至少兩臺(tái)聯(lián)網(wǎng)的機(jī)器。
    在23頁中的Resources可下載Java 2平臺(tái),完整的源代碼文件,以及其他一些完成本指南所需要的工具。

    下載安裝文件
    將JMF安裝到你的計(jì)算機(jī)中的第一步是在JMF的主頁中下載安裝文件,它同樣包括了JMF源代碼和API文檔的鏈接。23頁的Resources中有下載JMF的鏈接。
    目前,JMF有Windows, Solaris, Linux等版本,以及可運(yùn)行在任何裝有虛擬機(jī)的計(jì)算機(jī)上一個(gè)純Java版本。為了增加性能,你需要下載一個(gè)與你操作系統(tǒng)所適應(yīng)的版本。任何在一個(gè)操作系統(tǒng)JMF版本下書寫和編譯的代碼都可以方便的移植到另外的操作系統(tǒng)上。例如,如果你下載了一個(gè)Solaris版本的JMF并且編譯了一個(gè)類,這些類就可以在Linux上使用,不會(huì)有任何問題。
    作為選擇,你可以選擇下載純Java版本,或者跨平臺(tái)版本的JMF。這些版本沒有使用操作系統(tǒng)特有的庫文件。如果沒有合適的JMF版本適合的操作系統(tǒng),那么跨平臺(tái)版本就是一個(gè)不錯(cuò)的選擇。

    安裝JMF
    下載完JMF安裝程序后,雙擊安裝程序的圖標(biāo)。
    大部分安裝程序都會(huì)有個(gè)選項(xiàng),安裝本地庫到系統(tǒng)目錄中;例如,Windows版本安裝程序會(huì)有一個(gè)選項(xiàng)“Move DLLs to Windows/System directory.”。最好將此選項(xiàng)選中,因?yàn)樗艽_保這些操作系統(tǒng)的庫文件能正確的安裝
    在安裝的過程中,你還需要選擇項(xiàng)目來更新系統(tǒng)的CLASSPATH和PATH變量。如果這些選項(xiàng)被關(guān)閉,那么在你編譯和運(yùn)行本指南的例程序的時(shí)候就需要在classpath中引入JMF的jar文件。

    關(guān)于作者
    Eric Olson在Retek Inc工作的軟件工程師。它在Java平臺(tái)上有四年的工作經(jīng)驗(yàn),并且在不同的基于Java的技術(shù)上富有經(jīng)驗(yàn),包括JMF, Jini, Jiro, JSP, servlets, and EJBs。Eric畢業(yè)于St. Paul, MN的St. Thomas大學(xué),獲得計(jì)算機(jī)科學(xué)的學(xué)位。他在IBM的SanFrancisco項(xiàng)目組工作,負(fù)責(zé)WebSphere商業(yè)組件。他同時(shí)再為Imation Corp.工作,負(fù)責(zé)存儲(chǔ)應(yīng)用。現(xiàn)在,他正在開發(fā)零售行業(yè)的基于web的軟件解決方案。再業(yè)余的時(shí)間,Eric和Paul
    Monday在Stereo Beacon上合作—一個(gè)分布式的點(diǎn)對點(diǎn)的基于JMF的媒體播放器。聯(lián)系
    Eric zpalffy@yahoo.com.

    第二節(jié). 一個(gè)簡單的音頻播放器
    瀏覽
    在本節(jié)中,我們將進(jìn)行創(chuàng)建一個(gè)簡單的音頻播放器的第一個(gè)練習(xí)。本例將介紹Manager類和Player接口,中兩個(gè)都是建立大多數(shù)基于JMF應(yīng)用的重要部分。
    本例的功能目標(biāo)是在字符界面下播放本地的音頻文件。我們將學(xué)習(xí)此源代碼,并了解每一行所做的任務(wù)。完成本節(jié)后,你將會(huì)有一個(gè)基于JMF的可播放包括MP3, WAV, AU等多種音頻文件的演示程序。
    在本練習(xí)后的源代碼分類種可查詢文件SimpleAudioPlayer.java。

    引入必要的類
    SimpleAudioPlayer類中包括了一些調(diào)用,在其前幾行中需要引入所有必要的類:
    import javax.media.*;
    import java.io.File;
    import java.io.IOException;
    import java.net.URL;
    import java.net.MalformedURLException;

    The javax.media包是由JMF定義的多個(gè)包之一。javax.media是一個(gè)核心包,包括了定義Manager類和Player接口等。本節(jié)中,我們主要學(xué)習(xí)Manager類和Player接口,其余的javax.media類放在后面的章節(jié)中。
    除了引入javax.media聲明外,以上的代碼片斷引入了一些創(chuàng)建媒體播放器的輸入的聲明。

    Player接口
    在下面的代碼片斷中,創(chuàng)建一個(gè)公共類SimpleAudioPlayer并舉例定義一個(gè)Player變量:

    public class SimpleAudioPlayer {
    private Player audioPlayer = null;


    術(shù)語Player聽起來由點(diǎn)熟悉,因?yàn)樗墙⒃谖覀児玫囊纛l或者視頻播放器的基礎(chǔ)上的。事實(shí)上,這個(gè)接口的例子就像是當(dāng)作它們的真實(shí)的副本。Players揭示了一個(gè)實(shí)體上的媒體播放器(如立體音箱系統(tǒng)或者VCR)涉及到功能上的方法。例如,一個(gè)JMF媒體播放器可以開始和結(jié)束一個(gè)媒體流。在本節(jié)種,我們將使用Player的開始和結(jié)束功能。

    在一個(gè)文件上創(chuàng)建一個(gè)Player
    使用JMF獲得一個(gè)特定媒體文件的Player實(shí)例非常簡單。Manager類在JMF中如同一個(gè)工廠制作許多的特殊接口類型,包括Player接口。因此,Manager類的責(zé)任就是創(chuàng)建Player實(shí)例,如下例:

    public SimpleAudioPlayer(URL url) throws IOException,
    NoPlayerException,
    CannotRealizeException {
    audioPlayer = Manager.createRealizedPlayer(url);
    }
    public SimpleAudioPlayer(File file) throws IOException,
    NoPlayerException,
    CannotRealizeException {
    this(file.toURL());
    }



    如果你看完本節(jié)的代碼,你可以注意到Manager類包含了創(chuàng)建一個(gè)Player實(shí)例的其他方法。我們會(huì)研究其中的一些,如在后面的章節(jié)中的DataSource或者M(jìn)ediaLocator的實(shí)例化。

    Player的狀態(tài)
    JMF定義了大量的一個(gè)Player實(shí)例可能存在的不同狀態(tài)。如下:
    · Prefetched
    · Prefetching
    · Realized
    · Realizing
    · Started
    · Unrealized

    使用這些狀態(tài)
    因?yàn)槭褂妹襟w常常是資源非常密集的,由JMF對象揭示的許多方法都是不閉塞的,允許一系列事件監(jiān)聽的狀態(tài)改變的異步通知。例如,一個(gè)Player在它可以啟動(dòng)之前,必須經(jīng)過Prefetched和Realized狀態(tài)。由于這些狀態(tài)的改變都需要一些時(shí)間來完成,JMF媒體應(yīng)用可以分配一個(gè)線程來初始化創(chuàng)建Player實(shí)例,然后再繼續(xù)其他的操作。當(dāng)Player準(zhǔn)備就緒的時(shí)候,它會(huì)通知應(yīng)用程序其狀態(tài)已經(jīng)改變。

    在一個(gè)如同我們的這樣簡單的程序中,多功能性的類型并不是很重要。處于這個(gè)原因,Manager類也提供了一些創(chuàng)建Realized player的有用方法。調(diào)用一個(gè)createRealizedPlayer()方法來阻塞調(diào)用線程,直到player達(dá)到Realized狀態(tài)。為了調(diào)用一個(gè)無阻塞的創(chuàng)建player的方法,我們在Manager類中使用了一個(gè)createPlayer()方法。下面的一行代碼中創(chuàng)建了一個(gè)我們需要在例程序中使用的

    Realized player:
    audioPlayer = Manager.createRealizedPlayer(url);



    啟動(dòng)和停止Player
    設(shè)定一個(gè)Player實(shí)例的啟動(dòng)或是停止就如同調(diào)用Player的一個(gè)簡單的認(rèn)證方法,如下所示:

    public void play() {
    audioPlayer.start();
    }
    public void stop() {
    audioPlayer.stop();
    audioPlayer.close();
    }


    調(diào)用SimpleAudioPlayer類中的play()方法來實(shí)現(xiàn)調(diào)用Player實(shí)例的start()方法。調(diào)用此方法后,你能聽到本地的喇叭的聲音文件。同樣的,stop()方法使player停止并且關(guān)閉掉Player對象。

    對于讀取和或者播放本地媒體文件來說,關(guān)閉Player實(shí)例釋放所有資源是一個(gè)有用的方法。因?yàn)檫@是一個(gè)簡單的例子,關(guān)閉Player是終止一個(gè)會(huì)話可接受的方法。但是在實(shí)際的應(yīng)用中,你需要小心的確認(rèn)在除掉Player之前必須要關(guān)閉掉。一但你已經(jīng)關(guān)閉掉player,在再次播放一個(gè)媒體之前你必須要?jiǎng)?chuàng)建一個(gè)新的Player實(shí)例(等待它的狀態(tài)改變)。

    建立一個(gè)SimpleAudioPlayer

    最后,這個(gè)媒體播放應(yīng)用程序要包含一個(gè)可以從命令提示行中輸入命令而調(diào)用的main()方法。在此main()方法中,我們將調(diào)用創(chuàng)建SimpleAudioPlayer的方法:

    File audioFile = new File(args[0]);
    SimpleAudioPlayer player = new SimpleAudioPlayer(audioFile);



    在播放音頻文件之前的唯一的一些事情就是調(diào)用已經(jīng)創(chuàng)建的音頻player的方法play(),如下所示:

    player.play();



    要停止和清除掉音頻player,在main()方法中也應(yīng)該有如下調(diào)用:

    player.stop();



    編譯和運(yùn)行SimpleAudioPlayer
    通過在命令提示行輸入javac SimpleAudioPlayer.java來編譯例程序。所創(chuàng)建的文件SimpleAudioPlayer.class在當(dāng)前工作目錄中。
    然后在命令提示行中鍵入如下命令來運(yùn)行例程序:

    java SimpleAudioPlayer audioFile


    將audioFile替換成你本地機(jī)器上的音頻文件。所有的相對文件名都試相對于當(dāng)前的工作目錄。你會(huì)看到一些當(dāng)前正在播放文件的標(biāo)志信息。要終止播放,按下回車鍵。
    如果編譯失敗,確認(rèn)JMF的jar文件已經(jīng)正確的包含在CLASSPATH環(huán)境變量中。


    第三節(jié). JMF用戶界面組件
    播放視頻
    在前一節(jié)中,我們學(xué)習(xí)了建立一個(gè)通過字符界面播放音頻文件的應(yīng)用程序。JMF中一個(gè)最重要的特點(diǎn)就是你不需要為了配置媒體播放器而去了解媒體文件的格式;一切都內(nèi)置了。舉一個(gè)例子,再我們前面的例子中,需要使用MP3格式的時(shí)候,我們不需要讓應(yīng)用程序?yàn)橐粋€(gè)MP3文件建立一個(gè)特殊的Player。
    如同你將會(huì)再本節(jié)所見到的,對于視頻文件的操作同樣有效。JMF有所有媒體文件類型接口的詳細(xì)資料。
    處理視頻媒體與音頻最大的不同就是,我們必須建立一個(gè)能播放視頻的顯示屏幕。幸運(yùn)的是,JMF能處理許多的這些資料。如同再上例一樣我們會(huì)建立一個(gè)Player對象,并且使用很多的可視組件來直接從JMF對象中創(chuàng)建我們的可視的媒體瀏覽器。
    本節(jié)中,我們將學(xué)習(xí)兩個(gè)例程序。In this section, we'll walk through the second example application. 請?jiān)俸竺娴木毩?xí)的源代碼分布中查閱MediaPlayerFrame.java。

    關(guān)于例子
    在本節(jié)中,我們將創(chuàng)建一個(gè)能顯示和運(yùn)行本地音頻和視頻媒體的應(yīng)用程序。作為練習(xí)的一部分,我們將研究JMF內(nèi)置的一些GUI組件。熟悉AWT和Swing將有助于你理解本例,但這并不是必須的。除非需要直接涉及到JMF的GUI組件,或者我們是不會(huì)詳細(xì)介紹源代碼的。你可以在源代碼的注釋中找到這里未涉及的詳細(xì)說明。
    本例中我們使用的許多概念,類和方法都和第一個(gè)例子的類似。建立Player的基本操作大都一樣。最大的不同就是我們需要對Player對象專研更深一點(diǎn),特別當(dāng)需要從Player獲取媒體信息的時(shí)候。

    如何開始
    視頻播放器例子被設(shè)計(jì)得如同音頻播放例子一樣通過命令行來運(yùn)行,但是本例需要建立在GUI基礎(chǔ)上。如同在上節(jié)一樣,我們先通過媒體文件名調(diào)用應(yīng)用。然后,應(yīng)用程序顯示一個(gè)帶有可操作媒體組件的窗體。
    在MediaPlayerFrame開始的一行中我們定義了類并擴(kuò)展自,javax.swing.Jframe類。這就是使媒體播放器如同一個(gè)在桌面上的單獨(dú)窗體的方法。任何客戶機(jī)程序創(chuàng)建了本媒體播放對象后都可以通過調(diào)用Jframe類中定義的show()方法來顯示。
    下面是一個(gè)MediaPlayerFrame正在播放MPEG電影的屏幕截圖:

    獲取GUI組件
    Player界面有一些方法來獲取已選擇可視組件的涉及。在MediaPlayerFrame中,我們使用如下組件:
    · player.getVisualComponent()是一個(gè)播放所有視頻媒體的可視組件。
    · player.getControlPanelComponent() 是一個(gè)操作時(shí)間軸的可視組件(包括開始,停止,回放),也包含了一些媒體流的有用信息。
    · player.getGainControl().getControlComponent() 是操作音量(增加)的可視組件。getGainControl()方法返回一個(gè)GainControl實(shí)例,可用于改變節(jié)目的增加等級。

    使用可視化組件
    上面的界面方法都返回一個(gè)java.awt.Component類的實(shí)例。沒個(gè)實(shí)例都視可加載到我們窗體上的可視組件。這些組件都與Player有直接的聯(lián)系,所以在這些組件上的所有可視元素的處理都會(huì)產(chǎn)生Player播放媒體后相應(yīng)的變化。
    在我們將這些組件加入到我們的窗體的之前,必須要保證它們不為空。因?yàn)椴⒉皇撬械拿襟w播放器包括每一種可視組件,我們只需添加相關(guān)播放器類型的組件。比如,一般來說一個(gè)音頻播放器沒有可視組件,所以getVisualComponent()就要返回空。你不會(huì)想在音頻播放器窗體上添加可視組件的。

    獲得媒體的特殊控制
    一個(gè)Player實(shí)例也可以通過getControl()和getControls()方法來暴露其控制,getControls()返回一個(gè)控制對象集,而getControl()返回一個(gè)控制。不同的播放器類型可選擇為特殊的操作來暴露控制集去指定的媒體類型,或者用于獲取該媒體的傳輸機(jī)制。如果你在寫一個(gè)只支持某些媒體類型的播放器,你需要依靠某些在Player實(shí)例中可用Control對象。
    由于我們的播放器是非常抽象的,被設(shè)計(jì)于播放多種不同媒體類型,我們簡單的為用戶暴露所有的Control對象。如果找到任何擴(kuò)展的控制集,我們就可使用getControlComponent()方法來增加相應(yīng)的可視控件到標(biāo)簽面板上。通過這個(gè)辦法,用戶就可以觀察播放器上的所有組件。以下代碼片斷將所有的控制對象暴露給用戶:

    Control[] controls = player.getControls();
    for (int i = 0; i < controls.length; i++) {
    if (controls[i].getControlComponent() != null) {
    tabPane.add(controls[i].getControlComponent());
    }
    }


    為了使一個(gè)真實(shí)的應(yīng)用程序能用Control實(shí)例做一些有用的事(除了能顯示可視組件之外),應(yīng)用程序需要知道該Control的特殊類型,并分配它。此后,應(yīng)用程序就可使用這些control來控制媒體節(jié)目了。例如,如果你知道你經(jīng)常使用的媒體暴露javax.media.control.QualityControl類型的Control,你能使用QualityControl界面,之后在QualityControl界面上通過調(diào)用各種方法來改變性質(zhì)設(shè)定。

    使用一個(gè)MediaLocator
    在我們新的基于GUI的媒體播放器和我們的第一個(gè)簡單播放器之間最大的不同就是,我們使用一個(gè)MediaLocator對象而不是URL來創(chuàng)建Player實(shí)例,如下所示:

    public void setMediaLocator(MediaLocator locator) throws IOException,
    NoPlayerException, CannotRealizeException {
    setPlayer(Manager.createRealizedPlayer(locator));
    }


    我們將在稍后的章節(jié)中討論這個(gè)變化的原因。目前,在網(wǎng)絡(luò)上資源站點(diǎn)上,關(guān)于MediaLocator對象和URL的描述被認(rèn)為是非常相似的。事實(shí)上,你可以從一個(gè)URL創(chuàng)建一個(gè)MediaLocator,也可以從MediaLocator獲取到URL。我們的新媒體播放器一個(gè)URL中創(chuàng)建一個(gè)MediaLocator,并使用該MediaLocator通過文件創(chuàng)建了一個(gè)Player。

    編譯和運(yùn)行MediaPlayerFrame
    通過在命令提示行輸入javac MediaPlayerFrame.java來編譯例程序。在工作目錄下將創(chuàng)建一個(gè)名為MediaPlayerFrame.class的文件。
    在命令提示行中鍵入如下來運(yùn)行例程序:

    java MediaPlayerFrame mediaFile


    你需要用你本機(jī)上的一個(gè)媒體文件來替換掉mediaFile(音頻或者視頻文件都可以)。所有的相對文件名都是相對于當(dāng)前工作目錄。你會(huì)看見一個(gè)顯示控制媒體文件的GUI控制集的窗口。欲了解JMF支持的音頻和視頻文件列表,在23頁的資源。
    如果初始編譯時(shí)失敗,請確認(rèn)JMF的jar文件已經(jīng)包含在當(dāng)前的CLASSPATH環(huán)境變量中。

    MediaPlayerFrame在行動(dòng)
    在本節(jié)前你看見的一個(gè)視頻播放器正在播放MPEG視頻文件的屏幕截圖。下面的屏幕截圖顯示了一個(gè)音頻播放器正在播放一個(gè)MP3文件:
    要更多的學(xué)習(xí)本練習(xí)中的例子,查看完成的MediaPlayerFrame源代碼。

    第四節(jié). JMF概念
    JMF體系結(jié)構(gòu)
    你曾見過了使用JMF播放本地媒體文件是多么的容易,現(xiàn)在我們將后退一步,來看看一幅是如何通過JMF創(chuàng)建了如此成熟的基于媒體的應(yīng)用程序的大的畫面,是如何通過JMF創(chuàng)建了如此成熟的基于媒體的應(yīng)用程序。全面的了解JMF體系結(jié)構(gòu)是沒有意義的,本節(jié)將給你一個(gè)大體的概念,關(guān)于高級的JMF組件是如何組合起來創(chuàng)建想得到的東西。
    JMF的組件結(jié)構(gòu)非常的靈活,它的組件一般可以分成三個(gè)部分:
    · Input描述某種被用于在進(jìn)程休息的時(shí)候作為一個(gè)輸入的媒體。
    · process執(zhí)行某些輸入上的活動(dòng)。一個(gè)過程有一個(gè)明確的輸入和輸出。大量的過程可用, 能被用于一個(gè)輸入或者一批輸入。這些過程能被聯(lián)系起來,一個(gè)過程的輸出被用于另外一個(gè)過程的輸入。在這種風(fēng)格中,大量的過程可能被應(yīng)用于一個(gè)輸入。(這段期間是可選擇的——我們開始的兩個(gè)例子沒有包含真正的數(shù)據(jù)過程,只有一個(gè)來自文件的輸入和一個(gè)通過Player的輸出。)
    · Output 描述了媒體的某些目的地。

    從這些描述中,你可以想象到JMF組件體系結(jié)構(gòu)聽起來就好像在一個(gè)典型的立體聲系統(tǒng)或者VCR之后。很容易設(shè)想到,使用JMF就如同打開電視或者在立體聲音箱系統(tǒng)下調(diào)節(jié)聲音的風(fēng)格。例如,錄制喜愛的電視節(jié)目的簡單的動(dòng)作能在這些組件的基礎(chǔ)中:
    · Input 是電視廣播流,在同一個(gè)頻道運(yùn)輸音頻和視頻。
    · Process 是一個(gè)記錄設(shè)備(就是,一個(gè)VCR或者許多的數(shù)字設(shè)備)轉(zhuǎn)換模擬或者數(shù)字音頻視頻廣播流成適合復(fù)制到磁帶或其他媒體上的格式。
    · Output 是記錄已格式化軌跡(音頻和視頻)到某些類型的媒體上。

    JMF資料處理模式
    以下圖片說明了JMF數(shù)據(jù)處理模塊并對每個(gè)類型給出了例子:
    使用此模式,很容易明白我們前面的兩個(gè)例子,從文件中輸入音頻和視頻并輸出到本地計(jì)算機(jī)上。在后面的章節(jié)中,我們也會(huì)談?wù)撘恍┩ㄟ^傳播和接收音頻媒體的JMF網(wǎng)絡(luò)功能。

    處理模型例子
    將JMF的輸入,處理和輸出模式聯(lián)系起來,我們能開始想象許多基于媒體的操作都可能通過JMF完成。一個(gè)例子,轉(zhuǎn)換一種媒體類型為其他類型并將其輸出存儲(chǔ)到一個(gè)新的文件。舉一個(gè)例子,我們想要在不損壞原始文件的前提下轉(zhuǎn)化一個(gè)WAV格式的音頻文件為MP3格式。以下的過程模式插圖,就是我們將開始執(zhí)行轉(zhuǎn)換的步驟:
    本例的輸入是一個(gè)WAV文件。它被一個(gè)媒體格式轉(zhuǎn)換工具加工,并輸出到一個(gè)新的文件。現(xiàn)在,讓我們看看JMF API中的這個(gè)模式的每一步。我們使用輸入,處理和輸出模式作為概念上的路標(biāo)。

    JMF輸入
    再JMF中,一般由一個(gè)MediaLocator對象來描述一個(gè)輸入。如先前規(guī)定的,
    MediaLocator的外觀和行為都非常象一個(gè)URL,這樣它可以唯一確定網(wǎng)絡(luò)上的一個(gè)資源。事實(shí)上,使用一個(gè)URL來創(chuàng)建一個(gè)MediaLocator是完全可能的;我們在前面的兩個(gè)例子中就是這樣做的。
    為了我們的媒體轉(zhuǎn)換例子,我們需要建立一個(gè)MediaLocator來描述最初的WAV文件。如同我們將在后面的章節(jié)中見到的,一個(gè)MediaLocator也可以用于描述一個(gè)跨越網(wǎng)絡(luò)中媒體流。在這個(gè)案例中,MediaLocator會(huì)描述傳播的URL――很像一個(gè)被URL指定的在Web上的資源,用于取代指定一個(gè)本地文件系統(tǒng)的文件來建立MediaLocator。

    一個(gè)MediaLocator和一個(gè)URL之間的不同
    要成功的建立一個(gè)URL對象,需要適當(dāng)?shù)膉ava.net.URLStreamHandler安裝于系統(tǒng)中。這個(gè)流處理的用途是能夠處理被URL描述的流類型。一個(gè)MediaLocator對象并沒有這個(gè)需要。例如,我們的下個(gè)應(yīng)用程序?qū)⑹褂脤?shí)時(shí)傳輸協(xié)議(RTP)在網(wǎng)絡(luò)上傳輸音頻。由于多數(shù)的系統(tǒng)都未為RTP協(xié)議安裝一個(gè)URLStreamHandler,所以創(chuàng)建一個(gè)URL對象會(huì)失敗。在這個(gè)應(yīng)用中,只有MediaLocator對象會(huì)成功。
    要理解更多關(guān)于URL對象以及創(chuàng)建和注冊一個(gè)URLStreamHandler的信息,查閱JDK幫助文檔(查看23頁資源)。

    JMF處理機(jī)
    當(dāng)我們使用JMF的時(shí)候,應(yīng)用程序的處理機(jī)組件被Processor接口實(shí)例描述。你需要已有些熟悉Processor,它擴(kuò)展至Player接口。由于Processor繼承直Player接口,它同樣也從Player繼承所有可用屬性。另外,Processor增加了兩個(gè)屬性:Configuring和Configured。這些擴(kuò)展的屬性(和與之關(guān)聯(lián)的方法)用于Processor從輸入流收集信息時(shí)的通信。
    在我們的最后的例程序中,我們將建立一個(gè)Processor用于將MP3編碼格式的音頻轉(zhuǎn)換成適合在網(wǎng)絡(luò)上傳播的格式。在稍后的板塊中我們會(huì)討論創(chuàng)建一個(gè)簡單的Processor的步驟。

    JMF輸出
    有少許的方法用于描述JMF中處理模式的輸出狀態(tài)。最簡單的(并且我們將在最后一個(gè)例子中使用的)是javax.media.DataSink接口。一個(gè)DataSink讀取媒體內(nèi)容并且將其傳送到一些目的地。本節(jié)中最開始的音頻格式轉(zhuǎn)換過程中,MP3(輸出)文件將被DataSink描述。在我們最后一個(gè)例子中,我們將使用一個(gè)DataSink在實(shí)際上完成網(wǎng)絡(luò)中傳播音頻媒體的工作。一個(gè)DataSink是在Manager類中,由指定一個(gè)DataSource(輸入到DataSink)和一個(gè)MediaLocator(輸出到DataSink)完成的。
    一個(gè)DataSource實(shí)例描述可用于Players,Processors和DataSinks的輸入數(shù)據(jù)。一個(gè)處理機(jī)的輸出也被描述成一個(gè)DataSource對象。
    這就是為什么處理器能彼此聯(lián)系起來,在同一媒體數(shù)據(jù)中完成多種操作。這也是來自Processor的輸出能作為輸入被Player或者DataSink使用的原因(它可將媒體傳遞到輸出目的地)。
    一個(gè)DataSink的最后目的文件由一個(gè)MediaLocator對象說明。如同前面一樣,MediaLocator描述一個(gè)網(wǎng)絡(luò)資源;這就是媒體流將被傳遞的地方。

    第五節(jié).傳播接收媒體
    JMF和實(shí)時(shí)傳輸協(xié)議(RTP)
    許多的友善網(wǎng)絡(luò)的特征直接建立在JMF中,這些使為客戶端程序通過網(wǎng)絡(luò)傳輸和接收媒體非常容易。當(dāng)在一個(gè)網(wǎng)絡(luò)上的一個(gè)用戶想要接收任何種類的媒體流的時(shí)候,它不需要在觀看媒體前等待全部的廣播下載到機(jī)器上;用戶可以實(shí)時(shí)的觀看廣播。在流媒體中些提出了這個(gè)概念。通過流媒體,一個(gè)網(wǎng)絡(luò)客戶端能接收到其他機(jī)器上廣播的音頻,甚至獲取正在發(fā)生的實(shí)況視頻廣播。
    在IETF RFC 1889中定義了實(shí)時(shí)傳輸協(xié)議(RTP)。發(fā)展在快速和可靠的狀態(tài)下通過網(wǎng)絡(luò)傳輸時(shí)間極其敏感的數(shù)據(jù),RTP在JMF中用于提供給用戶向其他網(wǎng)絡(luò)節(jié)點(diǎn)中傳輸媒體流的方法。
    在本節(jié)中,我們將學(xué)習(xí)我們的最后一個(gè)例程序。這里,你將學(xué)習(xí)到如何傳輸一個(gè)存儲(chǔ)在一臺(tái)機(jī)器上的MP3文件到另外的在同一個(gè)網(wǎng)絡(luò)的機(jī)器上去。實(shí)際的MP3源文件并不從主計(jì)算機(jī)上移除,它也不使復(fù)制到其他機(jī)器上去;事實(shí)上它將會(huì)轉(zhuǎn)換成能使用RTP傳輸?shù)奈募袷讲⑼ㄟ^網(wǎng)絡(luò)發(fā)送。一旦被一個(gè)客戶端接收到,源文件(現(xiàn)在是RTP信息包的形式)可以再次傳輸,這一次是在接收機(jī)器上可播放的一種格式。
    在MediaTransmitter.java文件中源代碼查看學(xué)習(xí)以下練習(xí)。

    設(shè)置處理模式
    我們可以在前面的章節(jié)中定義的處理模式的基礎(chǔ)下來討論我們的最終的例子。在傳輸機(jī)器上,處理模式看起來像這樣:
    事實(shí)上,MediaTransmitter對象源代碼包括了以下三行:

    private MediaLocator mediaLocator = null;
    private DataSink dataSink = null;
    private Processor mediaProcessor = null;



    這三個(gè)實(shí)例變量可以直接映射到前面的處理模式圖表,如下:
    ·??mediaProcessor變量是我們的處理器;它將負(fù)責(zé)轉(zhuǎn)換音頻文件從MP3文件模式到一個(gè)適合通過RTP協(xié)議傳輸?shù)母袷健?br />·??dataSink變量是我們的輸出塊。
    · 當(dāng)我們建立DataSink時(shí)我們需要指定一個(gè)MediaLocator,它是DataSink的目的文件。

    當(dāng)我們通過運(yùn)行DataSink我們的處理過的媒體,它將傳輸?shù)轿覀冊贛ediaLocator中指定的地點(diǎn)。

    RTP MediaLocator
    在前面的兩個(gè)練習(xí)中,我們通過從文件中獲得的一個(gè)URL建立了MediaLocator實(shí)例。 在本練習(xí)中,我們必須建立一個(gè)MediaLocator來描述網(wǎng)絡(luò)上媒體傳播輸出流;換句話說,我們必須創(chuàng)建一個(gè)能我們的音頻傳播的目的地的MediaLocator。一個(gè)RTP MediaLocator符合如下規(guī)則,看起來就像一個(gè)典型的URL:

    rtp://address:port/content-type



    讓我們看看上面URL規(guī)范的每一段:
    · address 是將傳輸?shù)拿襟w的地址。以單播的模式傳輸(一個(gè)專用IP地址),地址將會(huì)是有意接收的機(jī)器的IP地址。以廣播的模式傳播(到子網(wǎng)中的所有機(jī)器),地址將會(huì)是以255作為最后的一塊的子網(wǎng)地址。舉個(gè)例子,如果我再子網(wǎng)中可指定地址為192.168.1和想要傳播到子網(wǎng)中的所有節(jié)點(diǎn),我可以指定192.168.1.255作為地址;這樣允許子網(wǎng)中的每個(gè)節(jié)點(diǎn)監(jiān)聽廣播媒體。
    · port 必須是被傳輸者和接收者都允許的一個(gè)端口。
    · content-type 是媒體流類型。在我們的案子中,這個(gè)將會(huì)是音頻。
    下面的一個(gè)簡單的RTP傳播MediaLocator例子會(huì)讓所有在指定網(wǎng)絡(luò)中的機(jī)器接收到媒體流:

    rtp://192.168.1.255:49150/audio



    創(chuàng)建一個(gè)處理機(jī)
    在setDataSource()方法中我們首先要做的就是創(chuàng)建一個(gè)Processor實(shí)例。
    下面的Processor的職責(zé)是轉(zhuǎn)換MP3音頻媒體為一個(gè)RTP來表示:
    public void setDataSource(DataSource ds) throws IOException,
    NoProcessorException, CannotRealizeException, NoDataSinkException {
    mediaProcessor = Manager.createRealizedProcessor(
    new ProcessorModel(ds, FORMATS, CONTENT_DESCRIPTOR));
    在Manager類中,我們能創(chuàng)建一個(gè)Processor對象,通過兩種方法中的一種:
    createProcessor()或者createRealizedProcessor()。你很可能會(huì)注意到這兩個(gè)方法樣式的顯示和前面例子中創(chuàng)建一個(gè)Player的方法很相似。在目前的例子中,我們將創(chuàng)建一個(gè)已實(shí)現(xiàn)的Processor。我們這樣做是因?yàn)槲覀兪褂玫膽?yīng)用非常簡單,在Processo處于Realized狀態(tài)時(shí)我們不需要關(guān)心任何真實(shí)的工作。

    創(chuàng)建一個(gè)ProcessorModel
    創(chuàng)建一個(gè)已實(shí)現(xiàn)的Processor,我們需要?jiǎng)?chuàng)建一個(gè)為Processor描述輸入和輸出媒體類型的ProcessorModel實(shí)例。為了創(chuàng)建ProcessorModel,我們需要下面的一些:
    · 一個(gè)DataSource,將被處理的媒體(輸入文件)。
    · 一個(gè)javax.media.Format數(shù)組,描述輸入媒體的格式。
    · 一個(gè)javax.media.protocol.ContentDescriptor實(shí)例,為我們的處理機(jī)描述輸出格式。傳送者的DataSource是通過一個(gè)參數(shù)傳遞到此方法。

    定義輸入和輸出格式
    因?yàn)槲覀兊腗ediaTransmitter類會(huì)被時(shí)常用于將輸入媒體格式(MP3)轉(zhuǎn)換成一種輸出格式(音頻RTP),中學(xué)對象被定義成靜態(tài)。我們創(chuàng)建一個(gè)新的javax.media.format.AudioFormat實(shí)例用于描述媒體輸入類型(在java幫助文檔中查看可用格式)。這就是我們的處理機(jī)可以獲取MP3音頻文件的原因。
    我們也創(chuàng)建一個(gè)javax.media.protocol.ContentDescriptor實(shí)例來描述想要處理機(jī)輸出的。在我們的案子中,這是一個(gè)RTP媒體流。

    這就是為什么我們的處理機(jī)可以只制造RTP流。
    下面的代碼片斷顯示了我們?nèi)绾卧O(shè)置格式和內(nèi)容描述符變量,用于創(chuàng)建ProcessorModel對象:

    private static final Format[] FORMATS = new Format[] {
    new AudioFormat(AudioFormat.MPEG_RTP)};
    private static final ContentDescriptor CONTENT_DESCRIPTOR =
    new ContentDescriptor(ContentDescriptor.RAW_RTP);



    連接輸入,處理機(jī)和輸出
    現(xiàn)在我們有一個(gè)處于Realized狀態(tài)的Processor,我們需要設(shè)置DataSink以能實(shí)際上傳播RTP媒體。創(chuàng)建DataSink是簡單的大概使用另外一個(gè)調(diào)用給Manager對象,如下所示:

    dataSink = Manager.createDataSink(mediaProcessor.getDataOutput(),
    mediaLocator);



    createDataSink()方法獲取新Processor的輸出(作為一個(gè)DataSource參數(shù))和MediaLocator對象,我們和MediaTransmitter對象同時(shí)建立的。通過這樣,你能開始我們的不同的組件是如何在處理模式中聯(lián)系起來的:我們從一個(gè)Processor中獲取輸出并使用他們作為輸入到其他組件。在這個(gè)特殊的應(yīng)用中,Processor輸出用于傳輸媒體的DataSink的一個(gè)輸入。

    創(chuàng)建一個(gè)DataSource實(shí)例
    在這點(diǎn)上,我們?nèi)慷际亲龊驮O(shè)置我們的媒體播放器的廣播傳輸。
    我們需要?jiǎng)?chuàng)建DataSource對象,我們用于創(chuàng)建處理機(jī)(就是,在我們的MediaTransmitter中,參數(shù)傳遞到setDataSource()方法)。下面是創(chuàng)建一個(gè)DataSource實(shí)例的代碼:

    File mediaFile = new File(args[1]);
    DataSource source = Manager.createDataSource(new MediaLocator(
    mediaFile.toURL()));



    這段代碼是在MediaTransmitter對象中的vmain()方法。這里我們通過從命令行輸入的第二個(gè)參數(shù)創(chuàng)建一個(gè)File對象。我們通過文件創(chuàng)建一個(gè)MediaLocator,而后通過位置創(chuàng)建一個(gè)DataSource。這個(gè)新近創(chuàng)建的DataSource是一個(gè)涉及到傳送者的輸入文件。我們能使用這個(gè)DataSource初始化傳輸者。

    開始和停止MediaTransmitter
    我們通過調(diào)用其中的startTransmitting()方法來開始MediaTransmitter,如下所示:

    public void startTransmitting() throws IOException {
    mediaProcessor.start();
    dataSink.open();
    dataSink.start();
    }



    這個(gè)方法首先開啟處理機(jī),然后打開并啟動(dòng)DataSink。在這個(gè)調(diào)用后,接收機(jī)器就可在媒體傳送者上監(jiān)聽。
    停止傳輸者是非常簡單的。以下代碼將DataSink和Processor都停止和關(guān)閉掉:

    public void stopTransmitting() throws IOException {
    dataSink.stop();
    dataSink.close();
    mediaProcessor.stop();
    mediaProcessor.close();
    }



    編譯和運(yùn)行MediaTransmitter
    通過在命令行中輸入javac MediaTransmitter.java來編譯例程序,可在你的工作目錄中生成一個(gè)同名的.class文件。
    要運(yùn)行例程序,在命令提示行中輸入以下代碼:

    java MediaTransmitter rtpMediaLocator audioFile



    此例將創(chuàng)建一個(gè)myAudio.mp3文件的媒體廣播。不要忘記將rtpMediaLocator替換成一個(gè)媒體傳輸?shù)腞TP URL,如同先前討論的。
    你同樣也需要將audioFile替換成你本機(jī)的音頻文件名。
    所有的相對文件名都是相對于當(dāng)前工作目錄的。你會(huì)看見一些信息標(biāo)志正在播放的文件。按下Enter鍵來停止播放。

    為傳送者的一個(gè)例命令行交互如下:
    java MediaTransmitter rtp://192.168.1.255:49150/audio myAudio.mp3
    如果初始編輯失敗,確定JMF的jar文件包含CLASSPATH環(huán)境變量中。要近一步探索本程序和練習(xí),請查閱MediaTransmitter源代碼。

    接收傳輸?shù)拿襟w
    現(xiàn)在你可能會(huì)問,“如果沒有人可以看或者收聽的話,這個(gè)傳播媒體有什么好的?”
    幸運(yùn)的是,設(shè)定一個(gè)接收傳播媒體的客戶端只需要對我們在第二個(gè)例程序的MediaPlayerFrame源代碼做很小的改動(dòng)。
    MediaPlayerFrame類需要一個(gè)很小的調(diào)節(jié)來接收和播放音頻文件。在main()方法中,你需要注釋掉如下的一行:

    mpf.setMediaLocator(new MediaLocator(new File(args[0]).toURL()));


    并且輸入如下的一行:

    mpf.setMediaLocator(new MediaLocator(args[0]));


    這個(gè)簡單的改動(dòng)允許我們通過String來創(chuàng)建一個(gè)MediaLocator對象,而不是通過創(chuàng)建一個(gè)File來創(chuàng)建MediaLocator。
    其他代碼都一樣。

    指定RTP URL
    在12頁的說明編譯和運(yùn)行MediaPlayerFrame介紹了如何編譯和運(yùn)行MediaPlayerFrame例程序。這唯一的不同就是你需要為傳輸者指定RTP URL。為接收者的例命令行交互如下:

    java MediaPlayerFrame rtp://192.168.1.255:49150/audio



    運(yùn)行網(wǎng)絡(luò)媒體傳送者的注意事項(xiàng)
    如果你在網(wǎng)絡(luò)上只有權(quán)使用一臺(tái)機(jī)器,你仍然可以運(yùn)行傳輸程序。當(dāng)你啟動(dòng)傳送程序的時(shí)候,你可以即使用RTP URL傳輸?shù)刂罚部芍付愎ぷ鞯臋C(jī)器的機(jī)器地址。為了能夠調(diào)節(jié)傳輸,在開始前接收者必須使用精確的同樣的RTP URL。
    如果你運(yùn)行本例真實(shí)的網(wǎng)絡(luò)版本,每臺(tái)你使用的機(jī)器都需要安裝JMF,不論是傳輸還是接收媒體流。這是必須的,因?yàn)椴徽撌莻魉统绦蜻€是接收程序都大量的使用了JMF的API。
    在任一個(gè)案子中,確認(rèn)在指定的RTP URL中使用了相同的地址和端口;否則媒體傳輸是不會(huì)工作的。

    第六節(jié). 約束和資源
    摘要
    我希望本指南能給你提供如何使用JMF的API的有用的瀏覽。
    我們建立了三個(gè)小的應(yīng)用程序來播放本地的音頻和視頻,也通過網(wǎng)絡(luò)傳播和接收媒體。這些應(yīng)用程序的源代碼中包含了很多的javadoc樣式的注釋。這就有助于你理解你剩余的問題。
    許多JMF的主題在本指南中并沒有涉及。實(shí)際上,我們更關(guān)注JMF的基本概念和應(yīng)用;在此基礎(chǔ)上,我們能輕易地?cái)U(kuò)展學(xué)習(xí)的其他范圍。要更深入JMF的應(yīng)用程序,你可能想要學(xué)習(xí)下面的面板中所提到的主題。更近一步的閱讀本指南中的主題,查閱23頁的資源。

    高級主題
    大量的值得做的練習(xí)在本指南的范圍之上。在簡單的說明之下自己更進(jìn)一步的學(xué)習(xí),你可以擴(kuò)展我們的應(yīng)用程序代碼,也可以反展你的JMF相關(guān)知識。使用以下的練習(xí)開始:
    · 媒體捕獲:JMF包含了豐富的API來捕獲媒體數(shù)據(jù)。如果你對使用JMF捕獲媒體感興趣,你可以使用javax.media.CaptureDeviceManager類和javax.media.protocol.CaptureDevice接口的API來學(xué)習(xí)。對于一個(gè)高級的練習(xí),考慮使用CaptureDeviceManager和CaptureDevice接口來增加媒體捕獲功能到媒體播放應(yīng)用程序的GUI版本上。
    · 會(huì)話管理:由于本指南是一個(gè)JMF的說明,我們使輸出表現(xiàn)非常的簡單,僅僅實(shí)現(xiàn)了javax.media.DataSink輸出。
    另外的輸出表示是使用javax.media.rtp.SessionManager。這個(gè)管理類允許客戶端創(chuàng)建并監(jiān)視他們的RTP流和連接。通過SessionManager并隨后創(chuàng)建流,它可能非常的接近監(jiān)視RTP會(huì)話。作為一個(gè)高級的練習(xí),轉(zhuǎn)換我們的地三個(gè)演示程序來使用SessionManager,然后監(jiān)聽流出的RTP流已經(jīng)哪些客戶端在收聽。
    · 使用JMF的多點(diǎn)傳送:我們的廣播演示應(yīng)用程序說明了如何傳送一個(gè)網(wǎng)絡(luò)的媒體到另外一個(gè)網(wǎng)絡(luò)的一或多臺(tái)機(jī)器上去。它也可能使用JMF中的多點(diǎn)傳輸協(xié)議來提供給更復(fù)雜,多用戶的網(wǎng)絡(luò)。
    JMF用戶指南提供了一個(gè)使用JMF的多播協(xié)議的更深入的探討。更進(jìn)一步追蹤本主題查看23頁資源。
    · 傳輸視頻: 我們的最后一個(gè)演示應(yīng)用程序著眼于如何傳輸一個(gè)MP3音頻文件,但是JMF也能夠通過網(wǎng)絡(luò)傳遞視頻。關(guān)注API文檔中的Format和ContentDescriptor類獲得如何使用的更好的方法。
    · 導(dǎo)入/導(dǎo)出RTP媒體流: JMF同樣允許將RTP流保存為文件以便將來使用。舉一個(gè)實(shí)例,一個(gè)遠(yuǎn)程電信會(huì)議可以保存下來以后再看。
    由于流已經(jīng)保存再RTP格式中,已經(jīng)不需要再次轉(zhuǎn)換,這樣可導(dǎo)致傳輸程序的性能改進(jìn)。通過一個(gè)文件而不是URL來設(shè)置DataSink對象中輸入/輸出MediaLocator。你會(huì)再JMF用戶指南中發(fā)現(xiàn)更深層次的主題探討。

    資源
    JMF
    · 下載mediaplayer.jar,本指南中使用的完整的例源代碼。
    ·??JMF主頁 (http://www.javasoft.com/jmf)是最好的探討JMF更多信息的資源。
    · 你可以找到JMF說明書(http://java.sun.com/products/java-media/jmf/2.1.1/specdownload.html),再Java開發(fā)者聯(lián)盟上包括API文檔和JMF用戶指南。你必須有權(quán)使用所有的這些資源,如果你想做任何更深入的JMF編程的話。
    · 官方的JMF支持文件格式 頁面
    (http://java.sun.com/products/java-media/jmf/2.1.1/formats.html) 列出了所有可為JMF辨識并播放的文件格式。此文件格式頁面也包括了學(xué)習(xí)更多關(guān)于捕獲設(shè)備和RTP格式的參考。
    · MPEG-4 Video for JMF (http://www.alphaworks.ibm.com/tech/mpeg-4), 來自IBM
    alphaWorks, 是一個(gè)JMF的視頻編解碼器。
    RTP
    ·??IETF RTP RFC (http://www.ietf.org/rfc/rfc1889.txt) 非常詳細(xì)的描述了RTP協(xié)議。
    · 查看 JMF API Guide
    (http://java.sun.com/products/java-media/jmf/2.1.1/specdownload.html) ,有許多有關(guān)于RTP協(xié)議和描述以及它是如何在JMF上應(yīng)用的。
    · 哥倫比亞大學(xué)有一個(gè)比較有用的RTP FAQ(http://www.cs.columbia.edu/~hgs/rtp/faq.html).
    Java技術(shù)
    ·??Java 2 Platform, Standard Edition (http://java.sun.com/j2se/) 可從sun公司獲得。
    · sun的指南關(guān)于JFC/Swing (http://java.sun.com/docs/books/tutorial/uiswing/index.html)
    和 AWT (http://java.sun.com/docs/books/tutorial/information/download.html#OLDui) 是非常好的能學(xué)習(xí)到很多關(guān)于Java程序語言中GUI編程的好地方。
    · 另外一個(gè)sun指南學(xué)習(xí)network programming 基礎(chǔ)
    (http://java.sun.com/docs/books/tutorial/networking/index.html)。
    多點(diǎn)傳輸協(xié)議
    · Explicit Multicast (XCAST)
    (http://oss.software.ibm.com/developerworks/opensource/xcast/) 是IP多點(diǎn)傳輸?shù)囊环N形式,為非常多的多點(diǎn)傳輸組設(shè)計(jì)提供可升級的支持,這些組有些少量的參與者代表。XCAST 代碼得到了IBM Common Public License的認(rèn)可。
    · Todd Montgomery 的 MTP page (http://www.nard.net/~tmont/rm-links.html),
    在這里你能找到一個(gè)廣泛的涉及到多點(diǎn)傳輸協(xié)議的列表。
    附加資源
    · 你可以在
    developerWorks Java technology zone (http://www-106.ibm.com/developerworks/java/)中找到許多的關(guān)于Java各方面的內(nèi)容。
    · 查看 developerWorks tutorials page
    (http://www-105.ibm.com/developerworks/education.nsf/dw/java-onlinecourse-bytitle?OpenDocument&Count=for a complete listing of free tutorials.

    posted @ 2006-07-27 20:05 KevinGong 閱讀(563) | 評論 (1)編輯 收藏

    僅列出標(biāo)題
    共2頁: 1 2 下一頁 
    主站蜘蛛池模板: 中文字幕人成人乱码亚洲电影| 国产国产人免费视频成69大陆| 四虎在线免费视频| 三年片在线观看免费大全| 在线jyzzjyzz免费视频| 欧亚一级毛片免费看| 亚洲剧情在线观看| 亚洲精品无码不卡在线播放| 亚洲黄色三级视频| 久久亚洲精品AB无码播放| 亚洲色欲一区二区三区在线观看| 亚洲成人一区二区| 亚洲s色大片在线观看| 国产精品亚洲综合一区| 亚洲狠狠综合久久| 亚洲中文字幕乱码一区| 男女猛烈无遮掩视频免费软件| A毛片毛片看免费| 性xxxxx免费视频播放| 又粗又大又长又爽免费视频| 亚洲gv白嫩小受在线观看| 久久亚洲最大成人网4438| 免费人成大片在线观看播放电影| 国产一精品一av一免费爽爽| 成年私人影院免费视频网站| 日韩精品福利片午夜免费观着| 免费一区二区视频| 少妇中文字幕乱码亚洲影视| 亚洲视频在线一区二区三区| 综合偷自拍亚洲乱中文字幕| 小说专区亚洲春色校园| 久久久久久一品道精品免费看| 在线a人片天堂免费观看高清| 亚洲线精品一区二区三区| 亚洲自国产拍揄拍| 免费在线观影网站| 性做久久久久免费看| 亚洲国产成人精品女人久久久 | 亚洲国产av无码精品| 777亚洲精品乱码久久久久久 | 亚洲自国产拍揄拍|