konhon

          忘掉過去,展望未來。找回自我,超越自我。
          逃避不一定躲的過, 面對不一定最難過, 孤單不一定不快樂, 得到不一定能長久, 失去不一定不再擁有, 可能因?yàn)槟硞€(gè)理由而傷心難過, 但我卻能找個(gè)理由讓自己快樂.

          Google

          BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
            203 Posts :: 0 Stories :: 61 Comments :: 0 Trackbacks

          2007年3月8日 #

             很多股民常常感到孤獨(dú)無助,買入的股票總是被套,這里面折射出一個(gè)問題,那就是你沒有真正的掌握好買入點(diǎn),今天我就在這里給大家講一講如何把握買入點(diǎn)。

            由于股票變化無常,主力更是絞盡腦汁和散戶斗智斗勇,所以買入法也沒有固定格式,我在這里只簡單的介紹幾種很有效的方法,僅供你借鑒。

               1、量縮法。顧名思義,就是當(dāng)股票在一定“趨勢和條件”下,成交量開始萎縮到不能再萎縮時(shí),說明下跌能量消耗已盡,此時(shí)就是最好的買入點(diǎn)。所謂的“趨勢和條件”是講——這只股票運(yùn)行趨勢必須是在上升通道或低位震蕩中,當(dāng)它連續(xù)下跌兩到三天時(shí),成交量已經(jīng)萎縮很多,股價(jià)波動范圍已經(jīng)很小,盤中也不再見有大的買單,特別是遇到大盤下跌時(shí),它也不再下跌,這說明這只股票到了“谷”底,隨時(shí)有反彈和新的行情發(fā)動,此時(shí)就是最價(jià)買入點(diǎn)。例如600297在1月30號到2月2號,連續(xù)下跌了四天,切成交量逐步萎縮,2月2號就是個(gè)最價(jià)買點(diǎn)。

               2、前高突破法。當(dāng)一只股票經(jīng)過一段時(shí)間的上漲,之后開始進(jìn)入回調(diào),當(dāng)經(jīng)過一段時(shí)間的調(diào)整,再次開始放量攻擊前期高點(diǎn)時(shí),此時(shí)也是買入點(diǎn)。但是這里最難把握的就是主力的假突破,很容易上當(dāng),這需要你自己正確判斷。比方說600983在1月23達(dá)到一個(gè)高點(diǎn)后,2月8號開始放量攻擊前期高點(diǎn),那么2月8號就是最價(jià)買點(diǎn)。而600717在3月8號就是一個(gè)假突破。我特別強(qiáng)調(diào)一點(diǎn),最好是出現(xiàn)三次沖擊前期高點(diǎn)的股票,把握性最大。

               3、長陽之后等待法。就是當(dāng)某只股票出現(xiàn)長陽甚至是漲停時(shí),第二天它很可能不再連續(xù)拉升,而是出現(xiàn)小幅的調(diào)整,此時(shí)也是買入點(diǎn),例如600723在1月18日就是一個(gè)買入點(diǎn)。

               4、誘空識破法。很多主力在進(jìn)入下一波的大行情中,往往做最后的誘空洗盤。此時(shí)也是最價(jià)買入法,這需要你高超的識盤技巧。例如,600176在1月31號,出現(xiàn)了一條放量的長陰,其實(shí)那是誘空,做出這樣的判斷是要對這只股票的基本面和技術(shù)面都非常熟悉才行。

               5、大換手率的等待法。當(dāng)某只股票在低位(特別強(qiáng)調(diào)是低位)出現(xiàn)大換手率時(shí),說明主力殺入,你隨時(shí)可以跟進(jìn)。例如600178在1月19和22連續(xù)兩天出現(xiàn)超過12%的還手率,之后再出現(xiàn)低點(diǎn)時(shí),你就可以殺入了。
          posted @ 2007-04-04 06:52 konhon 優(yōu)華 閱讀(1437) | 評論 (0)編輯 收藏

          http://www.openitpower.com/wenzhang/97/10846_1.html

            與TTable、TQuery一樣,TClientDataSet也是從TDataSet繼承下來的,它通常用于多層體系結(jié)構(gòu)的客戶端。TClientDataSet最大的特點(diǎn)是它不依賴于BDE(Borland Database Engine),但它需要一個(gè)動態(tài)鏈接庫的支持,這個(gè)動態(tài)鏈接庫叫DBCLIENT.DLL。在客戶端,也不需要用TDatabase構(gòu)件,因?yàn)榭蛻舳瞬⒉恢苯舆B接數(shù)據(jù)庫。
            由于TClientDataSet是從TDataSet繼承下來的,所以,它支持諸如編輯、搜索、瀏覽、糾錯、過濾等功能。由于TClientDataSet在內(nèi)存中建立了數(shù)據(jù)的本地副本,上述操作的執(zhí)行速度很快。也正是由于TClientDataSet并不直接連接數(shù)據(jù)庫,因此,客戶程序必須提供獲取數(shù)據(jù)的機(jī)制。在Delphi 4中,TClientDataSet有三種途徑獲取數(shù)據(jù):
          .從文件中存取數(shù)據(jù)。
          .從本地的另一個(gè)數(shù)據(jù)集中獲取數(shù)據(jù)。
          .通過IProvider接口從遠(yuǎn)程數(shù)據(jù)庫服務(wù)器獲取數(shù)據(jù)。
            在一個(gè)客戶程序中,可以同時(shí)運(yùn)用上述三種機(jī)制獲取數(shù)據(jù)。
          11.1 瀏覽和編輯數(shù)據(jù)
            和其他數(shù)據(jù)集構(gòu)件一樣,可以用標(biāo)準(zhǔn)的數(shù)據(jù)控件顯示由TClientDataSet引入的數(shù)據(jù)集,當(dāng)然,這需要借助于TDataSource構(gòu)件。
            由于TClientDataSet是從TDataSet繼承下來的,所以,凡是其他數(shù)據(jù)集構(gòu)件支持的功能,TClientDataSet構(gòu)件也大致具備。不同的是,TClientDataSet能夠在內(nèi)存中建立數(shù)據(jù)的副本,因此,TClientDataSet比其他數(shù)據(jù)集構(gòu)件增加了一些特殊的功能。
          11.1.1 瀏覽數(shù)據(jù)
            可以用標(biāo)準(zhǔn)的數(shù)據(jù)控件顯示由TClientDataSet引入的數(shù)據(jù)集。在運(yùn)行期,可以調(diào)用諸如First、GotoKey、Last、Next和Prior等函數(shù)來瀏覽數(shù)據(jù)。
            TClientDataSet也支持書簽功能,可以用書簽來標(biāo)記某條記錄,以后就可以方便地找到這條記錄。
            對于TTable、TQuery等數(shù)據(jù)集構(gòu)件來說,只能讀RecNo屬性來判斷當(dāng)前記錄的序號。對于TClientDataSet構(gòu)件來說,還可以寫RecNo屬性,使某一序號的記錄成為當(dāng)前記錄。
          11.1.2 CanModify屬性
            TDataSet的CanModify屬性用于判斷數(shù)據(jù)集中的數(shù)據(jù)是否可以修改。CanModify屬性本身是只讀的,也就是說,數(shù)據(jù)是否能夠修改不取決于應(yīng)用程序。
            不過,TClientDataSet構(gòu)件有其特殊性,因?yàn)門ClientDataSet已經(jīng)把數(shù)據(jù)在內(nèi)存中建立了副本,因此,應(yīng)用程序可以決定是否允許修改數(shù)據(jù)。如果不允許用戶修改數(shù)據(jù),只要把ReadOnly屬性設(shè)為True,此時(shí),CanModify屬性肯定返回False。
            與其他數(shù)據(jù)集構(gòu)件不同,修改TClientDataSet構(gòu)件的ReadOnly屬性時(shí),不需要事先把Active屬性設(shè)為True。
          11.1.3 取消修改
            TClientDataSet傳輸數(shù)據(jù)的基本單位稱為數(shù)據(jù)包,當(dāng)前的數(shù)據(jù)包可以由Data屬性來訪問。不過,用戶對數(shù)據(jù)的修改并不直接反映到Data屬性中,而是臨時(shí)寫到一個(gè)日志即Delta屬性中,這樣做的好處是以后隨時(shí)可以取消修改。
            不過,這里要說明一點(diǎn),盡管用戶的修改并沒有反映到Data,當(dāng)用戶在數(shù)據(jù)控件中看到的卻是最新修改的數(shù)據(jù)。如果一條記錄被反復(fù)修改了多次,用戶看到的只是最新的數(shù)據(jù),但日志中卻記載了多次。
            要取消上一次的修改,調(diào)用UndoLastChange函數(shù)。UndoLastChange需要傳遞一個(gè)布爾類型的參數(shù)叫FollowChange,如果FollowChange參數(shù)設(shè)為True,光標(biāo)就移到被恢復(fù)的記錄上,如果FollowChange參數(shù)設(shè)為False,光標(biāo)仍然在當(dāng)前記錄上。
            ChangeCount屬性返回日志中記載的修改次數(shù)。如果一條記錄被反復(fù)修改了多次,每調(diào)用一次UndoLastChange能夠逐級取消上一次的修改。
            UndoLastChange只能取消上一次的修改,如果想一下子取消所有的修改,首先要選擇一個(gè)記錄,然后調(diào)用RevertRecord。RevertRecord將從日志中取消所有對當(dāng)前記錄的修改。
            TClientDataSet還有一個(gè)SavePoint屬性,它能把當(dāng)前的編輯狀態(tài)保存起來,以后隨時(shí)可以返回當(dāng)時(shí)的狀態(tài)。例如,可以這樣保存當(dāng)前的狀態(tài):
            BeforeChanges := ClientDataSet1.SavePoint;
            以后,可以這樣來恢復(fù)當(dāng)時(shí)的狀態(tài):
            ClientDataSet1.SavePoint := BeforeChanges;
            應(yīng)用程序可以保存多處狀態(tài),可以恢復(fù)其中一個(gè)狀態(tài),不過,一旦某個(gè)狀態(tài)被恢復(fù),在其之后的狀態(tài)就無效。
            如果要一下子取消日志中記載的所有修改,可以調(diào)用CancelUpdates函數(shù)。CancelUpdates將把日志清空,取消所有的修改。
            如果LogChanges屬性設(shè)為False,用戶對數(shù)據(jù)的修改就會直接反映到Data屬性中。
          11.1.4 合并修改
            要把日志中記載的修改合并到Data屬性中,有兩種方式,具體使用哪一種方式,取決于應(yīng)用程序獲取數(shù)據(jù)的機(jī)制。不過,不管是哪種機(jī)制,合并后,日志自動被清空。
            對于一個(gè)從文件中獲取數(shù)據(jù)的程序來說,只要調(diào)用MergeChangeLog函數(shù),就把日志中記載的修改合并到Data屬性中。不用擔(dān)心其他用戶同時(shí)修改了數(shù)據(jù)。
            對于一個(gè)從應(yīng)用服務(wù)器獲取數(shù)據(jù)的程序來說,就不能調(diào)用MergeChangeLog來合并數(shù)據(jù),而要調(diào)用ApplyUpdates函數(shù),ApplyUpdates會把日志中記載的修改傳遞給應(yīng)用服務(wù)器,待應(yīng)用服務(wù)器成功地把數(shù)據(jù)更新了數(shù)據(jù)庫服務(wù)器后,才會合并到Data屬性中。
          11.1.5 糾錯
            TClientDataSet支持糾錯功能。一般情況下,需要自己建立糾錯規(guī)則,以便對用戶輸入的數(shù)據(jù)進(jìn)行糾錯。
            此外,如果獲得了IProvider接口的話,還可以從遠(yuǎn)程服務(wù)器引入糾錯規(guī)則。
            有時(shí)候,客戶端可能需要暫時(shí)禁止糾錯,因?yàn)榭蛻舳藦膽?yīng)用服務(wù)器檢索數(shù)據(jù)是分階段進(jìn)行的,在所有的數(shù)據(jù)檢索完畢之前,有些糾錯規(guī)則很可能會報(bào)錯。
          要暫時(shí)禁止糾錯,可以調(diào)用DisableConstraints,要重新允許糾錯,可以調(diào)用EnableConstraints函數(shù)。DisableConstraints和EnableConstraints實(shí)際上都是作用于一個(gè)內(nèi)部的計(jì)數(shù)。
          11.2 索 引
            使用索引有這么幾個(gè)好處:
          .在數(shù)據(jù)集中定位記錄比較快。
          .能夠在兩個(gè)數(shù)據(jù)集之間建立Lookup或Master/Detail關(guān)系。
          .可以對記錄排序。
            在多層體系結(jié)構(gòu)中,當(dāng)客戶程序從應(yīng)用服務(wù)器檢索數(shù)據(jù)時(shí),它同時(shí)獲得了默認(rèn)的索引。默認(rèn)的索引叫DEFAULT_ORDER,可以使用這個(gè)索引排序,但不能修改或刪除這個(gè)索引。
            除了默認(rèn)的索引外,TClientDataSet還對日志中記載的記錄自動建立了一個(gè)副索引叫CHANGEINDEX。與DEFAULT_ORDER一樣,不能修改或刪除這個(gè)副索引。
            另外,還可以使用數(shù)據(jù)集中已建立的其他索引,或者自己建立索引。
          11.2.1 創(chuàng)建一個(gè)新的索引
            要創(chuàng)建一個(gè)新的索引,可以調(diào)用AddIndex。AddIndex需要傳遞若干個(gè)參數(shù):
            一是Name參數(shù),用于指定索引名。在運(yùn)行期切換索引時(shí)需要用到索引的名稱。
            二是Fields參數(shù),它是一個(gè)字符串,用于指定索引中的字段名,彼此之間用分號隔開。
            三是Options參數(shù),用于設(shè)置索引的選項(xiàng),包含ixDescending元素表示按降序排列,包含ixCaseInsensitive元素表示大小寫不敏感。
            四是DescFields參數(shù),它也是一個(gè)字符串,用于指定若干個(gè)字段名,這些字段將按照降序排列。
            五是CaseInsFields參數(shù),它的作用與DescFields參數(shù)類似,包含在CaseInsFields參數(shù)中的字段將對大小寫不敏感。
            六是GroupingLevel參數(shù),用于指定分組級別,其值不能超過索引中的字段數(shù)。
            下面的代碼創(chuàng)建了一個(gè)索引:
          If Edit1.Text <> '' and ClientDataSet1.Fields.FindField(Edit1.Text) then
          Begin
          ClientDataSet1.AddIndex(Edit1.Text+'Index',Edit1.Text,  
            [ixCaseInsensitive],'','',0);
          ClientDataSet1.IndexName := Edit1.Text + 'Index';
          End;
          為了避免創(chuàng)建一個(gè)索引,可以臨時(shí)用IndexFieldNames屬性來指定若干個(gè)字段,讓數(shù)據(jù)集按這些字段排序。
          11.2.2 刪除和切換索引
            要刪除一個(gè)先前創(chuàng)建的索引,可以調(diào)用DeleteIndex并指定要刪除的索引名稱。注意:DEFAULT_ORDER和CHANGEINDEX不能刪除。
            如果建立了多個(gè)索引,可以任意選擇其中的一個(gè)索引,這就要用到IndexName屬性。
          11.2.3 用索引把數(shù)據(jù)分組
            選擇了一個(gè)索引后,數(shù)據(jù)集將自動按其中的字段進(jìn)行排序。這樣,臨近的記錄往往在關(guān)鍵字段上含有相同的值。例如,假設(shè)有一個(gè)表是這樣的:
          SalesRep Customer OrderNo Amount
          1      1     5    100
          1      1     2    50
          1      2     3    200
          1       2     6    75
          2      1     1    10
          2      3     4    200
            可以看出,SalesRep字段的值有重復(fù)的。對于SalesRep字段的值為1的來說,Customer字段的值也有重復(fù)的。這就是說,可以按SalesRep字段分組,進(jìn)而再按Customer字段分組。顯然,這里的分組級別是不同的,按SalesRep字段建立的分組屬于第一級,按Customer字段建立的分組屬于第二級。實(shí)際上,分組級別取決于字段在索引中的順序。
            TClientDataSet可以決定是否按照分組級別來顯示記錄的值。例如,也許想以下面這種形式顯示數(shù)據(jù):
          SalesRep Customer OrderNo Amount
          1      1    5    100
                     2    50
                 2    3    200
                     6    75
          2      1    1    10
          2      3    4    200
            要判斷當(dāng)前記錄某一級的什么位置,可以調(diào)用GetGroupState函數(shù)。GetGroupState函數(shù)需要傳遞一個(gè)參數(shù),用于指定分組級別。
          11.3 計(jì) 算 字 段
            與其他數(shù)據(jù)集一樣,也可以在TClientDataSet建立的數(shù)據(jù)集中增加計(jì)算字段。計(jì)算字段的值是基于同一個(gè)記錄中的其他字段計(jì)算出來的。
            在其他數(shù)據(jù)集中,只要用戶修改了數(shù)據(jù)或當(dāng)前記錄發(fā)生改變,就會觸發(fā)OnCalcFields事件,換句話說,計(jì)算字段的值就被計(jì)算一次。
            TClientDataSet引入了“內(nèi)部計(jì)算字段”的概念。與一般的計(jì)算字段不同的是,內(nèi)部計(jì)算字段的值將隨其他字段的值一起存取,這樣,只有當(dāng)用戶修改了數(shù)據(jù)才會觸發(fā)OnCalcFields事件,如果僅僅改變了當(dāng)前記錄,不會觸發(fā)OnCalcFields事件。也就是說,內(nèi)部計(jì)算字段的值需要重新計(jì)算的機(jī)會大大減少。
            在處理OnCalcFields事件的句柄中,首先要判斷State屬性。如果State屬性返回dsInternalCalc,此時(shí)需要計(jì)算內(nèi)部計(jì)算字段的值。如果State屬性返回dsCalcFields,此時(shí)需要計(jì)算一般的計(jì)算字段的值。
          11.4 統(tǒng) 計(jì) 值
            TClientDataSet增加了統(tǒng)計(jì)的功能,它可以基于分組自動計(jì)算總和、平均、計(jì)數(shù)、最大、最小值。當(dāng)用戶編輯數(shù)據(jù)時(shí),這些統(tǒng)計(jì)值會自動跟著變化。
          11.4.1 指定統(tǒng)計(jì)方式
            要指定怎樣進(jìn)行統(tǒng)計(jì),就要用到Aggregates屬性。這個(gè)屬性是一個(gè)TAggregates對象,它用于管理一組TAggregate對象。
            在設(shè)計(jì)期,可以單擊Aggregates屬性邊上的省略號按鈕打開如圖11.1所示
          的編輯器。
            圖11.1 管理一組TAggregate對象
            單擊按鈕可以增加一個(gè)TAggregate對象,單擊按鈕可以刪減一個(gè)TAggregate對象,單擊按鈕可以把TAggregate對象前移,單擊按鈕可以把TAggregate對象后移。
            可以用字段編輯器專門創(chuàng)建一個(gè)用于表達(dá)統(tǒng)計(jì)值的字段,該字段的類型必須是“Aggregate”。Delphi 4會自動創(chuàng)建一個(gè)TAggregate對象,并加到Aggregates屬性中。選擇一個(gè)TAggregate對象,Object Inpector將顯示該對象的屬性。
            其中,Expression屬性用于指定統(tǒng)計(jì)表達(dá)式,例如:
          Sum(Field1)
            也可以是比較復(fù)雜的表達(dá)式:
          Sum(Qty * Price) - Sum(AmountPaid)
            在表達(dá)式中,可以使用下列統(tǒng)計(jì)運(yùn)算符:
          .Sum計(jì)算一組數(shù)據(jù)的總和。
          .Avg計(jì)算一組數(shù)據(jù)的平均值。
          .Count計(jì)算一組數(shù)據(jù)中的非空值的個(gè)數(shù)。
          .Min計(jì)算一組數(shù)據(jù)的最小值。
          .Max計(jì)算一組數(shù)據(jù)的最大值。
            除了上述幾個(gè)統(tǒng)計(jì)運(yùn)算符外,還可以使用過濾條件中所能使用的運(yùn)算符,但不能嵌套。在一個(gè)表達(dá)式中,可以混合出現(xiàn)幾個(gè)統(tǒng)計(jì)值或常量,但不能混合出現(xiàn)統(tǒng)計(jì)值和字段。
            Sum(Qty * Price){合法}
            Max(Field1) - Max(Field2){合法}
            Avg(DiscountRate) * 100{合法}
            Min(Sum(Field1)){非法,不能嵌套}
            Count(Field1) - Field2{非法,統(tǒng)計(jì)值和字段不能混合出現(xiàn)在一個(gè)表達(dá)式中}
          11.4.2 指定分組
            默認(rèn)情況下,統(tǒng)計(jì)值是基于數(shù)據(jù)集中所有的記錄計(jì)算出來的。不過,也可以針對一部分記錄計(jì)算統(tǒng)計(jì)值,這就需要事先建立分組。
            前面在介紹索引時(shí)已經(jīng)提到分組的概念。可以通過IndexName屬性和GroupingLevel屬性來選擇使用哪個(gè)索引以及最大的分組級別。
            例如,假設(shè)有一個(gè)表是這樣的:
          SalesRep Customer OrderNo Amount
          1      1     5    100
          1      1     2    50
          1      2     3    200
          1       2     6    75
          2      1     1    10
          2      3     4    200
            如果要按SalesRep字段分組,并且指定其中的第一級,程序代碼應(yīng)當(dāng)這樣寫:
          Agg.Expression := 'Sum(Amount)';
          Agg.IndexName := 'SalesCust';
          Agg.GroupingLevel := 1;
          Agg.AggregateName := 'Total for Rep';
          11.4.3 怎樣獲取統(tǒng)計(jì)值
            要獲取統(tǒng)計(jì)值,可以調(diào)用TAggregate對象的Value函數(shù)。如果統(tǒng)計(jì)值是基于數(shù)據(jù)集中所有的記錄計(jì)算出來的,隨時(shí)可以調(diào)用Value函數(shù)。如果統(tǒng)計(jì)值是基于分組計(jì)算出來的,必須保證當(dāng)前記錄正好位于該分組內(nèi)。因此,在調(diào)用Value之前,最好先調(diào)用GetGroupState函數(shù)看看當(dāng)前記錄是否位于該分組內(nèi)。
            要在數(shù)據(jù)控件中顯示統(tǒng)計(jì)值,必須事先在字段編輯器中創(chuàng)建一個(gè)永久字段對象,該字段的類型必須是Aggregate。
          11.5 數(shù) 據(jù) 包
            通過Data屬性可以訪問客戶程序從應(yīng)用服務(wù)器檢索到的數(shù)據(jù)。程序示例如下:
          Procedure TForm1.Button1Click(Sender: TObject);
          Begin
          ClientDataSet1.Data := ClientDataSet1.Provider.DataRequest(FilterEdit.Text);
          End;
          11.5.1 直接對Data屬性賦值
            前面講過,客戶程序既可以通過IProvider接口獲取數(shù)據(jù),也可以從另一個(gè)數(shù)據(jù)集獲取數(shù)據(jù),后者就是通過Data屬性賦值的。程序示例如下:
            ClientDataSet1.Data := ClientDataSet2.Data;
            一旦Data被賦值,就可以用標(biāo)準(zhǔn)的數(shù)據(jù)控件顯示這些數(shù)據(jù)。
            注意:當(dāng)從另一個(gè)數(shù)據(jù)集獲取數(shù)據(jù)時(shí),另一個(gè)數(shù)據(jù)集的日志也將被復(fù)制過來,但不包括原來的范圍和過濾條件。
            如果要從另一個(gè)基于BDE的數(shù)據(jù)集中獲取數(shù)據(jù),可以通過數(shù)據(jù)集構(gòu)件的Provider屬性,程序示例如下:
            ClientDataSet1.Data := Table1.Provider.Data;
            如果要從一個(gè)自定義的數(shù)據(jù)集獲取數(shù)據(jù),首先要創(chuàng)建一個(gè)臨時(shí)的TProvider構(gòu)件,然后設(shè)置其DataSet屬性指定這個(gè)自定義的數(shù)據(jù)集。程序示例如下:
          TempProvider := TDataSetProvider.Create(Form1);
          TempProvider.DataSet := SourceDataSet;
          ClientDataSet1.Data := TempProvider.Data;
          TempProvider.Free;
          11.5.2 在數(shù)據(jù)包中加入自定義的信息
            可以把自定義的信息加到數(shù)據(jù)包中。當(dāng)把數(shù)據(jù)保存到文件或流中時(shí),這些自定義的信息也將保存到文件或流中。如果把數(shù)據(jù)包直接賦值給另一個(gè)數(shù)據(jù)集的話,這些自定義的信息也將被復(fù)制。
            要把自定義的信息加到數(shù)據(jù)包中,可以調(diào)用SetOptionalParam函數(shù)。要從數(shù)據(jù)包中檢索自定義的信息,可以調(diào)用GetOptionalParam。程序示例如下:
          Procedure TAppServer.Provider1UpdateData(Sender: TObject; DataSet: TClientDataSet);
          var
          WhenProvided: TDateTime;
          Begin
          WhenProvided := DataSet.GetOptionalParam('TimeProvided');
          ...
          End;
          11.5.3 克隆另一個(gè)數(shù)據(jù)集
            調(diào)用TClientDataSet的CloneCursor函數(shù)可以獲得一個(gè)數(shù)據(jù)集的完全相同的副本。它與直接通過Data屬性賦值是有區(qū)別的。
            區(qū)別之一:數(shù)據(jù)在兩個(gè)數(shù)據(jù)集之間是共享的,修改其中一個(gè)將同時(shí)修改另一個(gè)。
            區(qū)別之二:除了數(shù)據(jù)外,CloneCursor函數(shù)還復(fù)制了一些屬性和事件,這取決于Reset和KeepSettings參數(shù)怎樣設(shè)置。
             CloneCursor函數(shù)需要傳遞三個(gè)參數(shù),其中,Source參數(shù)指定源數(shù)據(jù)集,Reset參數(shù)和KeepSettings參數(shù)用于設(shè)置除了數(shù)據(jù)外是否還要復(fù)制下列屬性和事件:Filter、Filtered、FilterOptions、OnFilterRecord、IndexName、MasterSource、MasterFields、ReadOnly、RemoteServer、ProviderName、Provider。
            如果Reset和KeepSettings參數(shù)都設(shè)為False,源數(shù)據(jù)集的上述屬性和事件都將被復(fù)制給目標(biāo)數(shù)據(jù)集。如果Reset參數(shù)設(shè)為True,目標(biāo)數(shù)據(jù)集的上述屬性和事件都將被清空。如果Reset參數(shù)設(shè)為False,而KeepSettings參數(shù)設(shè)為True,目標(biāo)數(shù)據(jù)集的上述屬性和事件不變,不過,必須保證這些屬性和事件與克隆后的數(shù)據(jù)相容。
          11.6 與應(yīng)用服務(wù)器通訊
            在多層體系結(jié)構(gòu)中,客戶程序通過IProvider接口與應(yīng)用服務(wù)器交換數(shù)據(jù)。這一章介紹怎樣在客戶端獲得IProvider接口、怎樣向應(yīng)用服務(wù)器傳遞參數(shù)、怎樣向應(yīng)用服務(wù)器請求數(shù)據(jù)、怎樣把用戶對數(shù)據(jù)的修改寫到數(shù)據(jù)庫中。
          11.6.1 怎樣在客戶端獲得IProvider接口
            在單層應(yīng)用程序以及工作在“公文包”模式下的多層應(yīng)用程序中,不需要用到IProvider接口。而在多層體系結(jié)構(gòu)中,客戶程序要與應(yīng)用服務(wù)器交換數(shù)據(jù),首先必須獲得IProvider接口,這就要用到RemoteServer屬性和ProviderName屬性。
            RemoteServer屬性用于指定客戶端的MIDAS連接構(gòu)件。MIDAS連接構(gòu)件又稱Data Broker,用于建立和維護(hù)與應(yīng)用服務(wù)器的連接。
            在設(shè)計(jì)期,正確設(shè)置了RemoteServer屬性后,就可以在對象觀察器中為ProviderName屬性選擇一個(gè)值,實(shí)際上就是選擇應(yīng)用服務(wù)器上的一個(gè)TProvider構(gòu)件。
          11.6.2 向應(yīng)用服務(wù)器傳遞參數(shù)
            客戶程序可以向應(yīng)用服務(wù)器傳遞參數(shù),這些參數(shù)實(shí)際上是傳遞給應(yīng)用服務(wù)器上的TQuery構(gòu)件或TStoredProc構(gòu)件。既可以在設(shè)計(jì)期也可以在運(yùn)行期設(shè)置參數(shù)。
            在設(shè)計(jì)期,可以單擊Params屬性邊上的省略號按鈕,打開一個(gè)如圖11.2所示的編輯器。
            圖11.2 設(shè)置參數(shù)
            單擊按鈕可以增加一個(gè)參數(shù),單擊按鈕可以刪減一個(gè)參數(shù),單擊按鈕可以把一個(gè)參數(shù)前移,單擊按鈕可以把一個(gè)參數(shù)后移。
            選擇一個(gè)參數(shù),對象觀察器將顯示該參數(shù)(TParam對象)的屬性。
            在運(yùn)行期可以調(diào)用TParams的CreateParam函數(shù)來創(chuàng)建一個(gè)參數(shù)。例如,下面的代碼創(chuàng)建了一個(gè)參數(shù)叫CustNo,它的使用類型是ptInput,數(shù)據(jù)類型是ftInteger,它的值設(shè)為605。
          With ClientDataSet1.Params.CreateParam(ftInteger, 'CustNo', ptInput) Do
          AsInteger := 605;
            設(shè)置好參數(shù)以后,如果TClientDataset的Active屬性是False,只要把Active屬性設(shè)為True,這些參數(shù)將被自動傳遞給應(yīng)用服務(wù)器。如果Active屬性已經(jīng)為True,就要調(diào)用SendParams函數(shù)把參數(shù)傳遞給應(yīng)用服務(wù)器。
            注意:傳遞給應(yīng)用服務(wù)器的參數(shù)必須與TQuery構(gòu)件或TStoredProc構(gòu)件的參數(shù)匹配,包括名稱、數(shù)據(jù)類型和參數(shù)類型。
          11.6.3 怎樣向應(yīng)用服務(wù)器請求數(shù)據(jù)
            TClientDataSet提供了兩個(gè)屬性和三個(gè)方法,用于怎樣向應(yīng)用服務(wù)器請求數(shù)據(jù):
            一是FetchOnDemand屬性。如果這個(gè)屬性設(shè)為True,TClientDataSet會根據(jù)需要自動檢索附加的數(shù)據(jù)包,例如BLOB字段的值或者嵌套表的內(nèi)容。如果這個(gè)屬性設(shè)為False,程序需要顯式地調(diào)用GetNextPacket才能獲得這些附加的數(shù)據(jù)包。
            二是PacketRecords屬性,用于設(shè)置一個(gè)數(shù)據(jù)包中最多可容納的記錄數(shù),設(shè)為-1表示一個(gè)數(shù)據(jù)包可以容納數(shù)據(jù)集的所有記錄。
            三是GetNextPacket函數(shù),用于向應(yīng)用服務(wù)器檢索下一個(gè)數(shù)據(jù)包,并把檢索到的數(shù)據(jù)包添加到前一次檢索到的數(shù)據(jù)包的后面。這個(gè)函數(shù)返回實(shí)際檢索到的記錄數(shù)。
            四是FetchBlobs過程,用于從應(yīng)用服務(wù)器檢索BLOB字段的值。如果FetchOnDemand屬性設(shè)為True,就沒必要調(diào)用FetchBlobs函數(shù)。
            五是FetchDetails過程,用于檢索嵌套表中的數(shù)據(jù)。如果FetchOnDemand屬性設(shè)為True,就沒必要調(diào)用FetchDetails函數(shù)。
          11.6.4 更新數(shù)據(jù)庫
            在多層體系結(jié)構(gòu)中,用戶在客戶端修改了數(shù)據(jù)后,需要把最新的數(shù)據(jù)寫到數(shù)據(jù)庫中,這就要調(diào)用TClientDataSet的ApplyUpdates函數(shù)。
            ApplyUpdates只需要傳遞一個(gè)參數(shù)叫MaxErrors,用于指定一個(gè)整數(shù),當(dāng)遇到無法更新的記錄超過這個(gè)數(shù)時(shí),此次更新就中止。如果MaxErrors參數(shù)設(shè)為0,表示只要遇到一個(gè)錯誤更新就中止,客戶端的日志保持不變。如果MaxErrors參數(shù)設(shè)為-1,當(dāng)應(yīng)用服務(wù)器發(fā)現(xiàn)有錯誤的記錄,就嘗試更新下一個(gè)記錄,等所有的記錄都嘗試過以后才返回。
            ApplyUpdates會自動調(diào)用Reconcile函數(shù),進(jìn)而調(diào)用應(yīng)用服務(wù)器上的TProvider構(gòu)件的ApplyUpdates函數(shù)去更新遠(yuǎn)程的數(shù)據(jù)庫服務(wù)器。沒有被DBMS服務(wù)器認(rèn)可的記錄通過Reconcile返回給客戶端,此時(shí)將在客戶端觸發(fā)OnReconcileError事件讓您更正錯誤。最后,ApplyUpdates函數(shù)返回仍然沒有被認(rèn)可的記錄數(shù)。
          11.7 在文件中存取數(shù)據(jù)
            要從文件中讀取數(shù)據(jù),可以調(diào)用LoadFromFile函數(shù)。LoadFromFile函數(shù)需要傳遞一個(gè)參數(shù),用于指定文件名。文件名應(yīng)包含完整的路徑。如果客戶程序總是從一個(gè)固定的文件中讀取數(shù)據(jù),可以設(shè)置FileName屬性指定一個(gè)文件名,以后,當(dāng)TClientDataSet引入的數(shù)據(jù)集打開時(shí),就自動從這個(gè)文件中讀取數(shù)據(jù),不需要調(diào)用LoadFromFile。
            要從流中讀取數(shù)據(jù),可以調(diào)用LoadFromStream。LoadFromStream需要傳遞一個(gè)參數(shù),用于指定一個(gè)流對象。
            注意:LoadFromFile(LoadFromStream)只能從先前用SaveToFile(SaveToStream)保存的文件中讀取數(shù)據(jù)。
            要把數(shù)據(jù)保存到文件中,可以調(diào)用SaveToFile函數(shù)。SaveToFile需要傳遞一個(gè)參數(shù),用于指定文件名。如果指定的文件已存在,文件中的數(shù)據(jù)將被覆蓋。如果客戶程序總是把數(shù)據(jù)保存到一個(gè)固定的文件中,可以設(shè)置FileName屬性指定一個(gè)文件名,當(dāng)TClientDataSet引入的數(shù)據(jù)集關(guān)閉時(shí),就自動把數(shù)據(jù)保存到這個(gè)文件中,不需要調(diào)用SaveToFile。
            要把數(shù)據(jù)保存到流中,可以調(diào)用SaveToStream。SaveToStream需要傳遞一個(gè)參數(shù),指定一個(gè)流對象。
            注意:當(dāng)把數(shù)據(jù)保存到文件或流中時(shí),日志中記載的修改仍然保留。這樣,當(dāng)下次調(diào)用LoadFromFile或LoadFromStream讀取數(shù)據(jù)時(shí),仍然可以恢復(fù)原來的數(shù)據(jù)。
          posted @ 2007-03-29 05:57 konhon 優(yōu)華 閱讀(1649) | 評論 (0)編輯 收藏

          ? 近日(呵呵,這篇文章是去年寫的)用了兩個(gè)月開發(fā)了一個(gè)物流信息系統(tǒng),這個(gè)系統(tǒng)是兩層、三層相結(jié)合,C/SB/S相結(jié)合的系統(tǒng)。雖然限于時(shí)間的緊張和人手的原因,系統(tǒng)規(guī)模不是很大,但是其中涉及的技術(shù)卻很全面。在這個(gè)《開發(fā)技術(shù)篇》中我們將講解我在開發(fā)系統(tǒng)中遇到的技術(shù)問題及解決方案,希望對大家有幫助。對于物流信息系統(tǒng)的分析設(shè)計(jì)問題,我將在另一篇文章《物流信息系統(tǒng)開發(fā)手記――系統(tǒng)構(gòu)架篇》中講解。

          ?

          一、Midas的安全問題。

          ??? Midas技術(shù)是Delphi中進(jìn)行三層開發(fā)的首選技術(shù),它不僅有純DCOM/COM+(COM+技術(shù)是.NET技術(shù)的基礎(chǔ))的優(yōu)點(diǎn),而且也結(jié)合了Delphi的快速開發(fā)特性,可以快速開發(fā)出想要的系統(tǒng),其開發(fā)速度是用VC,PB等開發(fā)DCOM的數(shù)十倍,把程序員從煩雜的代碼中解脫出來,從而將更多的精力投入到業(yè)務(wù)邏輯的設(shè)計(jì)中去。

          ??? 但是Midas技術(shù)的一個(gè)最令人擔(dān)憂的就是它的安全問題:

          遠(yuǎn)端只要知道應(yīng)用服務(wù)器的端口號即可訪問到應(yīng)用服務(wù)器,而一旦訪問到應(yīng)用服務(wù)器,TClientDataSet即可獲得ProviderNames列表。一旦知道了ProviderNames列表,這就相當(dāng)于將數(shù)據(jù)庫暴露在外了。

          關(guān)于可輕易獲得ProviderNames列表的問題,我使用下面的方法解決:

          ?在服務(wù)器端定義一個(gè)

          LoginMTS(const AUserId, APassword: WideString): WordBool;

          方法。初始狀態(tài)下,所有的DataSetProvider和數(shù)據(jù)集的連接斷開。用戶必須調(diào)用LoginMTS并傳遞用戶名和密碼,登陸成功才將DataSetProvider和數(shù)據(jù)集的連接打開。這樣如果用戶驗(yàn)證沒有通過,即使它獲得了ProviderNames列表也沒法調(diào)用接口中的方法對數(shù)據(jù)庫進(jìn)行操作。

          二、Midas中主從表的實(shí)現(xiàn)

          主從表的應(yīng)用在信息系統(tǒng)中應(yīng)用很廣。在兩層開發(fā)中我們可以通過直接建立兩個(gè)數(shù)據(jù)集之間為主從關(guān)系來實(shí)現(xiàn)主從表;在三層中雖然我們?nèi)匀豢梢酝ㄟ^直接建立兩個(gè)數(shù)據(jù)集之間為主從關(guān)系來實(shí)現(xiàn)主從表,但是這樣就要求把數(shù)據(jù)庫中所有相關(guān)的數(shù)據(jù)行都下載到本地,喪失了三層開發(fā)的優(yōu)勢。我在實(shí)際中使用下面的方法實(shí)現(xiàn)。這里我以實(shí)現(xiàn)入庫單查詢、添加、修改、刪除(CRUD)為例來講解:

          1)新建一個(gè)MTS Data Module,命名為TmtsStockInListBiz,增加如下方法:

          ??? function QueryStockInListMasterById(const AId: WideString;

          ????? var ADatas: OleVariant): WordBool; safecall;

          ??? function QueryStockInListSlaveByMasterId(const AId: WideString;

          ????? var ADatas: OleVariant): WordBool; safecall;

          ??? procedure UpdataStockInListMaster(var ADatas: OleVariant); safecall;

          ??? procedure UpdataStockInListSlave(var ADatas: OleVariant); safecall;

          ??? function GenerateStockInListId: WideString; safecall;

          ?

          QueryStockInListMasterById作用是根據(jù)入庫單單號查詢?nèi)霂靻蔚幕拘畔ⅲㄈ霂烊掌凇⒇?fù)責(zé)人等),Aid為入庫單單號,Adatas為返回值,其格式就是Midas的數(shù)據(jù)包,可以將其附給ClientDatSetData屬性。

          QueryStockInListSlaveByMasterId作用是根據(jù)入庫單單號查詢?nèi)霂靻蔚脑敿?xì)信息(商品條碼,數(shù)量)

          UpdataStockInListMaster是對入庫單主表進(jìn)行刪除、添加、修改操作。只要將ClientDataSetDelta屬性做為傳遞即可。

          UpdataStockInListSlave是對入庫單從表進(jìn)行刪除、添加、修改操作。

          GenerateStockInListId是產(chǎn)生一個(gè)唯一的入庫單號。

          下面是幾個(gè)方法的代碼,都很簡單,就不多解釋了,可以查看Delphi的幫助。

          function TmtsStockInListBiz.QueryStockInListMasterById(

          ? const AId: WideString; var ADatas: OleVariant): WordBool;

          begin

          ? result := false;

          ? ADatas := null;

          ? try

          ??? cdsQuery.Close;

          ??? cdsQuery.CommandText := 'select * from t_StockInListMaster where Id=:Id';

          ??? cdsQuery.Params.ParamByName('Id').AsString := AId;

          ??? cdsQuery.Open;

          ??? if cdsQuery.RecordCount > 0 then

          ??? begin

          ????? result := true;

          ????? ADatas := cdsQuery.Data;

          ??? end;

          ? finally

          ??? cdsQuery.Close;

          ? end;

          end;

          ?

          procedure TmtsStockInListBiz.UpdataStockInListMaster(

          ? var ADatas: OleVariant);

          var

          ? eCount: Integer;

          ? OwnerData: OleVariant;

          begin

          ? DCOMConStockInList.GetServer.AS_ApplyUpdates('dspStockInListMaster',

          ??? ADatas, -1, eCount, OwnerData);

          end;

          ?

          function TmtsStockInListBiz.GenerateStockInListId: WideString;

          var

          ? LPrior: string;

          ? i: Integer;

          begin

          ? cdsQuery.Close;

          ? cdsQuery.CommandText := 'select top 1 id from t_StockInListMaster order by id desc';

          ? cdsQuery.Open;

          ? LPrior := cdsQuery.FieldByName('Id').AsString;

          ? i := StrToIntDef(RightStr(LPrior,8),0);

          ? Inc(i);

          ? result := 'RK' + FormatFloat('00000000',i);

          ? cdsQuery.Close;

          end;

          ?

          2)、新建一個(gè)應(yīng)用程序,通過DCOMConnectionSocketConnection等連接到MTS組件,然后就可以調(diào)用MTS的相應(yīng)的方法實(shí)現(xiàn)客戶端功能了。

          放入cdsStockInListMastercdsStockInListSlave兩個(gè)ClientDataSet控件,在控件上點(diǎn)擊右鍵,選擇“FieldsEditor”新建于服務(wù)器中的字段同樣的字段,然后再次在控件上單擊右鍵,選擇“CreateDataSet”,建立一個(gè)本地?cái)?shù)據(jù)庫。

          3

          根據(jù)入庫單號查詢?nèi)霂靻蔚姆椒▽?shí)現(xiàn):

          procedure TFormStockInList.BtnFindClick(Sender: TObject);

          var

          ? v,vs: OleVariant;

          begin

          ? if SocketConStockInList.AppServer.QueryStockInListMasterById(Trim(LEdtId.Text), v) then

          ? begin

          ??? cdsStockInListMaster.Data := v;//顯示入庫單主表(主要信息)

          ?

          ??? if SocketConStockInList.AppServer.QueryStockInListSlaveByMasterId(Trim(LEdtId.Text), vs) then

          ????? cdsStockInListSlave.Data := vs; ;//顯示入庫單從表(明細(xì)信息)

          ? end

          ? else

          ??? ShowMessage('此單不存在!');

          end;

          4)新建入庫單的實(shí)現(xiàn)

          procedure TFormStockInList.BtnNewClick(Sender: TObject);

          var

          ? LId: string;

          begin

          ? ClearCDSRecord;

          ? cdsStockInListMaster.Open;

          ? cdsStockInListMaster.Insert;

          ? LId := SocketConStockInList.AppServer.GenerateStockInListId;

          ? LEdtId.Text := LId;

          ? cdsStockInListMaster.FieldByName('Id').AsString := LId;

          ? cdsStockInListMaster.FieldByName('GenerateDate').AsDateTime := Now();

          end;

          5)提交功能的實(shí)現(xiàn)

          procedure TFormStockInList.BtnPostClick(Sender: TObject);

          var

          ? LQuerymts: ImtsQueryObjDisp;

          ? LBar: string;

          begin

          ? SetSocketConnectionConnect(SocketConQuery);

          ? LQuerymts := ImtsQueryObjDisp(SocketConQuery.GetServer);

          ?

          ? SocketConQuery.Close;

          ?

          ? if cdsStockInListMaster.RecordCount > 0 then

          ??? SocketConStockInList.AppServer.UpdataStockInListMaster(cdsStockInListMaster.Delta);

          ? if cdsStockInListSlave.RecordCount > 0 then

          ? SocketConStockInList.AppServer.UpdataStockInListSlave(cdsStockInListSlave.Delta);

          end;

          注:本文中ClientDataSet控件的名稱開頭一般為cdsTsocketConnection控件的名稱開頭一般為SocketCon

          三、動態(tài)設(shè)置TsimpleObjectBroker的服務(wù)器列表

          procedure SetSocketConnectionConnect(AValue: TSocketConnection);

          ? procedure FillAppServerList(ABroker: TSimpleObjectBroker);

          ? var

          ??? sl: TStringList;

          ??? i, n: Integer;

          ? begin

          ??? sl := TStringList.Create;

          ??? 從配置文件中讀取服務(wù)器列表,并保存到sl;

          ??? n := sl.Count - 1;

          ??? ABroker.ServerData := null;

          ??? for i := 0 to n do

          ??? begin

          ????? ABroker.Servers.Add;

          ????? ABroker.Servers[i].ComputerName := sl.Strings[i]

          ?? ?end;

          ??? sl.Free;

          ? end;

          var

          ? LBroker: TSimpleObjectBroker;

          begin

          ? LBroker := TSimpleObjectBroker.Create(nil);

          ??? FillAppServerList(LBroker);

          ??? AValue.ObjectBroker := LBroker;

          ??? try

          ????? AValue.Connected := true;

          ??? except

          ????? raise Exception.Create('應(yīng)用服務(wù)器連接錯誤!');

          ??? end;

          ??? LBroker.Free;

          end;

          posted @ 2007-03-28 05:07 konhon 優(yōu)華 閱讀(2580) | 評論 (0)編輯 收藏


            因?yàn)樾枰幚泶罅康囊簟⒁曨l數(shù)據(jù),所以一套強(qiáng)有力的計(jì)算機(jī)系統(tǒng)及外圍硬件配置是必要的。另外,由于我們要直接輸出的是高質(zhì)量的MPG文件(而非體積龐大的AVI文件),因此,強(qiáng)烈建議使用視頻壓縮卡進(jìn)行硬件高速壓縮,本文以較常見的MPEGator 3.1壓縮卡為例,介紹通過Premiere利用壓縮卡直接輸出MPG的辦法:

            1、制作VCD電子相冊應(yīng)使用怎樣的系統(tǒng)配置?

            答:推薦的系統(tǒng)配置如下---

            CPU: PIII 500E以上

            內(nèi)存: 256M SDRAM或更大

            硬盤: 20G高速

            壓縮卡:MPEGator 3.1 刻錄機(jī):所有能被Video Pack 4.0所支持的型號

            操作系統(tǒng):Windows 95 OSR2或Windows 98 制作軟件:Adobe Premiere 5.0/4.2、Video Pack 4.0

            輔助軟件:Paint shop Pro 6.0、ACDsee3.0、Audio Grabber 1.61 以上推薦的系統(tǒng)配置中,我們主要是采用了著名的視頻編輯軟件Adobe Premiere 5.0與性能價(jià)格比較高的MPEGator 3.0壓縮卡配合制作VCD相冊。為什么要采用這樣的配合呢?還是先讓我們來了解一下它們各自的特性吧:

            2、為什么推薦使用Premiere 5.0數(shù)字影視編輯軟件?

            答:Adobe Premiere 5.0是圖形圖像軟件巨人---Adobe公司繼廣受稱贊的Premiere 4.2后,推出的新一代桌面數(shù)字影視編輯系統(tǒng)。它具有比Premiere 4.2更為強(qiáng)大的圖像編輯能力,通過把動畫、位圖、數(shù)字音頻文件按照需要進(jìn)行剪輯、組合,讓你可以設(shè)計(jì)出近乎隨心所欲的影視特效;在專為編輯影像片段而設(shè)計(jì)的Timeline里,利用鼠標(biāo)就可完成所有的編輯操作;它的即時(shí)播放功能還使我們在發(fā)生編輯錯誤時(shí),能夠輕松地進(jìn)行修改,以節(jié)省時(shí)間與精力。更重要的是,Premiere 5.0可以提供高品質(zhì)影像輸出質(zhì)量!這一點(diǎn)著實(shí)令人心動。此外,它還支持制作輸出有聲有色的VCD電子相冊呢。

            3、為什么推薦使用MPEGator壓縮卡?

            答:壓縮卡方面,韓國DARIM公司生產(chǎn)的MPEGator壓縮卡(圖02)可謂是具有較高性能價(jià)格比的視頻壓縮卡:不僅帶有S-video、復(fù)合、及立體聲音頻輸入接口,可以通過攝像機(jī)、錄像機(jī)、電視及激光唱機(jī)等信號源將視頻信號實(shí)時(shí)壓縮成全I(xiàn).P.B幀的標(biāo)準(zhǔn)MPEG-1格式;還支持實(shí)時(shí)預(yù)覽。最為重要的是MPEGator卡可以使流行的視頻編輯軟件通過硬件加速轉(zhuǎn)換成為MPEG-1格式。  MPEGator可與Windows的其它應(yīng)用程序配合產(chǎn) PEG文件,3D Studio, Adobe Premiere等各種兼容Video for Window的流行的編輯軟件都可以在生成動畫或AVI之前,直接選用其壓縮驅(qū)動程序,通過硬件加速壓縮生成為MPEG文件,有效地避免了因AVI—→MPG而導(dǎo)致的畫質(zhì)下降這一難題。另外,MPEGator還具有PAL/NTSC制式兼容,PCI32位總線等特點(diǎn)。通過以上介紹,可以看出:利用這樣的軟硬件組合,我們將能夠制作出效果比較令人滿意的多媒體VCD相冊。下面,就讓我們開始實(shí)戰(zhàn)VCD相冊的制作吧。

            4.制作VCD相冊之前,為什么要擬定提綱?

            答:制作VCD相冊之前,首先應(yīng)對所制作的作品的各個(gè)方面做到心中有數(shù)。最好列個(gè)制作提綱,列出主題及各相對獨(dú)立片段的次序,以及每個(gè)片段內(nèi)的照片、音樂、旁白;將每張照片分別編上序號,并將其序號與欲添加的說明文字對應(yīng)起來。這樣,在實(shí)際制作的時(shí)候就條理清晰、步驟分明,不易出現(xiàn)錯漏等現(xiàn)象。

            5.怎樣進(jìn)行照片的掃描?

            答:選取一張淺色紋理紙,將其裁剪成寬155mm、高127mm(即352:288)大小的矩形模板。用雙面膠將照片粘于其上(注意居中,并使底邊高度略大于頂邊),放入掃描儀進(jìn)行掃描,并以位圖(.bmp)形式存盤。此舉好處之一是使掃出的照片具有一個(gè)漂亮的彩色相框;另一個(gè)好處是可以將添加的說明文字放在相框上,而不是照片內(nèi),不會破壞照片的美感(圖07)。?


            6. 如何為照片添加說明文字?

            進(jìn)入Paint Shop Pro 5.0,選擇File——open打開一幅已掃好的照片,點(diǎn)擊左側(cè)工具欄中的“A”鍵,接著將鼠標(biāo)移至照片內(nèi)并單擊左鍵,在彈出的“Add Text”文字輸入框中輸入想要的文字,再選定字體、字號及顏色,確定文字位置后點(diǎn)擊“OK”,并將編輯后的照片以原文件名存盤。

           7.如何截取音軌?

            答:啟動音軌截取軟件AudioGrabber,將音樂CD放入光驅(qū),勾選想要截取的CD音軌。

            點(diǎn)擊控制欄中的“Settings”按鍵后勾選其中的“ASPI”項(xiàng),其它選項(xiàng)用默認(rèn)值即可。然后,進(jìn)入“Norm”選項(xiàng),選擇“Use normalizing”后點(diǎn)擊“OK”退出。現(xiàn)在,先用鼠標(biāo)點(diǎn)擊一下工具欄里那標(biāo)有伸開手掌的“截取”(Grab)鈕,就可以開始抓取指定的音軌了。如果截獲的.WAV文件不能被正常讀取或者.WAV文件中有令人討厭的“爆音”(pops,這是令許多朋友頭痛的問題)。請?jiān)凇伴_始—設(shè)置—控制面板—系統(tǒng)—設(shè)備管理—CDROM—屬性—設(shè)置—選項(xiàng)”中將“同步數(shù)據(jù)傳送”選中,然后按“確定”退出。再重新去試截取剛才有問題的音軌,您可能會發(fā)現(xiàn),問題已經(jīng)迎刃而解了。其次,若覺得光驅(qū)讀取音樂數(shù)據(jù)的速度很緩慢,請先檢查光驅(qū)上數(shù)據(jù)線是否直接接到了主板的IDE接口上。

            為了方便管理和使用,可新建Photo、Audio、Wav三個(gè)子目錄,分別用于存放照片、音樂及旁白。

            準(zhǔn)備工作完成后,就可以開始著手制作了。為了工作得更有條理,我們一般先對每一個(gè)相對獨(dú)立的片段進(jìn)行編輯制作,最后再把它們連成整體。

            8.如何設(shè)置才能讓Premier5.0利用MPEGator來進(jìn)行高效硬件壓縮?

            答:首先啟動Premiere5.0。在彈出的New Project setting窗口,選擇General settings,在“編輯模式”里選“Video for window”,其下的兩個(gè)選項(xiàng)均選“25”(因?yàn)槲覀円谱鞯氖荘AL制式的VCD);然后進(jìn)Video settings,在“壓縮器(Compressor)”這一項(xiàng)中選“DVMPEG Video (hardware)”(圖08),即選用硬件壓縮;分辨率設(shè)為352*288,幀率設(shè)為25;在Audio settings里,關(guān)鍵是在“Type(類型)”中選擇“DVMPEG Audio”---指定用硬件進(jìn)行音頻壓縮;采樣頻率設(shè)為44.1KHZ,格式設(shè)為16bit--Stereo。


            9.Premiere 5.0的主界面的結(jié)構(gòu)如何?

            答:進(jìn)入Premiere 5.0的主界面,我們會發(fā)現(xiàn)設(shè)計(jì)新穎的時(shí)間軸窗口(Timeline)已取代了其4.2版本中的Constraction窗口。作為Premiere 5.0的核心,Timeline的用戶窗口分為兩個(gè)部份:視頻部分和音頻部分;其中視頻部份又分為兩個(gè)主視頻剪輯軌道——Video 2和Video 1。其中,標(biāo)成黑體字的Video 1部份又內(nèi)含兩個(gè)視頻剪輯軌道:Video 1A和Video 1B,它們之間的Transition軌道是視頻切換效果軌道。Premiere 5.0提供了非常豐富的視頻切換效果,包括滑動、擦除、融合、剝落、分割、爆破、漸變、突變、三維旋轉(zhuǎn)、翻頁、推動等多種劃變效果,令人目不暇接。音頻軌道Audio 1、2、3則用于放置背景音樂、配音、旁白等聲音信號。  

            10.如何導(dǎo)入圖片及配音文件?

            答:點(diǎn)擊“File--Import--Folder”,把剛才準(zhǔn)備好的圖片文件及背景音樂文件輸入進(jìn)來,在Project窗口下雙擊剛才輸入的文件夾,可以看到文件夾中的各文件的具體信息,雙擊該文件則可對其進(jìn)行預(yù)覽。  

            11.如何設(shè)置照片的參數(shù)?

            答:將第一幅照片拖到視頻剪輯軌道Video 1A中,對其點(diǎn)擊鼠標(biāo)右鍵,在彈出的菜單中的Duration項(xiàng)里設(shè)定照片的播放時(shí)間;并在菜單中的Video項(xiàng)里將Maintain Aspect Retio選中(圖09)——請注意,這是非常重要的一步,此項(xiàng)設(shè)置將使最后輸出的照片保持原本的長寬比例,而不致于使照片上的人像、景物發(fā)生變形。按上述方法將照片依次拖入Video1的A、B欄,(注意每幅照片的尾與下一幅照片首應(yīng)留有重疊部份,重疊部份的時(shí)間長短依實(shí)際需要而定。把背景音樂、旁白拖入Audio欄)。如果是旁白,應(yīng)特別注意旁白的時(shí)間長度應(yīng)與相應(yīng)照片的播放時(shí)間相當(dāng)。然后,用鼠標(biāo)把Timeline窗戶上方的淺藍(lán)色橫杠拉至最后一張照片的末端,以設(shè)定Premiere將進(jìn)行處理的視頻片段的長度。


            12. 如何設(shè)定視頻切換特效?

            答:Premiere 5.0用戶界面上,有一個(gè)Transition/Command命令窗口,其中共有75種切換特效可供選擇。而且,其中大多數(shù)切換特效都可按自己的需要進(jìn)行設(shè)置。將選中的特效用鼠標(biāo)拖到Video 1窗口的Transition中兩幅照片相重疊的部分,其長度應(yīng)為兩幅照片相重疊的長度。如果能根據(jù)每幅照片的特點(diǎn)恰當(dāng)?shù)剡x擇Transitions,將使您的VCD相冊在播放時(shí)贏得更多的贊嘆之聲。  

            13. 如何處理背景音樂?

            答:為VCD相冊添加優(yōu)美的背景音樂,也將使你的VCD相冊平添許多迷人的魅力。然而,因?yàn)楸尘耙魳肥俏覀儾捎米ヒ糗壍姆绞将@得的,這樣就不可避免地在VCD相冊一開始播放時(shí)就出現(xiàn)突兀而至的音樂聲。此外,由于音軌的長度與照片播放時(shí)間的長度往往難以很好的吻合。這樣,就可能出現(xiàn)一段VCD相冊的播放馬上就要結(jié)束,而音樂聲卻正處于高潮……。理想的狀況應(yīng)該是:照片播放時(shí),背景音樂逐漸輕柔地響起;照片播放即將結(jié)束時(shí),音樂聲又漸漸隨之淡去。換句話說,也就是要實(shí)現(xiàn)背景音樂的淡入淡出。在Premiere 5.0中,按前述方法裝入照片及背景音樂后,單擊第一音頻軌道(Audio 1)上的那個(gè)指向右的小三角,這時(shí)會彈出該音軌的波形顯示框。可以看到該框中部有一條左右各有一方形端點(diǎn)的紅線——這就是控制音樂淡入淡出的關(guān)鍵。將鼠標(biāo)移至紅線上,鼠標(biāo)指針將變?yōu)槭中?圖10)。此時(shí),按住鼠標(biāo)左鍵即可通過增加和拖動點(diǎn)子來隨意確定該紅線條形狀。從起始位置開始,將線條置于從左至右漸高狀態(tài)時(shí),即可實(shí)現(xiàn)背景音樂的淡入效果。用類似的方法還可制造音樂的淡出效果,在此不再贅述。有興趣的朋友盡可自行嘗試。?

            14. 如何設(shè)置輸出參數(shù)?

            答:輸出參數(shù)包含General、Audio、Video三項(xiàng),只有正確的設(shè)備了輸出參數(shù),VCD相冊才能在VCD機(jī)上順利播放。首先選Project--Setting進(jìn)入General設(shè)置:在“Editing Mode”里選“Video for window”,“Time display”及“Timebase”均選“25”;再進(jìn)入Video設(shè)置,“Compressor”選“DVMPEG Video(Hardware)”,尺寸設(shè)為352*288,幀率設(shè)為25;最后設(shè)置Audio參數(shù):采樣頻率設(shè)為44.1KHZ,格式設(shè)為16bit--Stereo(圖11);Type設(shè)成“DVMPEG Audio”。在這里,音頻及視頻均設(shè)置為硬件(MPEGator卡)加速壓縮。?


            15. 如何直接輸出MPG文件?

            答:上述參數(shù)設(shè)置完畢后,接著選File-Export-movie,將剛才組合好的照片,音樂,旁白等素材,通過MPEGator卡的硬件加速直接生成高質(zhì)量的MPG文件。我們知道,如果利用Xing MPEG Encoder等進(jìn)行純軟件壓縮,即使你的系統(tǒng)配置較高,其壓縮時(shí)間也將漫長得驚人:約為真實(shí)播放時(shí)間的10-20倍;而利用MPEGator卡進(jìn)行硬件壓縮的話,可就太節(jié)省時(shí)間了:壓縮時(shí)間僅為真實(shí)播放時(shí)間的3倍左右,大大提高了制作效率。需要注意的是,為了便于分類,應(yīng)把同一主題的內(nèi)容輸出生成一個(gè)獨(dú)立的MPG文件。

            16. 如何把電子相冊刻成VCD碟?

            前面所有辛苦的勞動,都將通過刻制成VCD碟片而變成勞動的果實(shí)。說到2.0 VCD刻錄,CeQuadrat出品的Video Pack 4.0因其較細(xì)致而周到的功能設(shè)計(jì),是一個(gè)在業(yè)余條件下不錯的選擇,其缺點(diǎn)是操作相對比較繁瑣。啟動Video Pack 4.0,將剛才壓縮好的各個(gè)MPG文件依次用鼠標(biāo)拖至位于主界面下方的工作框內(nèi),右鍵單擊MPG文件,在彈出的菜單選中Properties,在Playlist node中的第二個(gè)選項(xiàng)(即每一片段的等待時(shí)間)里把等待時(shí)間設(shè)為0秒,按“確定”退出。每個(gè)MPG文件都必須重復(fù)上述步驟,這樣可以使各獨(dú)立主題內(nèi)容切換時(shí)不至于出現(xiàn)停頓等待狀態(tài)。這時(shí)你也許發(fā)現(xiàn)了,剛才拖入工作框的各MPG文件方形圖標(biāo)上下均有一個(gè)三角形缺口。原來,在Video Pack 4.0中是用連線的方式來表示各種播放次序的,而這種三角形缺口,就是這些連線的出入口。將鼠標(biāo)指針移至MPG文件圖標(biāo)下方的缺口,圖標(biāo)里會出現(xiàn)黃顏色的“Next”字樣,此時(shí)即可開始進(jìn)行連線,方法是使各MPG文件按順序首尾相連(圖12)。上述步驟完成后,點(diǎn)擊工具欄中的紅色的“Make CD”鈕即可開始刻錄VCD光碟了。

            17. 把電子相冊刻成VCD碟的過程中要注意哪些事項(xiàng)?

            要是現(xiàn)在問你:自己刻制一張VCD相冊光盤困難嗎?你肯定會說:一點(diǎn)都不難!

            那么,是不是就像在硬盤上拷貝文件那么輕而易舉呢?決非如此簡單。VCD相冊刻錄前進(jìn)行些必要的準(zhǔn)備工作,將能大大提高我們的刻錄成功率:  

            a.刻錄前為什么要整理硬盤?

            答:我們通常都是以硬盤作為信息源盤來進(jìn)行刻錄的。由于未經(jīng)整理的磁盤文件大多呈零散狀態(tài)分布。這樣,硬盤在讀取數(shù)據(jù)時(shí),讀寫頭就只能在零散的文件之間來回奔忙,極有可能造成不必要的延誤而導(dǎo)致刻出廢盤。所以,每次刻錄前對硬盤的每一個(gè)邏輯分區(qū)進(jìn)行磁盤掃描和碎片整理。進(jìn)行硬盤整理是成功刻錄的第一步。  

            b.為什么刻錄過程中要避免執(zhí)行任何無關(guān)程序?

            答:這些程序不僅包括屏幕保護(hù)程序和內(nèi)存駐留程序(比如某些殺毒程序),這些程序都有可能在數(shù)據(jù)流從硬盤轉(zhuǎn)移到刻錄機(jī)中光盤上的緊要關(guān)頭,來與刻錄軟件爭奪有限的系統(tǒng)資源,從而影響數(shù)據(jù)流的正常傳輸而引發(fā)緩存器欠載等問題,導(dǎo)致刻盤失敗。

            c.為什么使用質(zhì)量可靠的CD-R盤片?

            答:CD-R空白盤片按反射層材料的不同可分綠盤、金盤、藍(lán)盤三大類。這三種盤片并沒有明顯的優(yōu)劣差別。從特性上來說,綠盤具有較好的兼容性,另外價(jià)格很便宜;藍(lán)盤在寫入和讀取數(shù)據(jù)時(shí)有較高的準(zhǔn)確性;金盤有較好的抗光性。關(guān)鍵的是,分別試刻不同類別和品牌的盤片,從中找出最適合你的刻錄機(jī)的那幾種。  

            至此,兩種不同類型的電子相冊的制作方法就介紹完畢,預(yù)祝你早日制作出自己的精美電子相冊!

          posted @ 2007-03-27 19:11 konhon 優(yōu)華 閱讀(1599) | 評論 (0)編輯 收藏

          首先,我們新建一個(gè)類,存放天氣信息

          /*
          ?*?Created?on?2005-3-8
          ?*
          ?*?To?change?the?template?for?this?generated?file?go?to
          ?*?Window&gt;Preferences&gt;Java&gt;Code?Generation&gt;Code?and?Comments
          ?
          */
          package ?org.exoplatform.portlets.chinaweather.component;

          /**
          ?*?
          @author ?Administrator
          ?*
          ?*?To?change?the?template?for?this?generated?type?comment?go?to
          ?*?Window&gt;Preferences&gt;Java&gt;Code?Generation&gt;Code?and?Comments
          ?
          */
          public ? class ?Weather?{
          ?
          private ?String?city;
          ?
          private ?String?state;
          ?
          private ?String?temperature;
          ?
          private ?String?time;
          ?
          private ?String?wind;
          ?
          private ?String?windpower;
          ?
          private ? long ?UpdateTime;

          ?
          /**
          ??*?
          @return
          ??
          */
          ?
          public ?String?getTemperature()?{
          ??
          return ?temperature;
          ?}

          ?
          /**
          ??*?
          @return
          ??
          */
          ?
          public ?String?getTime()?{
          ??
          return ?time;
          ?}

          ?
          /**
          ??*?
          @return
          ??
          */
          ?
          public ?String?getWind()?{
          ??
          return ?wind;
          ?}

          ?
          /**
          ??*?
          @return
          ??
          */
          ?
          public ?String?getWindpower()?{
          ??
          return ?windpower;
          ?}

          ?
          /**
          ??*?
          @param ?string
          ??
          */
          ?
          public ? void ?setTemperature(String?string)?{
          ??temperature?
          = ?string;
          ?}

          ?
          /**
          ??*?
          @param ?string
          ??
          */
          ?
          public ? void ?setTime(String?string)?{
          ??time?
          = ?string;
          ?}

          ?
          /**
          ??*?
          @param ?string
          ??
          */
          ?
          public ? void ?setWind(String?string)?{
          ??wind?
          = ?string;
          ?}

          ?
          /**
          ??*?
          @param ?string
          ??
          */
          ?
          public ? void ?setWindpower(String?string)?{
          ??windpower?
          = ?string;
          ?}

          ?
          /**
          ??*?
          @return
          ??
          */
          ?
          public ? long ?getUpdateTime()?{
          ??
          return ?UpdateTime;
          ?}

          ?
          /**
          ??*?
          @param ?l
          ??
          */
          ?
          public ? void ?setUpdateTime( long ?l)?{
          ??UpdateTime?
          = ?l;
          ?}

          ?
          /**
          ??*?
          @return
          ??
          */
          ?
          public ?String?getState()?{
          ??
          return ?state;
          ?}

          ?
          /**
          ??*?
          @param ?string
          ??
          */
          ?
          public ? void ?setState(String?string)?{
          ??state?
          = ?string;
          ?}

          ?
          /**
          ??*?
          @return
          ??
          */
          ?
          public ?String?getCity()?{
          ??
          return ?city;
          ?}

          ?
          /**
          ??*?
          @param ?string
          ??
          */
          ?
          public ? void ?setCity(String?string)?{
          ??city?
          = ?string;
          ?}

          }


          具體的解析代碼為:

          private ?Weather?parserWeather()? throws ?Exception?{
          ??Weather?w?
          = ? new ?Weather();
          ??
          try ?{

          ???
          // Parser?parser?=
          ???
          // ?new?Parser("file: // localhost/I:/projects/query.html");
          ???Parser?parser? =
          ????
          new ?Parser( " http://weather.news.sohu.com/query.php?city=鎮(zhèn)江 " );
          ???
          ???parser.setEncoding(
          " GBK " );
          ???Node?nodes[]?
          = ?parser.extractAllNodesThatAre(TableTag. class );

          ???TableTag?table?
          = ?(TableTag)?nodes[ 3 ];
          ???
          // temperature
          ???StringNode[]?stringNodes? = ?table.digupStringNode( " 鎮(zhèn)江 " );
          ???StringNode?name?
          = ?stringNodes[ 0 ];
          ???w.setCity(name.toPlainTextString());
          ???CompositeTag?td?
          = ?(CompositeTag)?name.getParent();
          ???CompositeTag?tr?
          = ?(CompositeTag)?td.getParent();
          ???
          int ?columnNo? = ?tr.findPositionOf(td);
          ???TableColumn?nextColumn?
          = ?(TableColumn)?tr.childAt( 5 );
          ???Node?expectedName?
          = ?nextColumn.childAt( 0 );
          ???Node?expectedName2?
          = ?nextColumn.childAt( 2 );
          ???
          // System.out.println(expectedName.getText());
          ???
          // System.out.println(expectedName2.getText());
          ???w.setState(expectedName.getText());
          ???w.setTemperature(expectedName2.getText());
          ???
          // time
          ???stringNodes? = ?table.digupStringNode( " 時(shí)間 " );
          ???name?
          = ?stringNodes[ 0 ];
          ???
          // System.out.println(name.toPlainTextString());

          ???String?time?
          =
          ????name
          ?????.toPlainTextString()
          ?????.substring(
          4 ,?name.toPlainTextString().length())
          ?????.trim();
          ???
          // System.out.println(time);
          ???w.setTime(time);
          ???
          // wind
          ???stringNodes? = ?table.digupStringNode( " 風(fēng)向 " );
          ???name?
          = ?stringNodes[ 0 ];
          ???
          // System.out.println(name.toPlainTextString());

          ???String?wind?
          =
          ????name
          ?????.toPlainTextString()
          ?????.substring(
          4 ,?name.toPlainTextString().length())
          ?????.trim();
          ???
          // System.out.println(wind);
          ???w.setWind(wind);
          ???
          // wind?power
          ???stringNodes? = ?table.digupStringNode( " 風(fēng)力 " );
          ???name?
          = ?stringNodes[ 0 ];
          ???
          // System.out.println(name.toPlainTextString());

          ???String?windpower?
          =
          ????name
          ?????.toPlainTextString()
          ?????.substring(
          4 ,?name.toPlainTextString().length())
          ?????.trim();
          ???
          // System.out.println(windpower);
          ???w.setWindpower(windpower);

          ???w.setUpdateTime(System.currentTimeMillis());

          ??}?
          catch ?(ParserException?e)?{

          ???e.printStackTrace();
          ??}
          ??
          return ?w;
          ?}


          解析出來的代碼必須做緩存處理,

          private ? static ? long ?TIME_TO_LIVE? = ? 1000 ? * ? 60 ? * ? 60 ? * ? 12 ;

          ?
          private ?Weather?loadWeather()? throws ?Exception?{
          ??Weather?weather?
          = ?weather? = ?(Weather)?cache_.get( " chinaweather " );
          ??
          long ?currentTime? = ?System.currentTimeMillis();
          ??
          if ?(weather? != ? null
          ???
          && ?currentTime? < ?(weather.getUpdateTime()? + ?TIME_TO_LIVE))?{
          ???cache_.remove(
          " chinaweather " );
          ???weather?
          = ? null ;
          ??}

          ??
          if ?(weather? == ? null )?{
          ???
          synchronized ?(cache_)?{
          ????weather?
          = ?parserWeather();
          ????cache_.put(
          " chinaweather " ,?weather);
          ???}
          ??}

          ??
          return ?weather;
          ?}


          posted @ 2007-03-08 06:56 konhon 優(yōu)華 閱讀(2231) | 評論 (0)編輯 收藏

          ?

          import ?org.htmlparser.Node;
          import ?org.htmlparser.NodeFilter;
          import ?org.htmlparser.Parser;
          import ?org.htmlparser.filters.TagNameFilter;
          import ?org.htmlparser.tags.TableTag;
          import ?org.htmlparser.util.NodeList;

          /**
          ?*?<br>
          ?*?標(biāo)題:?<br>
          ?*?功能概要:?<br>
          ?*?版權(quán):?cityyouth.cn?(c)?2005?<br>
          ?*?公司:上海城市青年網(wǎng)?<br>
          ?*?創(chuàng)建時(shí)間:2005-12-21?<br>
          ?*?修改時(shí)間:?<br>
          ?*?修改原因:
          ?*?
          ?*?
          @author ?張偉
          ?*?
          @version ?1.0
          ?
          */
          public ? class ?TestYahoo?{
          ????
          public ? static ? void ?testHtml()?{
          ????????
          try ?{
          ????????????String?sCurrentLine;
          ????????????String?sTotalString;
          ????????????sCurrentLine?
          = ? "" ;
          ????????????sTotalString?
          = ? "" ;
          ????????????java.io.InputStream?l_urlStream;
          ????????????java.net.URL?l_url?
          = ? new ?java.net.URL(
          ????????????????????
          " http://sports.sina.com.cn/iframe/nba/live/ " );
          ????????????java.net.HttpURLConnection?l_connection?
          = ?(java.net.HttpURLConnection)?l_url
          ????????????????????.openConnection();
          ????????????l_connection.connect();
          ????????????l_urlStream?
          = ?l_connection.getInputStream();
          ????????????java.io.BufferedReader?l_reader?
          = ? new ?java.io.BufferedReader(
          ????????????????????
          new ?java.io.InputStreamReader(l_urlStream));
          ????????????
          while ?((sCurrentLine? = ?l_reader.readLine())? != ? null )?{
          ????????????????sTotalString?
          += ?sCurrentLine;
          ????????????}
          ????????????System.out.println(sTotalString);

          ????????????System.out.println(
          " ==================== " );
          ????????????String?testText?
          = ?extractText(sTotalString);
          ????????????System.out.println(testText);
          ????????}?
          catch ?(Exception?e)?{
          ????????????e.printStackTrace();
          ????????}

          ????}

          ????
          /**
          ?????*?抽取純文本信息
          ?????*?
          ?????*?
          @param ?inputHtml
          ?????*?
          @return
          ?????
          */
          ????
          public ? static ?String?extractText(String?inputHtml)? throws ?Exception?{
          ????????StringBuffer?text?
          = ? new ?StringBuffer();

          ????????Parser?parser?
          = ?Parser.createParser( new ?String(inputHtml.getBytes(),
          ????????????????
          " 8859_1 " ),? " 8859-1 " );
          ????????
          // ?遍歷所有的節(jié)點(diǎn)
          ????????NodeList?nodes? = ?parser.extractAllNodesThatMatch( new ?NodeFilter()?{
          ????????????
          public ? boolean ?accept(Node?node)?{
          ????????????????
          return ? true ;
          ????????????}
          ????????});
          ????????Node?node?
          = ?nodes.elementAt( 0 );
          ????????text.append(
          new ?String(node.toPlainTextString().getBytes( " 8859_1 " )));
          ????????
          return ?text.toString();
          ????}

          ????
          /**
          ?????*?讀取文件的方式來分析內(nèi)容.?filePath也可以是一個(gè)Url.
          ?????*?
          ?????*?
          @param ?resource
          ?????*????????????文件/Url
          ?????
          */
          ????
          public ? static ? void ?test5(String?resource)? throws ?Exception?{
          ????????Parser?myParser?
          = ? new ?Parser(resource);

          ????????
          // ?設(shè)置編碼
          ????????myParser.setEncoding( " GBK " );
          ????????String?filterStr?
          = ? " table " ;
          ????????NodeFilter?filter?
          = ? new ?TagNameFilter(filterStr);
          ????????NodeList?nodeList?
          = ?myParser.extractAllNodesThatMatch(filter);
          ????????TableTag?tabletag?
          = ?(TableTag)?nodeList.elementAt( 11 );
          ????????????
          ????????????System.out.println(tabletag.toHtml());
          ????????????
          ????????????System.out.println(
          " ============== " );

          ????}

          ????
          /*
          ?????*?public?static?void?main(String[]?args)?{?TestYahoo?testYahoo?=?new
          ?????*?TestYahoo();?testYahoo.testHtml();?}
          ?????
          */
          ????
          public ? static ? void ?main(String[]?args)? throws ?Exception?{
          ????????test5(
          " http://sports.yahoo.com/nba/scoreboard " );
          ????}
          }
          posted @ 2007-03-08 06:50 konhon 優(yōu)華 閱讀(1602) | 評論 (0)編輯 收藏

               摘要: 最近搞一個(gè)扣網(wǎng)頁內(nèi)容的SessionBean,需要模擬客戶端post提交,然后得到servlet返回的結(jié)果。采用Jakarta的HttpClient API解決之.HttpClient擴(kuò)展和增強(qiáng)了標(biāo)準(zhǔn)java.net包,是一個(gè)內(nèi)容廣泛的代碼庫,功能極其豐富,能夠構(gòu)造出各種使用HTTP協(xié)議的分布式應(yīng)用,或者也可以嵌入到現(xiàn)有應(yīng)用,為應(yīng)用增加訪問HTTP協(xié)議的能力 要求:1:CLASSPATH中有...  閱讀全文
          posted @ 2007-03-07 21:51 konhon 優(yōu)華 閱讀(3781) | 評論 (0)編輯 收藏


          服務(wù)器:
          1.jsp
          <body>
          <form name="_ctl0" method="post" action="TestFileManager.aspx" id="_ctl0" enctype="multipart/form-data">
          <input type="hidden" name="__VIEWSTATE" value="dDwyNTIzNjA5NDU7Oz7rsE3eBYzQHDVtl+aTn96MvQW6PQ==" />
          <p>
          <input name="uploadfile1" id="uploadfile1" type="file" size="49" />
          <input type="submit" name="Button1" value="?" id="Button1" />
          </p>
          <p>
          <span id="Label1" style="width:459px;"></span>
          </p>
          <!-- Insert content here -->
          </form>
          </body>
          客戶端:
          首先創(chuàng)建一個(gè)到服務(wù)器http的請求
          HttpRequest request = new HttpRequest("http://服務(wù)器/1.jsp");
          第一次使用的是GET方式
          request.setMethod("GET");
          緊接著進(jìn)行一些請求的屬性設(shè)置
          request.setRequestHeader("Cache-Control", "no-cache");
          這里保持連接,因?yàn)楹竺孢€要發(fā)送數(shù)據(jù)到服務(wù)器呢
          request.setRequestHeader("Connection", "Keep-Alive");
          下面是一些無關(guān)緊要的屬性設(shè)置了。
          request.setRequestHeader("Accept", "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
          request.setRequestHeader("Accept-Encoding", "gzip, deflate");
          request.setRequestHeader("Accept-Language", "en-au");
          request.setRequestHeader("Referer", "http://服務(wù)器/1.jsp");
          request.setRequestHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3215; .NET CLR 1.0.3705)");
          構(gòu)造好了連接請求,然后連接
          request.connect();
          緊接著提取Cookie值,在后文的post中可以用到。
          String strCookie = request.getResponseHeader("Set-Cookie");
          strCookie = strCookie.substring(0,strCookie.indexOf(";"));
          下面通過循環(huán)查找,提取__VIEWSTATE的值
          for ( int i = 0; i < nlist.getLength(); i++) {
          node = nlist.item(i);
          strName = getNodeAttributeValue(node,"name");
          if ( strName.equals("__VIEWSTATE") ) {
          strValue = getNodeAttributeValue(node,"value");
          break;
          }
          }
          往服務(wù)器組織發(fā)送數(shù)據(jù)
          DataOutputStream dos = new DataOutputStream(request.getOutputStream());
          dos.writeBytes("-----------------------------"+strBoundary);//這是每個(gè)要被發(fā)送數(shù)據(jù)間的間隔
          dos.writeBytes(" Content-Disposition: form-data; name="__VIEWSTATE"");
          dos.writeBytes(" "+strValue);
          dos.writeBytes(" -----------------------------"+strBoundary);
          這里面是發(fā)送文件的部分
          dos.writeBytes(" Content-Disposition: form-data; name="uploadfile1"; filename="" + strFileName + """);
          dos.writeBytes(" Content-Type: text/xml");
          dos.writeBytes(" ");
          dos.writeBytes(new String(data));
          dos.writeBytes(" -----------------------------"+strBoundary);
          dos.writeBytes(" Content-Disposition: form-data; name="Button1"");
          dos.writeBytes(" 上傳");
          dos.writeBytes(" -----------------------------"+strBoundary+"--");
          dos.writeBytes(" ");
          dos.close();
          posted @ 2007-03-07 20:14 konhon 優(yōu)華 閱讀(4274) | 評論 (1)編輯 收藏

          主站蜘蛛池模板: 海兴县| 泸西县| 吉隆县| 游戏| 苍南县| 高雄县| 济源市| 务川| 洛浦县| 河西区| 广河县| 西青区| 新宾| 汽车| 辽源市| 佛教| 赤水市| 平江县| 临武县| 南昌市| 邳州市| 西安市| 浮梁县| 麻阳| 西峡县| 锡林浩特市| 达尔| 夏津县| 四平市| 天等县| 香河县| 扶沟县| 施甸县| 嘉义县| 宜兴市| 甘孜县| 普格县| 师宗县| 宕昌县| 南部县| 普宁市|