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

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

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

    Feeling

        三人行,必有我?guī)熝?/p>

       ::  :: 新隨筆 :: 聯(lián)系 ::  :: 管理 ::
      185 隨筆 :: 0 文章 :: 392 評(píng)論 :: 0 Trackbacks

    2011年12月13日 #

         摘要: 很多網(wǎng)上下載的PDF文件都包含各種形式的水印,本文主要闡述如何使用易轉(zhuǎn)換一鍵刪除PDF文件中的各種圖片水印和文字水印  閱讀全文
    posted @ 2021-03-09 20:29 三人行,必有我?guī)熝?閱讀(437) | 評(píng)論 (0)編輯 收藏

    Spark源代碼下載地址: http://spark.apache.org/downloads.html

    下載后,直接用 Scala IDE 通過已存在的項(xiàng)目導(dǎo)入到Eclipse workspace中去,然后Eclipse會(huì)自動(dòng)進(jìn)行編譯。第一次編譯會(huì)報(bào)很多錯(cuò)誤,不過總的來說,導(dǎo)致編譯錯(cuò)誤的源頭有三個(gè):
    1、Scala編譯器版本錯(cuò)誤
    2、Eclipse Maven插件不能自動(dòng)識(shí)別spark project的一些pom,報(bào)Plugin execution not covered by lifecycle configuration異常
    3、一些項(xiàng)目,maven會(huì)自動(dòng)生成scala和java文件,但是這些自動(dòng)生成的代碼文件沒有配置在eclipse項(xiàng)目的classpath里。

    針對(duì)第一種錯(cuò)誤,比較簡(jiǎn)單,對(duì)于每個(gè)scala項(xiàng)目,右鍵屬性選擇spark對(duì)應(yīng)的scala編譯器版本。



    當(dāng)然spark代碼里的項(xiàng)目有幾十個(gè),只能手工一個(gè)個(gè)設(shè)置了,比較傻,沒辦法,還不停的彈出對(duì)話框,不停地回車吧。

    編譯的難點(diǎn)主要在第二種錯(cuò)誤上,比如spark-sql項(xiàng)目的pom, 里面有個(gè)build-helper-maven-plugin,它下面的execution,eclipse maven插件無法識(shí)別,報(bào)Plugin execution not covered by lifecycle configuration異常,解決方案參見 https://www.eclipse.org/m2e/documentation/m2e-execution-not-covered.html,先使用 Eclipse quick-fix選項(xiàng)自動(dòng)修復(fù),忽略此 maven goal,Eclipse 會(huì)為 pom.xml自動(dòng)添加一段xml代碼,包含在 pluginManagement section中,里面有一段 <action><ignore/></action>,此處手動(dòng)修改成
    <action>
        <execute>
            <runOnIncremental>false</runOnIncremental>
        </execute>
    </action>
    然后右鍵 maven update project 就OK了。

    一共有5個(gè)project需要修改pom,如圖


    修改pom后重新編譯,依舊會(huì)報(bào)一些錯(cuò)誤,這些錯(cuò)誤都是由于maven自動(dòng)生成的java和scala代碼沒有添加到classpath里導(dǎo)致的編譯錯(cuò)誤,只需要手工添加一下即可,需要手工添加項(xiàng)目有 spark-streaming-flume-sink 的 src_managed\main\compiled_avro 目錄 和 spark-sql 項(xiàng)目的 test\gen-java 目錄。

    全部編譯好以后的截圖:


    修改完以后,Spark代碼全部編譯下來大概耗時(shí)25分鐘左右(CPU 雙核 I7 4600)

    原文地址:http://m.tkk7.com/cnfree/archive/2016/11/08/431965.html
    posted @ 2016-11-08 13:12 三人行,必有我?guī)熝?閱讀(2255) | 評(píng)論 (0)編輯 收藏

      Spark簡(jiǎn)介

      Spark是整個(gè)BDAS的核心組件,是一個(gè)大數(shù)據(jù)分布式編程框架,不僅實(shí)現(xiàn)了MapReduce的算子map 函數(shù)和reduce函數(shù)及計(jì)算模型,還提供更為豐富的算子,如filter、join、groupByKey等。是一個(gè)用來實(shí)現(xiàn)快速而同用的集群計(jì)算的平臺(tái)。

      Spark將分布式數(shù)據(jù)抽象為彈性分布式數(shù)據(jù)集(RDD),實(shí)現(xiàn)了應(yīng)用任務(wù)調(diào)度、RPC、序列化和壓縮,并為運(yùn)行在其上的上層組件提供API。其底層采用Scala這種函數(shù)式語言書寫而成,并且所提供的API深度借鑒Scala函數(shù)式的編程思想,提供與Scala類似的編程接口

      Sparkon Yarn

      

      從用戶提交作業(yè)到作業(yè)運(yùn)行結(jié)束整個(gè)運(yùn)行期間的過程分析。

      一、客戶端進(jìn)行操作

    1. 根據(jù)yarnConf來初始化yarnClient,并啟動(dòng)yarnClient

    2. 創(chuàng)建客戶端Application,并獲取Application的ID,進(jìn)一步判斷集群中的資源是否滿足executor和ApplicationMaster申請(qǐng)的資源,如果不滿足則拋出IllegalArgumentException;

    3. 設(shè)置資源、環(huán)境變量:其中包括了設(shè)置Application的Staging目錄、準(zhǔn)備本地資源(jar文件、log4j.properties)、設(shè)置Application其中的環(huán)境變量、創(chuàng)建Container啟動(dòng)的Context等;

    4. 設(shè)置Application提交的Context,包括設(shè)置應(yīng)用的名字、隊(duì)列、AM的申請(qǐng)的Container、標(biāo)記該作業(yè)的類型為Spark;

    5. 申請(qǐng)Memory,并最終通過yarnClient.submitApplication向ResourceManager提交該Application。

      當(dāng)作業(yè)提交到Y(jié)ARN上之后,客戶端就沒事了,甚至在終端關(guān)掉那個(gè)進(jìn)程也沒事,因?yàn)檎麄€(gè)作業(yè)運(yùn)行在YARN集群上進(jìn)行,運(yùn)行的結(jié)果將會(huì)保存到HDFS或者日志中。

      二、提交到Y(jié)ARN集群,YARN操作

    1. 運(yùn)行ApplicationMaster的run方法;

    2. 設(shè)置好相關(guān)的環(huán)境變量。

    3. 創(chuàng)建amClient,并啟動(dòng);

    4. 在Spark UI啟動(dòng)之前設(shè)置Spark UI的AmIpFilter;

    5. 在startUserClass函數(shù)專門啟動(dòng)了一個(gè)線程(名稱為Driver的線程)來啟動(dòng)用戶提交的Application,也就是啟動(dòng)了Driver。在Driver中將會(huì)初始化SparkContext;

    6. 等待SparkContext初始化完成,最多等待spark.yarn.applicationMaster.waitTries次數(shù)(默認(rèn)為10),如果等待了的次數(shù)超過了配置的,程序?qū)?huì)退出;否則用SparkContext初始化yarnAllocator;

    7. 當(dāng)SparkContext、Driver初始化完成的時(shí)候,通過amClient向ResourceManager注冊(cè)ApplicationMaster

    8. 分配并啟動(dòng)Executeors。在啟動(dòng)Executeors之前,先要通過yarnAllocator獲取到numExecutors個(gè)Container,然后在Container中啟動(dòng)Executeors。

        那么這個(gè)Application將失敗,將Application Status標(biāo)明為FAILED,并將關(guān)閉SparkContext。其實(shí),啟動(dòng)Executeors是通過ExecutorRunnable實(shí)現(xiàn)的,而ExecutorRunnable內(nèi)部是啟動(dòng)CoarseGrainedExecutorBackend的。

    9. 最后,Task將在CoarseGrainedExecutorBackend里面運(yùn)行,然后運(yùn)行狀況會(huì)通過Akka通知CoarseGrainedScheduler,直到作業(yè)運(yùn)行完成。

      Spark節(jié)點(diǎn)的概念

      一、Spark驅(qū)動(dòng)器是執(zhí)行程序中的main()方法的進(jìn)程。它執(zhí)行用戶編寫的用來創(chuàng)建SparkContext(初始化)、創(chuàng)建RDD,以及運(yùn)行RDD的轉(zhuǎn)化操作和行動(dòng)操作的代碼。

      驅(qū)動(dòng)器節(jié)點(diǎn)driver的職責(zé):

    1. 把用戶程序轉(zhuǎn)為任務(wù)task(driver)

        Spark驅(qū)動(dòng)器程序負(fù)責(zé)把用戶程序轉(zhuǎn)化為多個(gè)物理執(zhí)行單元,這些單元也被稱之為任務(wù)task(詳解見備注)

    2. 為執(zhí)行器節(jié)點(diǎn)調(diào)度任務(wù)(executor)

        有了物理計(jì)劃之后,Spark驅(qū)動(dòng)器在各個(gè)執(zhí)行器節(jié)點(diǎn)進(jìn)程間協(xié)調(diào)任務(wù)的調(diào)度。Spark驅(qū)動(dòng)器程序會(huì)根據(jù)當(dāng)前的執(zhí)行器節(jié)點(diǎn),把所有任務(wù)基于數(shù)據(jù)所在位置分配給合適的執(zhí)行器進(jìn)程。當(dāng)執(zhí)行任務(wù)時(shí),執(zhí)行器進(jìn)程會(huì)把緩存的數(shù)據(jù)存儲(chǔ)起來,而驅(qū)動(dòng)器進(jìn)程同樣會(huì)跟蹤這些緩存數(shù)據(jù)的位置,并利用這些位置信息來調(diào)度以后的任務(wù),以盡量減少數(shù)據(jù)的網(wǎng)絡(luò)傳輸。(就是所謂的移動(dòng)計(jì)算,而不移動(dòng)數(shù)據(jù))。

      二、執(zhí)行器節(jié)點(diǎn)

      作用:

    1. 負(fù)責(zé)運(yùn)行組成Spark應(yīng)用的任務(wù),并將結(jié)果返回給驅(qū)動(dòng)器進(jìn)程;

    2. 通過自身的塊管理器(blockManager)為用戶程序中要求緩存的RDD提供內(nèi)存式存儲(chǔ)。RDD是直接緩存在執(zhí)行器進(jìn)程內(nèi)的,因此任務(wù)可以在運(yùn)行時(shí)充分利用緩存數(shù)據(jù)加快運(yùn)算。

      驅(qū)動(dòng)器的職責(zé):

      所有的Spark程序都遵循同樣的結(jié)構(gòu):程序從輸入數(shù)據(jù)創(chuàng)建一系列RDD,再使用轉(zhuǎn)化操作派生成新的RDD,最后使用行動(dòng)操作手機(jī)或存儲(chǔ)結(jié)果RDD,Spark程序其實(shí)是隱式地創(chuàng)建出了一個(gè)由操作組成的邏輯上的有向無環(huán)圖DAG。當(dāng)驅(qū)動(dòng)器程序執(zhí)行時(shí),它會(huì)把這個(gè)邏輯圖轉(zhuǎn)為物理執(zhí)行計(jì)劃。

      這樣 Spark就把邏輯計(jì)劃轉(zhuǎn)為一系列步驟(stage),而每個(gè)步驟又由多個(gè)任務(wù)組成。這些任務(wù)會(huì)被打包送到集群中。

      Spark初始化

    1. 每個(gè)Spark應(yīng)用都由一個(gè)驅(qū)動(dòng)器程序來發(fā)起集群上的各種并行操作。驅(qū)動(dòng)器程序包含應(yīng)用的main函數(shù),并且定義了集群上的分布式數(shù)據(jù)集,以及對(duì)該分布式數(shù)據(jù)集應(yīng)用了相關(guān)操作。

    2. 驅(qū)動(dòng)器程序通過一個(gè)SparkContext對(duì)象來訪問spark,這個(gè)對(duì)象代表對(duì)計(jì)算集群的一個(gè)連接。(比如在sparkshell啟動(dòng)時(shí)已經(jīng)自動(dòng)創(chuàng)建了一個(gè)SparkContext對(duì)象,是一個(gè)叫做SC的變量。(下圖,查看變量sc)

        

    3. 一旦創(chuàng)建了sparkContext,就可以用它來創(chuàng)建RDD。比如調(diào)用sc.textFile()來創(chuàng)建一個(gè)代表文本中各行文本的RDD。(比如vallinesRDD = sc.textFile(“yangsy.text”),val spark = linesRDD.filter(line=>line.contains(“spark”),spark.count())

        執(zhí)行這些操作,驅(qū)動(dòng)器程序一般要管理多個(gè)執(zhí)行器,就是我們所說的executor節(jié)點(diǎn)。

    4. 在初始化SparkContext的同時(shí),加載sparkConf對(duì)象來加載集群的配置,從而創(chuàng)建sparkContext對(duì)象。

        從源碼中可以看到,在啟動(dòng)thriftserver時(shí),調(diào)用了spark- daemon.sh文件,該文件源碼如左圖,加載spark_home下的conf中的文件。

        

        (在執(zhí)行后臺(tái)代碼時(shí),需要首先創(chuàng)建conf對(duì)象,加載相應(yīng)參數(shù), val sparkConf = newSparkConf().setMaster("local").setAppName("cocapp").set("spark.executor.memory","1g"), val sc: SparkContext = new SparkContext(sparkConf))

      RDD工作原理:

      RDD(Resilient DistributedDatasets)[1] ,彈性分布式數(shù)據(jù)集,是分布式內(nèi)存的一個(gè)抽象概念,RDD提供了一種高度受限的共享內(nèi)存模型,即RDD是只讀的記錄分區(qū)的集合,只能通過在其他RDD執(zhí)行確定的轉(zhuǎn)換操作(如map、join和group by)而創(chuàng)建,然而這些限制使得實(shí)現(xiàn)容錯(cuò)的開銷很低。對(duì)開發(fā)者而言,RDD可以看作是Spark的一個(gè)對(duì)象,它本身運(yùn)行于內(nèi)存中,如讀文件是一個(gè)RDD,對(duì)文件計(jì)算是一個(gè)RDD,結(jié)果集也是一個(gè)RDD ,不同的分片、數(shù)據(jù)之間的依賴、key-value類型的map數(shù)據(jù)都可以看做RDD。

      主要分為三部分:創(chuàng)建RDD對(duì)象,DAG調(diào)度器創(chuàng)建執(zhí)行計(jì)劃,Task調(diào)度器分配任務(wù)并調(diào)度Worker開始運(yùn)行。

      SparkContext(RDD相關(guān)操作)→通過(提交作業(yè))→(遍歷RDD拆分stage→生成作業(yè))DAGScheduler→通過(提交任務(wù)集)→任務(wù)調(diào)度管理(TaskScheduler)→通過(按照資源獲取任務(wù))→任務(wù)調(diào)度管理(TaskSetManager)

      Transformation返回值還是一個(gè)RDD。它使用了鏈?zhǔn)秸{(diào)用的設(shè)計(jì)模式,對(duì)一個(gè)RDD進(jìn)行計(jì)算后,變換成另外一個(gè)RDD,然后這個(gè)RDD又可以進(jìn)行另外一次轉(zhuǎn)換。這個(gè)過程是分布式的。

      Action返回值不是一個(gè)RDD。它要么是一個(gè)Scala的普通集合,要么是一個(gè)值,要么是空,最終或返回到Driver程序,或把RDD寫入到文件系統(tǒng)中

      轉(zhuǎn)換(Transformations)(如:map, filter, groupBy, join等),Transformations操作是Lazy的,也就是說從一個(gè)RDD轉(zhuǎn)換生成另一個(gè)RDD的操作不是馬上執(zhí)行,Spark在遇到Transformations操作時(shí)只會(huì)記錄需要這樣的操作,并不會(huì)去執(zhí)行,需要等到有Actions操作的時(shí)候才會(huì)真正啟動(dòng)計(jì)算過程進(jìn)行計(jì)算。

      操作(Actions)(如:count, collect, save等),Actions操作會(huì)返回結(jié)果或把RDD數(shù)據(jù)寫到存儲(chǔ)系統(tǒng)中。Actions是觸發(fā)Spark啟動(dòng)計(jì)算的動(dòng)因。

      它們本質(zhì)區(qū)別是:Transformation返回值還是一個(gè)RDD。它使用了鏈?zhǔn)秸{(diào)用的設(shè)計(jì)模式,對(duì)一個(gè)RDD進(jìn)行計(jì)算后,變換成另外一個(gè)RDD,然后這個(gè)RDD又可以進(jìn)行另外一次轉(zhuǎn)換。這個(gè)過程是分布式的。Action返回值不是一個(gè)RDD。它要么是一個(gè)Scala的普通集合,要么是一個(gè)值,要么是空,最終或返回到Driver程序,或把RDD寫入到文件系統(tǒng)中。關(guān)于這兩個(gè)動(dòng)作,在Spark開發(fā)指南中會(huì)有就進(jìn)一步的詳細(xì)介紹,它們是基于Spark開發(fā)的核心。

      RDD基礎(chǔ)

    1. Spark中的RDD就是一個(gè)不可變的分布式對(duì)象集合。每個(gè)RDD都被分為多個(gè)分區(qū),這些分區(qū)運(yùn)行在集群的不同節(jié)點(diǎn)上。創(chuàng)建RDD的方法有兩種:一種是讀取一個(gè)外部數(shù)據(jù)集;一種是在群東程序里分發(fā)驅(qū)動(dòng)器程序中的對(duì)象集合,不如剛才的示例,讀取文本文件作為一個(gè)字符串的RDD的示例。

    2. 創(chuàng)建出來后,RDD支持兩種類型的操作:轉(zhuǎn)化操作和行動(dòng)操作

        轉(zhuǎn)化操作會(huì)由一個(gè)RDD生成一個(gè)新的RDD。(比如剛才的根據(jù)謂詞篩選)

        行動(dòng)操作會(huì)對(duì)RDD計(jì)算出一個(gè)結(jié)果,并把結(jié)果返回到驅(qū)動(dòng)器程序中,或把結(jié)果存儲(chǔ)到外部存儲(chǔ)系統(tǒng)(比如HDFS)中。比如first()操作就是一個(gè)行動(dòng)操作,會(huì)返回RDD的第一個(gè)元素。

        注:轉(zhuǎn)化操作與行動(dòng)操作的區(qū)別在于Spark計(jì)算RDD的方式不同。雖然你可以在任何時(shí)候定義一個(gè)新的RDD,但Spark只會(huì)惰性計(jì)算這些RDD。它們只有第一個(gè)在一個(gè)行動(dòng)操作中用到時(shí),才會(huì)真正的計(jì)算。之所以這樣設(shè)計(jì),是因?yàn)楸热鐒偛耪{(diào)用sc.textFile(...)時(shí)就把文件中的所有行都讀取并存儲(chǔ)起來,就會(huì)消耗很多存儲(chǔ)空間,而我們馬上又要篩選掉其中的很多數(shù)據(jù)。

        這里還需要注意的一點(diǎn)是,spark會(huì)在你每次對(duì)它們進(jìn)行行動(dòng)操作時(shí)重新計(jì)算。如果想在多個(gè)行動(dòng)操作中重用同一個(gè)RDD,那么可以使用RDD.persist()或RDD.collect()讓Spark把這個(gè)RDD緩存下來。(可以是內(nèi)存,也可以是磁盤)

    3. Spark會(huì)使用譜系圖來記錄這些不同RDD之間的依賴關(guān)系,Spark需要用這些信息來按需計(jì)算每個(gè)RDD,也可以依靠譜系圖在持久化的RDD丟失部分?jǐn)?shù)據(jù)時(shí)用來恢復(fù)所丟失的數(shù)據(jù)。(如下圖,過濾errorsRDD與warningsRDD,最終調(diào)用union()函數(shù))

        

      RDD計(jì)算方式

      

      RDD的寬窄依賴

      

      窄依賴 (narrowdependencies) 和寬依賴 (widedependencies) 。窄依賴是指 父 RDD 的每個(gè)分區(qū)都只被子 RDD 的一個(gè)分區(qū)所使用 。相應(yīng)的,那么寬依賴就是指父 RDD 的分區(qū)被多個(gè)子 RDD 的分區(qū)所依賴。例如, map 就是一種窄依賴,而 join 則會(huì)導(dǎo)致寬依賴

      這種劃分有兩個(gè)用處。首先,窄依賴支持在一個(gè)結(jié)點(diǎn)上管道化執(zhí)行。例如基于一對(duì)一的關(guān)系,可以在 filter 之后執(zhí)行 map 。其次,窄依賴支持更高效的故障還原。因?yàn)閷?duì)于窄依賴,只有丟失的父 RDD 的分區(qū)需要重新計(jì)算。而對(duì)于寬依賴,一個(gè)結(jié)點(diǎn)的故障可能導(dǎo)致來自所有父 RDD 的分區(qū)丟失,因此就需要完全重新執(zhí)行。因此對(duì)于寬依賴,Spark 會(huì)在持有各個(gè)父分區(qū)的結(jié)點(diǎn)上,將中間數(shù)據(jù)持久化來簡(jiǎn)化故障還原,就像 MapReduce 會(huì)持久化 map 的輸出一樣。

      SparkExample

      

      步驟 1 :創(chuàng)建 RDD 。上面的例子除去最后一個(gè) collect 是個(gè)動(dòng)作,不會(huì)創(chuàng)建 RDD 之外,前面四個(gè)轉(zhuǎn)換都會(huì)創(chuàng)建出新的 RDD 。因此第一步就是創(chuàng)建好所有 RDD( 內(nèi)部的五項(xiàng)信息 ) 。

      步驟 2 :創(chuàng)建執(zhí)行計(jì)劃。Spark 會(huì)盡可能地管道化,并基于是否要重新組織數(shù)據(jù)來劃分 階段 (stage) ,例如本例中的 groupBy() 轉(zhuǎn)換就會(huì)將整個(gè)執(zhí)行計(jì)劃劃分成兩階段執(zhí)行。最終會(huì)產(chǎn)生一個(gè) DAG(directedacyclic graph ,有向無環(huán)圖 ) 作為邏輯執(zhí)行計(jì)劃。

      步驟 3 :調(diào)度任務(wù)。 將各階段劃分成不同的 任務(wù) (task) ,每個(gè)任務(wù)都是數(shù)據(jù)和計(jì)算的合體。在進(jìn)行下一階段前,當(dāng)前階段的所有任務(wù)都要執(zhí)行完成。因?yàn)橄乱浑A段的第一個(gè)轉(zhuǎn)換一定是重新組織數(shù)據(jù)的,所以必須等當(dāng)前階段所有結(jié)果數(shù)據(jù)都計(jì)算出來了才能繼續(xù)。

      假設(shè)本例中的 hdfs://names 下有四個(gè)文件塊,那么 HadoopRDD 中 partitions 就會(huì)有四個(gè)分區(qū)對(duì)應(yīng)這四個(gè)塊數(shù)據(jù),同時(shí) preferedLocations 會(huì)指明這四個(gè)塊的最佳位置。現(xiàn)在,就可以創(chuàng)建出四個(gè)任務(wù),并調(diào)度到合適的集群結(jié)點(diǎn)上。

      Spark數(shù)據(jù)分區(qū)

    1. Spark的特性是對(duì)數(shù)據(jù)集在節(jié)點(diǎn)間的分區(qū)進(jìn)行控制。在分布式系統(tǒng)中,通訊的代價(jià)是巨大的,控制數(shù)據(jù)分布以獲得最少的網(wǎng)絡(luò)傳輸可以極大地提升整體性能。Spark程序可以通過控制RDD分區(qū)方式來減少通訊的開銷。

    2. Spark中所有的鍵值對(duì)RDD都可以進(jìn)行分區(qū)。確保同一組的鍵出現(xiàn)在同一個(gè)節(jié)點(diǎn)上。比如,使用哈希分區(qū)將一個(gè)RDD分成了100個(gè)分區(qū),此時(shí)鍵的哈希值對(duì)100取模的結(jié)果相同的記錄會(huì)被放在一個(gè)節(jié)點(diǎn)上。

        (可使用partitionBy(newHashPartitioner(100)).persist()來構(gòu)造100個(gè)分區(qū))

    3. Spark中的許多操作都引入了將數(shù)據(jù)根據(jù)鍵跨界點(diǎn)進(jìn)行混洗的過程。(比如:join(),leftOuterJoin(),groupByKey(),reducebyKey()等)對(duì)于像reduceByKey()這樣只作用于單個(gè)RDD的操作,運(yùn)行在未分區(qū)的RDD上的時(shí)候會(huì)導(dǎo)致每個(gè)鍵的所有對(duì)應(yīng)值都在每臺(tái)機(jī)器上進(jìn)行本地計(jì)算。

      SparkSQL的shuffle過程

      

      Spark SQL的核心是把已有的RDD,帶上Schema信息,然后注冊(cè)成類似sql里的”Table”,對(duì)其進(jìn)行sql查詢。這里面主要分兩部分,一是生成SchemaRD,二是執(zhí)行查詢。

      如果是spark-hive項(xiàng)目,那么讀取metadata信息作為Schema、讀取hdfs上數(shù)據(jù)的過程交給Hive完成,然后根據(jù)這倆部分生成SchemaRDD,在HiveContext下進(jìn)行hql()查詢。

      SparkSQL結(jié)構(gòu)化數(shù)據(jù)

    1. 首先說一下ApacheHive,Hive可以在HDFS內(nèi)或者在其他存儲(chǔ)系統(tǒng)上存儲(chǔ)多種格式的表。SparkSQL可以讀取Hive支持的任何表。要把Spark SQL連接已有的hive上,需要提供Hive的配置文件。hive-site.xml文件復(fù)制到spark的conf文件夾下。再創(chuàng)建出HiveContext對(duì)象(sparksql的入口),然后就可以使用HQL來對(duì)表進(jìn)行查詢,并以由行足證的RDD的形式拿到返回的數(shù)據(jù)。

    2. 創(chuàng)建Hivecontext并查詢數(shù)據(jù)

        importorg.apache.spark.sql.hive.HiveContext

        valhiveCtx = new org.apache.spark.sql.hive.HiveContext(sc)

        valrows = hiveCtx.sql(“SELECT name,age FROM users”)

        valfitstRow – rows.first()

        println(fitstRow.getSgtring(0)) //字段0是name字段

    3. 通過jdbc連接外部數(shù)據(jù)源更新與加載

        Class.forName("com.mysql.jdbc.Driver")

        val conn =DriverManager.getConnection(mySQLUrl)

        val stat1 =conn.createStatement()

        stat1.execute("UPDATE CI_LABEL_INFO set DATA_STATUS_ID = 2 , DATA_DATE ='" + dataDate +"' where LABEL_ID in ("+allCreatedLabels.mkString(",")+")")

        stat1.close()

        //加載外部數(shù)據(jù)源數(shù)據(jù)到內(nèi)存

        valDIM_COC_INDEX_MODEL_TABLE_CONF =sqlContext.jdbc(mySQLUrl,"DIM_COC_INDEX_MODEL_TABLE_CONF").cache()

        val targets =DIM_COC_INDEX_MODEL_TABLE_CONF.filter("TABLE_DATA_CYCLE ="+TABLE_DATA_CYCLE).collect

      SparkSQL解析

      

      首先說下傳統(tǒng)數(shù)據(jù)庫(kù)的解析,傳統(tǒng)數(shù)據(jù)庫(kù)的解析過程是按Rusult、Data Source、Operation的次序來解析的。傳統(tǒng)數(shù)據(jù)庫(kù)先將讀入的SQL語句進(jìn)行解析,分辨出SQL語句中哪些詞是關(guān)鍵字(如select,from,where),哪些是表達(dá)式,哪些是Projection,哪些是Data Source等等。進(jìn)一步判斷SQL語句是否規(guī)范,不規(guī)范就報(bào)錯(cuò),規(guī)范則按照下一步過程綁定(Bind)。過程綁定是將SQL語句和數(shù)據(jù)庫(kù)的數(shù)據(jù)字典(列,表,視圖等)進(jìn)行綁定,如果相關(guān)的Projection、Data Source等都存在,就表示這個(gè)SQL語句是可以執(zhí)行的。在執(zhí)行過程中,有時(shí)候甚至不需要讀取物理表就可以返回結(jié)果,比如重新運(yùn)行剛運(yùn)行過的SQL語句,直接從數(shù)據(jù)庫(kù)的緩沖池中獲取返回結(jié)果。在數(shù)據(jù)庫(kù)解析的過程中SQL語句時(shí),將會(huì)把SQL語句轉(zhuǎn)化成一個(gè)樹形結(jié)構(gòu)來進(jìn)行處理,會(huì)形成一個(gè)或含有多個(gè)節(jié)點(diǎn)(TreeNode)的Tree,然后再后續(xù)的處理政對(duì)該Tree進(jìn)行一系列的操作。

      Spark SQL對(duì)SQL語句的處理和關(guān)系數(shù)據(jù)庫(kù)對(duì)SQL語句的解析采用了類似的方法,首先會(huì)將SQL語句進(jìn)行解析,然后形成一個(gè)Tree,后續(xù)如綁定、優(yōu)化等處理過程都是對(duì)Tree的操作,而操作方法是采用Rule,通過模式匹配,對(duì)不同類型的節(jié)點(diǎn)采用不同的操作。SparkSQL有兩個(gè)分支,sqlContext和hiveContext。sqlContext現(xiàn)在只支持SQL語法解析器(Catalyst),hiveContext支持SQL語法和HiveContext語法解析器。

    原文地址:http://mt.sohu.com/20160522/n450849016.shtml

    posted @ 2016-09-08 13:11 三人行,必有我?guī)熝?閱讀(252) | 評(píng)論 (0)編輯 收藏

    spark中有partition的概念(和slice是同一個(gè)概念,在spark1.2中官網(wǎng)已經(jīng)做出了說明),一般每個(gè)partition對(duì)應(yīng)一個(gè)task。在我的測(cè)試過程中,如果沒有設(shè)置spark.default.parallelism參數(shù),spark計(jì)算出來的partition非常巨大,與我的cores非常不搭。我在兩臺(tái)機(jī)器上(8cores *2 +6g * 2)上,spark計(jì)算出來的partition達(dá)到2.8萬個(gè),也就是2.9萬個(gè)tasks,每個(gè)task完成時(shí)間都是幾毫秒或者零點(diǎn)幾毫秒,執(zhí)行起來非常緩慢。在我嘗試設(shè)置了 spark.default.parallelism 后,任務(wù)數(shù)減少到10,執(zhí)行一次計(jì)算過程從minute降到20second。

    參數(shù)可以通過spark_home/conf/spark-default.conf配置文件設(shè)置。

    eg.

    spark.master  spark://master:7077 

    spark.default.parallelism  10 

    spark.driver.memory  2g 

    spark.serializer  org.apache.spark.serializer.KryoSerializer 

    spark.sql.shuffle.partitions  50

     

    下面是官網(wǎng)的相關(guān)描述:

    from:http://spark.apache.org/docs/latest/configuration.html

    Property NameDefaultMeaning
    spark.default.parallelism For distributed shuffle operations like reduceByKey and join, the largest number of partitions in a parent RDD. For operations likeparallelize with no parent RDDs, it depends on the cluster manager:
    • Local mode: number of cores on the local machine
    • Mesos fine grained mode: 8
    • Others: total number of cores on all executor nodes or 2, whichever is larger
    Default number of partitions in RDDs returned by transformations like joinreduceByKey, and parallelize when not set by user.

    from:http://spark.apache.org/docs/latest/tuning.html

    Level of Parallelism

    Clusters will not be fully utilized unless you set the level of parallelism for each operation high enough. Spark automatically sets the number of “map” tasks to run on each file according to its size (though you can control it through optional parameters to SparkContext.textFile, etc), and for distributed “reduce” operations, such as groupByKey and reduceByKey, it uses the largest parent RDD’s number of partitions. You can pass the level of parallelism as a second argument (see the spark.PairRDDFunctions documentation), or set the config propertyspark.default.parallelism to change the default. In general, we recommend 2-3 tasks per CPU core in your cluster.


    原文地址:http://www.cnblogs.com/wrencai/p/4231966.html

    posted @ 2016-09-08 13:07 三人行,必有我?guī)熝?閱讀(2206) | 評(píng)論 (0)編輯 收藏

    Eclipse Class Decompiler是一款Eclipse插件,整合了多種反編譯器,和Eclipse Class Viewer無縫集成,能夠很方便的使用插件查看類庫(kù)源碼,進(jìn)行Debug調(diào)試。
    同時(shí)還提供了在線自動(dòng)查找源代碼,查看Class二進(jìn)制字節(jié)碼的功能。
     

    Eclipse Class Decompiler對(duì)JDK的最低要求為JDK1.6, 能反編譯和debug各版本的Class文件,支持JDK8的Lambda語法,同時(shí)支持中文等非Ascii碼字符集的解析,支持Eclipse 3.6及以上所有版本的Eclipse。

    本插件支持Windows,Linux,Macosx 32位及64位操作系統(tǒng)。

    Github項(xiàng)目地址為:https://github.com/cnfree/Eclipse-Class-Decompiler

    請(qǐng)通過以下地址選擇一個(gè)可用的源在線安裝:

    http://cnfree.github.io/Eclipse-Class-Decompiler/update
    http://raw.githubusercontent.com/cnfree/eclipse/master/decompiler/update/
    http://www.cpupk.com/decompiler/update/

    離線包下載地址:
    https://github.com/cnfree/Eclipse-Class-Decompiler/releases/download/v2.10.0/eclipse-class-decompiler-update_v2.10.0.zip

     
    插件使用說明:

    下圖為Eclipse Class Decompiler的首選項(xiàng)頁面,可以選擇缺省的反編譯器工具,并進(jìn)行反編譯器的基本設(shè)置。缺省的反編譯工具為JD-Core,JD-Core更為先進(jìn)一些,支持泛型、Enum、注解等JDK1.5以后才有的新語法。

    首選項(xiàng)配置選項(xiàng):
    1.重用緩存代碼:只會(huì)反編譯一次,以后每次打開該類文件,都顯示的是緩存的反編譯代碼。
    2.忽略已存在的源代碼:若未選中,則查看Class文件是否已綁定了Java源代碼,如果已綁定,則顯示Java源代碼,如果未綁定,則反編譯Class文件。若選中此項(xiàng),則忽略已綁定的Java源代碼,顯示反編譯結(jié)果。
    3.顯示反編譯器報(bào)告:顯示反編譯器反編譯后生成的數(shù)據(jù)報(bào)告及異常信息。
    4.使用Eclipse代碼格式化工具:使用Eclipse格式化工具對(duì)反編譯結(jié)果重新格式化排版,反編譯整個(gè)Jar包時(shí),此操作會(huì)消耗一些時(shí)間。
    5.使用Eclipse成員排序:使用Eclipse成員排序?qū)Ψ淳幾g結(jié)果重新格式化排版,反編譯整個(gè)Jar包時(shí),此操作會(huì)消耗大量時(shí)間。
    6.以注釋方式輸出原始行號(hào)信息:如果Class文件包含原始行號(hào)信息,則會(huì)將行號(hào)信息以注釋的方式打印到反編譯結(jié)果中。
    7.根據(jù)行號(hào)對(duì)齊源代碼以便于調(diào)試:若選中該項(xiàng),插件會(huì)采用AST工具分析反編譯結(jié)果,并根據(jù)行號(hào)信息調(diào)整代碼順序,以便于Debug過程中的單步跟蹤調(diào)試。
    8.設(shè)置類反編譯查看器作為缺省的類文件編輯器:默認(rèn)為選中,將忽略Eclipse自帶的Class Viewer,每次Eclipse啟動(dòng)后,默認(rèn)使用本插件提供的類查看器打開Class文件。



    插件提供了系統(tǒng)菜單,工具欄,當(dāng)打開了插件提供的類反編譯查看器后,會(huì)激活菜單和工具欄選項(xiàng),可以方便的進(jìn)行首選項(xiàng)配置,切換反編譯工具重新反編譯,以及導(dǎo)出反編譯結(jié)果。






    類反編譯查看器右鍵菜單包含了Eclipse自帶類查看器右鍵菜單的全部選項(xiàng),并增加了一個(gè)“導(dǎo)出反編譯源代碼”菜單項(xiàng)。



    打開項(xiàng)目路徑下的Class文件,如果設(shè)置類反編譯查看器為缺省的查看器,直接雙擊Class文件即可,如果沒有設(shè)置為缺省查看器,可以使用右鍵菜單進(jìn)行查看。




    同時(shí)插件也支持直接將外部的Class文件拖拽到Eclipse編輯器中進(jìn)行反編譯。


    Eclipse Class Decompiler插件也提供了反編譯整個(gè)Jar文件或者Java包的反編譯。該操作支持Package Explorer對(duì)包顯示布局的操作,如果是平鋪模式布局,則導(dǎo)出的源代碼不包含子包,如果是層級(jí)模式布局,則導(dǎo)出選中的包及其所有的子包。




    Debug調(diào)試:可以在首選項(xiàng)選中對(duì)齊行號(hào)進(jìn)行單步跟蹤調(diào)試,和普通的包含源代碼時(shí)的調(diào)試操作完全一致,同樣的也可以設(shè)置斷點(diǎn)進(jìn)行跟蹤。當(dāng)透視圖為Debug時(shí),插件自動(dòng)生成行號(hào)并進(jìn)行對(duì)齊方便調(diào)試代碼,無需進(jìn)行任何設(shè)置。


    博文地址:http://m.tkk7.com/cnfree/archive/2012/10/30/390457.html
    posted @ 2016-05-13 14:23 三人行,必有我?guī)熝?閱讀(1315) | 評(píng)論 (5)編輯 收藏

    Java應(yīng)用定制工廠(以下簡(jiǎn)稱為JCB,Java Customization Builder)是一個(gè)針對(duì)Java輕量級(jí)桌面應(yīng)用進(jìn)行精簡(jiǎn)優(yōu)化的小工具,使用它可以精簡(jiǎn)你的jar包,并自動(dòng)生成一個(gè)精簡(jiǎn)的JRE,也可以使用它生成一個(gè)Exe啟動(dòng)引導(dǎo)程序,并且能夠?qū)δ愕腏ava應(yīng)用自動(dòng)做Pack200和Unpack200處理。使用本工具定制的Java桌面應(yīng)用通常不會(huì)超過10M(包含JRE),SWT客戶端程序相對(duì)于Swing客戶端程序更小,一般不會(huì)超過5M。

    JCB是一個(gè)Java應(yīng)用,所以目標(biāo)機(jī)器上必須安裝1.5以上版本的JDK用以啟動(dòng)JCB,但是JCB可以用來精簡(jiǎn)1.4版的JRE,并且JRE1.4精簡(jiǎn)后的體積遠(yuǎn)小于1.5以上的版本。

    1.新建JCB項(xiàng)目
    精簡(jiǎn)JRE的步驟比較繁瑣,有可能精簡(jiǎn)失敗,為了不重復(fù)之前的步驟,JCB提供一個(gè)項(xiàng)目文件用來保存精簡(jiǎn)配置信息,擴(kuò)展名為jcprj。這里我們創(chuàng)建一個(gè)項(xiàng)目,名為JCB


    Wizard需要輸入一個(gè)工程名和指定工程位置,至于下面的應(yīng)用程序位置和定制JRE位置由JCB自動(dòng)指定,這兒顯示出來僅供參考。

    此時(shí)最好Ctrl+S保存一下項(xiàng)目,否則退出后你之前的配置信息會(huì)全部丟失,因?yàn)槟悴]有制定一個(gè)可用的項(xiàng)目配置文件。

    2. 配置JCB項(xiàng)目


    首先指定項(xiàng)目需要的jar文件,然后依次選擇項(xiàng)目的main class,啟動(dòng)路徑默認(rèn)為空,一般來說無需指定。然后設(shè)定應(yīng)用程序參數(shù)和虛擬機(jī)參數(shù)。最后選定需要精簡(jiǎn)的JRE,JCB當(dāng)前支持1.4-1.7版本的JRE,未來可能會(huì)支持更高版本的JRE。

    右下角有2個(gè)單選按鈕:全部重新運(yùn)行和增量運(yùn)行。全部重新運(yùn)行就會(huì)放棄之前的運(yùn)行結(jié)果,增量運(yùn)行就是會(huì)保留以前的運(yùn)行結(jié)果。

    然后點(diǎn)擊“以Verbose模式運(yùn)行”按鈕。Verbose模式運(yùn)行Java程序,會(huì)顯示JVM加載的全部類信息,JCB需要這些類信息進(jìn)行JRE的精簡(jiǎn),所以請(qǐng)盡可能的把應(yīng)用所有的功能盡可能的跑一遍,跑的越全面,導(dǎo)致精簡(jiǎn)出錯(cuò)的可能性就越低。



    Verbose運(yùn)行結(jié)果,這個(gè)頁面的顯示信息僅供參考,無實(shí)際用處。

    3. 分析項(xiàng)目的類依賴項(xiàng)


    分析類依賴模式有2個(gè)選項(xiàng):重新完全分析和增量分析。完全分析會(huì)花費(fèi)較多的時(shí)間。當(dāng)使用verbose模式增量運(yùn)行后,可以使用增量模式分析類依賴項(xiàng),這樣可以節(jié)約大量的時(shí)間。類依賴分析會(huì)反編譯所有運(yùn)行的類,分析類引用關(guān)系,但是無法獲取Class.forName這類動(dòng)態(tài)類加載信息,所以需要Verbose模式運(yùn)行的盡量全面,以避免這些動(dòng)態(tài)加載的類的缺失。

    為什么需要分析類依賴關(guān)系呢?因?yàn)椴煌牟僮飨到y(tǒng),不同的硬件配置,JRE可能會(huì)采取策略模式加載不同的類,或者一些異常,Verbose模式一般不會(huì)加載,這樣換個(gè)硬件環(huán)境,僅僅使用Verbose模式的類可能會(huì)導(dǎo)致ClassNotFound這樣的異常,導(dǎo)致Java程序崩潰。


    4. 精簡(jiǎn)JRE


    精簡(jiǎn)JRE有兩種模式:使用Verbose運(yùn)行結(jié)果和使用類依賴分析結(jié)果。前者只包含Verbose分析出來的類,精簡(jiǎn)出來的JRE包很小,但是基本不具備跨平臺(tái)性。所以一般來說推薦選擇后者。

    如果你的程序包含Swing的客戶端,并且比較復(fù)雜的話,最好選中包含Swing選項(xiàng)。因?yàn)镾wing的設(shè)計(jì)完全是動(dòng)態(tài)化的加載,全部使用Class.forName方式,類依賴分析對(duì)Swing是無效的。當(dāng)然選中該選項(xiàng)后,JRE的體積會(huì)增加許多。比較好的解決方案,是使用SWT替代Swing進(jìn)行開發(fā),或者盡量把你的程序跑全面,包括各種異常界面都跑出來。

    右下角有兩個(gè)按鈕,是用來自定義類和資源文件的,比如移除JAR包的MD5文件或者無用的文件。或者測(cè)試運(yùn)行發(fā)現(xiàn)ClassNotFound異常,手動(dòng)把缺少的類加進(jìn)去,然后JCB會(huì)自動(dòng)運(yùn)行增量類依賴分析加載所有可能需要的類。

    選擇左上角的“精簡(jiǎn)Jar包”按鈕,就可以對(duì)JRE進(jìn)行精簡(jiǎn)了,精簡(jiǎn)完畢后可以點(diǎn)擊“查看精簡(jiǎn)結(jié)果”按鈕進(jìn)行查看。

    5.定制JRE


    上圖顯示了JRE精簡(jiǎn)結(jié)果,JCB會(huì)自動(dòng)分析所有的Class,生成精簡(jiǎn)版JRE,包括需要的JAR,DLL和資源文件。一般來說精簡(jiǎn)出來的JRE,普通功能都能正確完成,但是不排除有些功能不能正常使用,比如缺少某個(gè)資源文件或者DLL,需要手工添加。

    為了保證精簡(jiǎn)的正確性,你需要進(jìn)行運(yùn)行測(cè)試,這一步是必須的,而且最好和Verbose運(yùn)行模式一樣,把所有的功能都跑一遍,確認(rèn)精簡(jiǎn)無誤。



    如果測(cè)試運(yùn)行有誤的話,請(qǐng)根據(jù)運(yùn)行錯(cuò)誤報(bào)告進(jìn)行分析,如果缺少類,請(qǐng)使用Verbose模式重新運(yùn)行相應(yīng)的功能,或者在步驟四手工添加需要的類,然后重新生成依賴的JRE。如果缺少相關(guān)的DLL或者資源文件,也請(qǐng)手工添加,并且取消步驟四的“清理工作區(qū)選項(xiàng)”,否則每次精簡(jiǎn)JRE都需要重新手工添加。

    到此為止,精簡(jiǎn)JRE部分就算全部完成了,你最好使用Ctrl+S保存一下結(jié)果,以避免下次重做項(xiàng)目。

    JCB項(xiàng)目下載地址:http://www.sourceforge.net/projects/jcb
    posted @ 2013-03-03 17:25 三人行,必有我?guī)熝?閱讀(5224) | 評(píng)論 (13)編輯 收藏

    1. 40億個(gè)無符號(hào)整數(shù),找出一個(gè)不在這40億個(gè)整數(shù)中的數(shù)。可以換個(gè)方向思考, 99個(gè)小于100的數(shù),找出一個(gè)不在這99個(gè)數(shù)中的小于100的數(shù)。
    首先把這99個(gè)數(shù)分為10組,按高位為0-9分,然后計(jì)算每組的數(shù)量,數(shù)量最少的那個(gè)肯定就是缺失的那個(gè),然后遞歸……找最少的那個(gè),組合起來的數(shù)肯定是缺失的。答案是按位運(yùn)算找,和這個(gè)類似。

    2. 43億個(gè)無符號(hào)整數(shù),找出一個(gè)重復(fù)的整數(shù)。也就是101個(gè)小于100的數(shù),找出重復(fù)的那個(gè)數(shù)來。
    首先把這99個(gè)數(shù)分為10組,按高位為0-9分,然后計(jì)算每組的數(shù)量,數(shù)量最多的那組,肯定有重復(fù)的,一次類推找第二位……
    posted @ 2012-11-24 22:21 三人行,必有我?guī)熝?閱讀(403) | 評(píng)論 (0)編輯 收藏

    When a object creates a new object, please use the dependency.

    When a object just uses a object, please use the association. 
    posted @ 2012-11-19 13:16 三人行,必有我?guī)熝?閱讀(286) | 評(píng)論 (0)編輯 收藏

    comparator 

    Decorator Pattern and Adapter Pattern have the same alias name: wrapper. But they face different aspects. Decorator pattern changes the object function, but the adapter pattern changes the interface.

    The typical decorator pattern is the java OutputStream, you can use the BufferedOutputStream to wrap it, then get the extra function.
    The typical adapter pattern in the BIRT is the ElementAdapter, it can convert any object to an other object.

    Decorator pattern must extend the class which you want to wrap, but the adapter class must implements the interface using by the client.


    FlyWeight pattern extracts the same part of some different objects, and the part doesn't be changed when these objects changed. String class uses the FlyWeight pattern, jface 
    ImageRegistry also uses it. 
    FlyWeight can have a interface to get external data, and change the external data's status, but FlyWeight internal status shouldn't be changed.

    The Collections.sort() method implementation contains template method design pattern and strategy design pattern, but it doesn't contain the visitor design pattern. The Collections.sort() method uses the merge sort algorithm, you can't change it, but you can change the comparator logic, it's one step of the sort algorithm. So it's a template method pattern, but not a classic implementation, it uses the callback method to implement the pattern, but not extending the parent template class. The comparator class use the strategy design pattern, it not a visitor pattern, visitor pattern have a accept method to operate the element to deal some logic. 



    posted @ 2012-11-14 00:22 三人行,必有我?guī)熝?閱讀(329) | 評(píng)論 (0)編輯 收藏

    1 歸并排序(MergeSort)

    歸并排序最差運(yùn)行時(shí)間是O(nlogn),它是利用遞歸設(shè)計(jì)程序的典型例子。

    歸并排序的最基礎(chǔ)的操作就是合并兩個(gè)已經(jīng)排好序的序列。

    假設(shè)我們有一個(gè)沒有排好序的序列,那么首先我們使用分割的辦法將這個(gè)序列分割成一個(gè)一個(gè)已經(jīng)排好序的子序列。然后再利用歸并的方法將一個(gè)個(gè)的子序列合并成排序好的序列。分割和歸并的過程可以看下面的圖例。



    從上圖可以看出,我們首先把一個(gè)未排序的序列從中間分割成2部分,再把2部分分成4部分,依次分割下去,直到分割成一個(gè)一個(gè)的數(shù)據(jù),再把這些數(shù)據(jù)兩兩歸并到一起,使之有序,不停的歸并,最后成為一個(gè)排好序的序列。

    如何把兩個(gè)已經(jīng)排序好的子序列歸并成一個(gè)排好序的序列呢?可以參看下面的方法。

    假設(shè)我們有兩個(gè)已經(jīng)排序好的子序列。
    序列A:1 23 34 65
    序列B:2 13 14 87
    那么可以按照下面的步驟將它們歸并到一個(gè)序列中。

    (1)首先設(shè)定一個(gè)新的數(shù)列C[8]。
    (2)A[0]和B[0]比較,A[0] = 1,B[0] = 2,A[0] < B[0],那么C[0] = 1
    (3)A[1]和B[0]比較,A[1] = 23,B[0] = 2,A[1] > B[0],那么C[1] = 2
    (4)A[1]和B[1]比較,A[1] = 23,B[1] = 13,A[1] > B[1],那么C[2] = 13
    (5)A[1]和B[2]比較,A[1] = 23,B[2] = 14,A[1] > B[2],那么C[3] = 14
    (6)A[1]和B[3]比較,A[1] = 23,B[3] = 87,A[1] < B[3],那么C[4] = 23
    (7)A[2]和B[3]比較,A[2] = 34,B[3] = 87,A[2] < B[3],那么C[5] = 34
    (8)A[3]和B[3]比較,A[3] = 65,B[3] = 87,A[3] < B[3],那么C[6] = 65
    (9)最后將B[3]復(fù)制到C中,那么C[7] = 87。歸并完成。

    如果我們清楚了上面的分割和歸并過程,那么我們就可以用遞歸的方法得到歸并算法的實(shí)現(xiàn)。

        public class MergeSorter
        {
            
    private static int[] myArray;
            
    private static int arraySize;

            
    public static void Sort( int[] a )
            {
                myArray 
    = a;
                arraySize 
    = myArray.Length;
                MergeSort();
            }

            
    /// <summary>
            
    /// 利用歸并的方法排序數(shù)組,首先將序列分割
            
    /// 然后將數(shù)列歸并,這個(gè)算法需要雙倍的存儲(chǔ)空間
            
    /// 時(shí)間是O(nlgn)
            
    /// </summary>
            private static void MergeSort()
            {
                
    int[] temp = new int[arraySize];
                MSort( temp, 
    0, arraySize - 1);
            }

            
    private static void MSort(int[] temp, int left, int right)
            {
                
    int mid;

                
    if (right > left)
                {
                    mid 
    = (right + left) / 2;
                    MSort( temp, left, mid); 
    //分割左邊的序列
                    MSort(temp, mid+1, right);//分割右邊的序列
                    Merge(temp, left, mid+1, right);//歸并序列
                }
            }

            
    private static void Merge( int[] temp, int left, int mid, int right)
            {
                
    int i, left_end, num_elements, tmp_pos;

                left_end 
    = mid - 1;
                tmp_pos 
    = left;
                num_elements 
    = right - left + 1;

                
    while ((left <= left_end) && (mid <= right)) 
                {
                    
    if (myArray[left] <= myArray[mid]) //將左端序列歸并到temp數(shù)組中
                    {
                        temp[tmp_pos] 
    = myArray[left];
                        tmp_pos 
    = tmp_pos + 1;
                        left 
    = left +1;
                    }
                    
    else//將右端序列歸并到temp數(shù)組中
                    {
                        temp[tmp_pos] 
    = myArray[mid];
                        tmp_pos 
    = tmp_pos + 1;
                        mid 
    = mid + 1;
                    }
                }

                
    while (left <= left_end) //拷貝左邊剩余的數(shù)據(jù)到temp數(shù)組中
                {
                    temp[tmp_pos] 
    = myArray[left];
                    left 
    = left + 1;
                    tmp_pos 
    = tmp_pos + 1;
                }
                
    while (mid <= right) //拷貝右邊剩余的數(shù)據(jù)到temp數(shù)組中
                {
                    temp[tmp_pos] 
    = myArray[mid];
                    mid 
    = mid + 1;
                    tmp_pos 
    = tmp_pos + 1;
                }

                
    for (i=0; i < num_elements; i++//將所有元素拷貝到原始數(shù)組中
                {
                    myArray[right] 
    = temp[right];
                    right 
    = right - 1;
                }
            }
        }


    歸并排序算法是一種O(nlogn)的算法。它的最差,平均,最好時(shí)間都是O(nlogn)。但是它需要額外的存儲(chǔ)空間,這在某些內(nèi)存緊張的機(jī)器上會(huì)受到限制。

    歸并算法是又分割和歸并兩部分組成的。對(duì)于分割部分,如果我們使用二分查找的話,時(shí)間是O(logn),在最后歸并的時(shí)候,時(shí)間是O(n),所以總的時(shí)間是O(nlogn)。

    2 堆排序(HeapSort)

    堆排序?qū)儆诎偃f俱樂部的成員。它特別適合超大數(shù)據(jù)量(百萬條記錄以上)的排序。因?yàn)樗⒉皇褂眠f歸(因?yàn)槌髷?shù)據(jù)量的遞歸可能會(huì)導(dǎo)致堆棧溢出),而且它的時(shí)間也是O(nlogn)。還有它并不需要大量的額外存儲(chǔ)空間。

    堆排序的思路是:

    (1)將原始未排序的數(shù)據(jù)建成一個(gè)堆。
    (2)建成堆以后,最大值在堆頂,也就是第0個(gè)元素,這時(shí)候?qū)⒌诹銈€(gè)元素和最后一個(gè)元素交換。
    (3)這時(shí)候?qū)?到倒數(shù)第二個(gè)元素的所有數(shù)據(jù)當(dāng)成一個(gè)新的序列,建一個(gè)新的堆,再次交換第一個(gè)和最后一個(gè)元素,依次類推,就可以將所有元素排序完畢。

    建立堆的過程如下面的圖所示:


    堆排序的具體算法如下:

    public class HeapSorter 
        {
            
    private static int[] myArray;
            
    private static int arraySize;

            
    public static void Sort( int[] a )
            {
                myArray 
    = a;
                arraySize 
    = myArray.Length;
                HeapSort();
            }

            
    private static void HeapSort()
            {
                BuildHeap();            
    //將原始序列建成一個(gè)堆

                
    while ( arraySize > 1 )
                {
                    arraySize
    --;
                    Exchange ( 
    0, arraySize );//將最大值放在數(shù)組的最后
                    DownHeap ( 0 );  //將序列從0到n-1看成一個(gè)新的序列,重新建立堆
                } 
            }

            
    private static void BuildHeap()
            {
                
    for (int v=arraySize/2-1; v>=0; v--)
                    DownHeap ( v );
            }

            
    //利用向下遍歷子節(jié)點(diǎn)建立堆
            private static void DownHeap( int v )
            {
                
    int w = 2 * v + 1;                     // 節(jié)點(diǎn)w是節(jié)點(diǎn)v的第一個(gè)子節(jié)點(diǎn)

                
    while (w < arraySize)
                {
                    
    if ( w+1 < arraySize )        // 如果節(jié)點(diǎn)v下面有第二個(gè)字節(jié)點(diǎn)
                        if ( myArray[w+1> myArray[w] ) 
                            w
    ++;                        // 將子節(jié)點(diǎn)w設(shè)置成節(jié)點(diǎn)v下面值最大的子節(jié)點(diǎn)

                     
    // 節(jié)點(diǎn)v已經(jīng)大于子節(jié)點(diǎn)w,有了堆的性質(zhì),那么返回
                    if ( myArray[v] >= myArray[w] ) 
                        
    return;   
                    
                    Exchange( v, w );     
    // 如果不是,就交換節(jié)點(diǎn)v和節(jié)點(diǎn)w的值
                    v = w;        
                    w 
    = 2 * v + 1;            // 繼續(xù)向下找子節(jié)點(diǎn)
                }
            }

            
    //交換數(shù)據(jù)
            private static void Exchange( int i, int j )
            {
                
    int t = myArray[i];
                myArray[i] 
    = myArray[j];
                myArray[j] 
    = t;
            }
        }    


     

    堆排序主要用于超大規(guī)模的數(shù)據(jù)的排序。因?yàn)樗恍枰~外的存儲(chǔ)空間,也不需要大量的遞歸。

    3 幾種O(nlogn)算法的初步比較

    我們可以從下表看到幾種O(nlogn)算法的效率的區(qū)別。所有的數(shù)據(jù)都使用.Net的Random類產(chǎn)生,每種算法運(yùn)行100次,時(shí)間的單位為毫秒。


    500隨機(jī)整數(shù)5000隨機(jī)整數(shù)20000隨機(jī)整數(shù)
    合并排序0.31251.56257.03125
     Shell排序0.31251.256.875
    堆排序0.468752.18756.71875
    快速排序0.156250.6252.8125

    從上表可以明顯地看出,快速排序是最快的算法。這也就給了我們一個(gè)結(jié)論,對(duì)于一般的應(yīng)用來說,我們總是選擇快速排序作為我們的排序算法,當(dāng)數(shù)據(jù)量非常大(百萬數(shù)量級(jí))我們可以使用堆排序,如果內(nèi)存空間非常緊張,我們可以使用Shell排序。但是這意味著我們不得不損失速度。 

    /******************************************************************************************
     *【Author】:flyingbread
     *【Date】:2007年2月2日
     *【Notice】:
     *1、本文為原創(chuàng)技術(shù)文章,首發(fā)博客園個(gè)人站點(diǎn)(http://flyingbread.cnblogs.com/),轉(zhuǎn)載和引用請(qǐng)注明作者及出處。
     *2、本文必須全文轉(zhuǎn)載和引用,任何組織和個(gè)人未授權(quán)不能修改任何內(nèi)容,并且未授權(quán)不可用于商業(yè)。
     *3、本聲明為文章一部分,轉(zhuǎn)載和引用必須包括在原文中。
     ******************************************************************************************/
    posted @ 2012-11-10 23:18 三人行,必有我?guī)熝?閱讀(616) | 評(píng)論 (2)編輯 收藏

    1 快速排序(QuickSort)

    快速排序是一個(gè)就地排序,分而治之,大規(guī)模遞歸的算法。從本質(zhì)上來說,它是歸并排序的就地版本。快速排序可以由下面四步組成。

    (1) 如果不多于1個(gè)數(shù)據(jù),直接返回。
    (2) 一般選擇序列最左邊的值作為支點(diǎn)數(shù)據(jù)。
    (3) 將序列分成2部分,一部分都大于支點(diǎn)數(shù)據(jù),另外一部分都小于支點(diǎn)數(shù)據(jù)。
    (4) 對(duì)兩邊利用遞歸排序數(shù)列。

    快速排序比大部分排序算法都要快。盡管我們可以在某些特殊的情況下寫出比快速排序快的算法,但是就通常情況而言,沒有比它更快的了。快速排序是遞歸的,對(duì)于內(nèi)存非常有限的機(jī)器來說,它不是一個(gè)好的選擇。 

    2 歸并排序(MergeSort)

    歸并排序先分解要排序的序列,從1分成2,2分成4,依次分解,當(dāng)分解到只有1個(gè)一組的時(shí)候,就可以排序這些分組,然后依次合并回原來的序列中,這樣就可以排序所有數(shù)據(jù)。合并排序比堆排序稍微快一點(diǎn),但是需要比堆排序多一倍的內(nèi)存空間,因?yàn)樗枰粋€(gè)額外的數(shù)組。

    3 堆排序(HeapSort)

    堆排序適合于數(shù)據(jù)量非常大的場(chǎng)合(百萬數(shù)據(jù))。

    堆排序不需要大量的遞歸或者多維的暫存數(shù)組。這對(duì)于數(shù)據(jù)量非常巨大的序列是合適的。比如超過數(shù)百萬條記錄,因?yàn)榭焖倥判颍瑲w并排序都使用遞歸來設(shè)計(jì)算法,在數(shù)據(jù)量非常大的時(shí)候,可能會(huì)發(fā)生堆棧溢出錯(cuò)誤。

    堆排序會(huì)將所有的數(shù)據(jù)建成一個(gè)堆,最大的數(shù)據(jù)在堆頂,然后將堆頂數(shù)據(jù)和序列的最后一個(gè)數(shù)據(jù)交換。接下來再次重建堆,交換數(shù)據(jù),依次下去,就可以排序所有的數(shù)據(jù)。

    4 Shell排序(ShellSort)

    Shell排序通過將數(shù)據(jù)分成不同的組,先對(duì)每一組進(jìn)行排序,然后再對(duì)所有的元素進(jìn)行一次插入排序,以減少數(shù)據(jù)交換和移動(dòng)的次數(shù)。平均效率是O(nlogn)。其中分組的合理性會(huì)對(duì)算法產(chǎn)生重要的影響。現(xiàn)在多用D.E.Knuth的分組方法。

    Shell排序比冒泡排序快5倍,比插入排序大致快2倍。Shell排序比起QuickSort,MergeSort,HeapSort慢很多。但是它相對(duì)比較簡(jiǎn)單,它適合于數(shù)據(jù)量在5000以下并且速度并不是特別重要的場(chǎng)合。它對(duì)于數(shù)據(jù)量較小的數(shù)列重復(fù)排序是非常好的。

    5 插入排序(InsertSort)

    插入排序通過把序列中的值插入一個(gè)已經(jīng)排序好的序列中,直到該序列的結(jié)束。插入排序是對(duì)冒泡排序的改進(jìn)。它比冒泡排序快2倍。一般不用在數(shù)據(jù)大于1000的場(chǎng)合下使用插入排序,或者重復(fù)排序超過200數(shù)據(jù)項(xiàng)的序列。

    6 冒泡排序(BubbleSort)

    冒泡排序是最慢的排序算法。在實(shí)際運(yùn)用中它是效率最低的算法。它通過一趟又一趟地比較數(shù)組中的每一個(gè)元素,使較大的數(shù)據(jù)下沉,較小的數(shù)據(jù)上升。它是O(n^2)的算法。

    7 交換排序(ExchangeSort)和選擇排序(SelectSort)

    這兩種排序方法都是交換方法的排序算法,效率都是 O(n2)。在實(shí)際應(yīng)用中處于和冒泡排序基本相同的地位。它們只是排序算法發(fā)展的初級(jí)階段,在實(shí)際中使用較少。

    8 基數(shù)排序(RadixSort)

    基數(shù)排序和通常的排序算法并不走同樣的路線。它是一種比較新穎的算法,但是它只能用于整數(shù)的排序,如果我們要把同樣的辦法運(yùn)用到浮點(diǎn)數(shù)上,我們必須了解浮點(diǎn)數(shù)的存儲(chǔ)格式,并通過特殊的方式將浮點(diǎn)數(shù)映射到整數(shù)上,然后再映射回去,這是非常麻煩的事情,因此,它的使用同樣也不多。而且,最重要的是,這樣算法也需要較多的存儲(chǔ)空間。

    9 總結(jié)

    下面是一個(gè)總的表格,大致總結(jié)了我們常見的所有的排序算法的特點(diǎn)。
    排序法 平均時(shí)間最差情形穩(wěn)定度額外空間備注
    冒泡 O(n2)  O(n2) 穩(wěn)定O(1)n小時(shí)較好
    交換  O(n2)  O(n2)不穩(wěn)定O(1)n小時(shí)較好
    選擇 O(n2) O(n2)不穩(wěn)定O(1)n小時(shí)較好
    插入 O(n2) O(n2)穩(wěn)定O(1)大部分已排序時(shí)較好
    基數(shù)O(logRB)O(logRB)穩(wěn)定O(n)

    B是真數(shù)(0-9),

    R是基數(shù)(個(gè)十百)

    ShellO(nlogn)O(ns) 1<2不穩(wěn)定O(1)s是所選分組
    快速O(nlogn)O(n2)不穩(wěn)定O(nlogn)n大時(shí)較好
    歸并O(nlogn)O(nlogn)穩(wěn)定O(1)n大時(shí)較好
    O(nlogn)O(nlogn)不穩(wěn)定O(1)n大時(shí)較好

    posted @ 2012-11-10 22:30 三人行,必有我?guī)熝?閱讀(336) | 評(píng)論 (0)編輯 收藏

    Eclipse Class Decompiler是一款Eclipse插件,整合了多種反編譯器,和Eclipse Class Viewer無縫集成,能夠很方便的使用插件查看類庫(kù)源碼,進(jìn)行Debug調(diào)試。
    同時(shí)還提供了在線自動(dòng)查找源代碼,查看Class二進(jìn)制字節(jié)碼的功能。 


    Eclipse Class Decompiler對(duì)JDK的最低要求為JDK1.6, 能反編譯和debug各版本的Class文件,支持JDK8的Lambda語法,同時(shí)支持中文等非Ascii碼字符集的解析,支持Eclipse 3.6及以上所有版本的Eclipse。

    本插件支持Windows,Linux,Macosx 32位及64位操作系統(tǒng)。

    Github項(xiàng)目地址為:https://github.com/cnfree/Eclipse-Class-Decompiler

    請(qǐng)通過以下地址選擇一個(gè)可用的源在線安裝:

    http://cnfree.github.io/Eclipse-Class-Decompiler/update
    http://raw.githubusercontent.com/cnfree/eclipse/master/decompiler/update/
    http://www.cpupk.com/decompiler/update/

    離線包下載地址:
    https://github.com/cnfree/Eclipse-Class-Decompiler/releases/download/v2.10.0/eclipse-class-decompiler-update_v2.10.0.zip
     
    插件使用說明:

    下圖為Eclipse Class Decompiler的首選項(xiàng)頁面,可以選擇缺省的反編譯器工具,并進(jìn)行反編譯器的基本設(shè)置。缺省的反編譯工具為JD-Core,JD-Core更為先進(jìn)一些,支持泛型、Enum、注解等JDK1.5以后才有的新語法。

    首選項(xiàng)配置選項(xiàng):
    1.重用緩存代碼:只會(huì)反編譯一次,以后每次打開該類文件,都顯示的是緩存的反編譯代碼。
    2.忽略已存在的源代碼:若未選中,則查看Class文件是否已綁定了Java源代碼,如果已綁定,則顯示Java源代碼,如果未綁定,則反編譯Class文件。若選中此項(xiàng),則忽略已綁定的Java源代碼,顯示反編譯結(jié)果。
    3.顯示反編譯器報(bào)告:顯示反編譯器反編譯后生成的數(shù)據(jù)報(bào)告及異常信息。
    4.使用Eclipse代碼格式化工具:使用Eclipse格式化工具對(duì)反編譯結(jié)果重新格式化排版,反編譯整個(gè)Jar包時(shí),此操作會(huì)消耗一些時(shí)間。
    5.使用Eclipse成員排序:使用Eclipse成員排序?qū)Ψ淳幾g結(jié)果重新格式化排版,反編譯整個(gè)Jar包時(shí),此操作會(huì)消耗大量時(shí)間。
    6.以注釋方式輸出原始行號(hào)信息:如果Class文件包含原始行號(hào)信息,則會(huì)將行號(hào)信息以注釋的方式打印到反編譯結(jié)果中。
    7.根據(jù)行號(hào)對(duì)齊源代碼以便于調(diào)試:若選中該項(xiàng),插件會(huì)采用AST工具分析反編譯結(jié)果,并根據(jù)行號(hào)信息調(diào)整代碼順序,以便于Debug過程中的單步跟蹤調(diào)試。
    8.設(shè)置類反編譯查看器作為缺省的類文件編輯器:默認(rèn)為選中,將忽略Eclipse自帶的Class Viewer,每次Eclipse啟動(dòng)后,默認(rèn)使用本插件提供的類查看器打開Class文件。



    插件提供了系統(tǒng)菜單,工具欄,當(dāng)打開了插件提供的類反編譯查看器后,會(huì)激活菜單和工具欄選項(xiàng),可以方便的進(jìn)行首選項(xiàng)配置,切換反編譯工具重新反編譯,以及導(dǎo)出反編譯結(jié)果。






    類反編譯查看器右鍵菜單包含了Eclipse自帶類查看器右鍵菜單的全部選項(xiàng),并增加了一個(gè)“導(dǎo)出反編譯源代碼”菜單項(xiàng)。



    打開項(xiàng)目路徑下的Class文件,如果設(shè)置類反編譯查看器為缺省的查看器,直接雙擊Class文件即可,如果沒有設(shè)置為缺省查看器,可以使用右鍵菜單進(jìn)行查看。




    同時(shí)插件也支持直接將外部的Class文件拖拽到Eclipse編輯器中進(jìn)行反編譯。


    Eclipse Class Decompiler插件也提供了反編譯整個(gè)Jar文件或者Java包的反編譯。該操作支持Package Explorer對(duì)包顯示布局的操作,如果是平鋪模式布局,則導(dǎo)出的源代碼不包含子包,如果是層級(jí)模式布局,則導(dǎo)出選中的包及其所有的子包。




    Debug調(diào)試:可以在首選項(xiàng)選中對(duì)齊行號(hào)進(jìn)行單步跟蹤調(diào)試,和普通的包含源代碼時(shí)的調(diào)試操作完全一致,同樣的也可以設(shè)置斷點(diǎn)進(jìn)行跟蹤。當(dāng)透視圖為Debug時(shí),插件自動(dòng)生成行號(hào)并進(jìn)行對(duì)齊方便調(diào)試代碼,無需進(jìn)行任何設(shè)置。


    博文地址:http://m.tkk7.com/cnfree/archive/2012/10/30/390457.html
    posted @ 2012-10-30 13:48 三人行,必有我?guī)熝?閱讀(92518) | 評(píng)論 (43)編輯 收藏

    The original author of the JadClipse project maintains it no more, and the latest build 3.3.0 doesn't support eclipse 4.x, so I download the source code and update it.

    JadClipse for Eclipse 4.x also support Eclipse 3.x, and provides several new features:
     
    1. Integrate jad.exe into the plugin, don't need to set jad path in the preference page again.
    2. Add two options in the JadClipse main preference page:
        (1) Use Eclipse member sorter
        (2) Show decompiler report
    3. Update the formatting preference default settings, the "Output fields before methods" setting's default value changes to true.

    JadClipse for Eclipse 4.x Update Site: http://feeling.sourceforge.net/update

    Offline Archive Update File Download: 
    1. http://feeling.sourceforge.net/downloads/org.sf.feeling.decompiler_1.0.3.zip
    2. http://m.tkk7.com/Files/cnfree/org.sf.feeling.decompiler_1.0.3.zip
    posted @ 2012-10-15 17:45 三人行,必有我?guī)熝?閱讀(7453) | 評(píng)論 (10)編輯 收藏

    http://www.open-open.com/lib/view/1326265166952

    http://blog.chinaunix.net/uid-22342564-id-3183018.html
    posted @ 2012-05-31 02:42 三人行,必有我?guī)熝?閱讀(476) | 評(píng)論 (0)編輯 收藏

    com\maxmpz\audioplayer\widget\listwrappers\D800DC00 這個(gè)package 主要用于 PlayList 模型的操作。

    com\maxmpz\audioplayer\widget\listwrappers\D800DC00\D803DC04.java

    里面有個(gè)
        private static int D801DC01(Activity activity, int i)
        {
            TypedArray typedarray 
    = activity.obtainStyledAttributes(null, com.maxmpz.audioplayer.j.true.p, 00);
            
    int j = typedarray.getResourceId(i, 0);
            typedarray.recycle();
            
    return j;
        }

    Context.obtainStyledAttributes 實(shí)現(xiàn)控件屬性與XML定義綁定的代碼。 

    TypedArray其實(shí)就是一個(gè)存放資源的Array,首先從上下文中獲取到R.styleable。。。這個(gè)屬性資源的資源數(shù)組。 attrs是構(gòu)造函數(shù)傳進(jìn)來,應(yīng)該就是對(duì)應(yīng)attrs.xml文件。 a.getString(R.styleable。。。);這句代碼就是獲取attrs.xml中定義的屬性,并將這個(gè)屬性的值傳給本控件的mValue.最后,返回一個(gè)綁定結(jié)束的信號(hào)給資源:a.recycle();綁定結(jié)束

    相關(guān)學(xué)習(xí)文章:
    http://blog.csdn.net/aomandeshangxiao/article/details/7449973

    com.maxmpz.audioplayer.widget.listwrappers.0xE9 這個(gè)類,用于顯示文件夾列表,右上方有2個(gè)自定義的RadioButton,用來設(shè)置是平鋪模式顯示還是層級(jí)顯示。
    定義了一個(gè)ID為:flat_hier_group 的RadioGroup,里面有個(gè)2個(gè)自定義的RadioButton。

    <RadioGroup android:gravity="right" android:orientation="horizontal" android:id="@id/flat_hier_group" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true"
      xmlns:android
    ="http://schemas.android.com/apk/res/android">
        
    <RadioButton android:id="@id/flat_folders_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="0.0dip" android:button="@drawable/matte_flat_folders_selector" />
        
    <RadioButton android:id="@id/hier_folders_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="-8.0dip" android:button="@drawable/matte_hier_folders_selector" />
    </RadioGroup>

    matte_flat_folders_selector的XML定義為:
     

    <selector
      
    xmlns:android="http://schemas.android.com/apk/res/android">
        
    <item android:state_checked="true" android:drawable="@drawable/matte_flat_folders_selected" />
        
    <item android:state_checked="false" android:drawable="@drawable/matte_flat_folders" />
    </selector>

    自定義的RadioButton實(shí)際上就是張背景透明的圖片罷了。


    播放器列表的Layout布局文件為 list_with_big_header.xml。

    里面有個(gè)android:ellipsize屬性:
    EidtText和textview中內(nèi)容過長(zhǎng)的話自動(dòng)換行,使用android:ellipsize與android:singleine可以解決,使只有一行。EditText不支持marquee

    關(guān)于android:ellipsize屬性更詳細(xì)的文章:http://www.cnblogs.com/chiao/archive/2011/08/20/2147250.html


    里面還有個(gè) android:textAppearance 屬性,這里涉及到了Android的theme和style設(shè)置了,更詳細(xì)的文章參見:http://jiayanjujyj.iteye.com/blog/1392541
    posted @ 2012-05-23 11:59 三人行,必有我?guī)熝?閱讀(426) | 評(píng)論 (0)編輯 收藏

    獲取屏幕Display: Activity.getWindowManager().getDefaultDisplay();
    獲取擴(kuò)展存儲(chǔ)目錄:Environment.getExternalStorageDirectory()
    通過文件獲取Uri:Uri.fromFile(File)
    根據(jù)文件路徑獲取圖片:BitmapFactory.decodeFile(imageFilePath, bmpFactoryOptions)
    獲取相機(jī)Intent:new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    獲取相機(jī)拍照后的圖片:
    Bundle extras = intent.getExtras();
    Bitmap bmp = (Bitmap) extras.get("data");
    觸摸事件:onTouchEvent(MotionEvent ev)
    媒體播放器:android.media.MediaPlayer
    媒體控制器:android.widget.MediaController(和播放器不在同一個(gè)package下)
    SurfaceView是視圖(View)的繼承類,這個(gè)視圖里內(nèi)嵌了一個(gè)專門用于繪制的Surface,類似于Canvas,但感覺比Canvas更高級(jí)。
    android.provider.MediaStore里包含了相關(guān)的Image,Video,Audio信息,可通過managedQuery方法來查詢和遍歷。
    Android中的AdapterView使用Adapter來獲取數(shù)據(jù),和JFace中的ContentProvider對(duì)應(yīng)。
    根據(jù)字符串路徑獲取Uri:
    Uri.parse((String)Path)
    封裝好的視頻View:android.widget.VideoView
    視頻錄制:android.media.MediaRecorder
    相機(jī)高畫質(zhì):CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);


    設(shè)置透明度(這是窗體本身的透明度,非背景)

    WindowManager.LayoutParams lp=getWindow().getAttributes();
                    lp.alpha=0.3f;
                  getWindow().setAttributes(lp);
                    
    alpha在0.0f到1.0f之間。1.0完全不透明,0.0f完全透明


    設(shè)置黑暗度

                    WindowManager.LayoutParams lp=getWindow().getAttributes();
                    lp.dimAmount=0.5f;
                    getWindow().setAttributes(lp);
                    getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);

    dimAmount在0.0f和1.0f之間,0.0f完全不暗,1.0f全暗


    設(shè)置背景模糊

    getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,     
               WindowManager.LayoutParams.FLAG_BLUR_BEHIND);



    //調(diào)用瀏覽器 
    Uri uri = Uri.parse(""); 
    Intent it = new Intent(Intent.ACTION_VIEW,uri); 
    startActivity(it); 

    //顯示某個(gè)坐標(biāo)在地圖上 
    Uri uri = Uri.parse("geo:38.899533,-77.036476"); 
    Intent it = new Intent(Intent.Action_VIEW,uri); 
    startActivity(it); 

    //顯示路徑 
    Uri uri = Uri.parse("http://maps.google.com/maps?f=d&saddr=startLat%20startLng&daddr=endLat%20endLng&hl=en"); 
    Intent it = new Intent(Intent.ACTION_VIEW,URI); 
    startActivity(it); 

    //撥打電話 
    Uri uri = Uri.parse("tel:10086"); 
    Intent it = new Intent(Intent.ACTION_DIAL, uri); 
    startActivity(it); 

    Uri uri = Uri.parse("tel.10086"); 
    Intent it =new Intent(Intent.ACTION_CALL,uri); 
    //需要添加 <uses-permission id="android.permission.CALL_PHONE" /> 這個(gè)權(quán)限到androidmanifest.xml 

    //發(fā)送短信或彩信 
    Intent it = new Intent(Intent.ACTION_VIEW); 
    it.putExtra("sms_body", "The SMS text"); 
    it.setType("vnd.android-dir/mms-sms"); 
    startActivity(it); 

    //發(fā)送短信 
    Uri uri = Uri.parse("smsto:10086"); 
    Intent it = new Intent(Intent.ACTION_SENDTO, uri); 
    it.putExtra("sms_body", "cwj"); 
    startActivity(it); 

    //發(fā)送彩信 
    Uri uri = Uri.parse("content://media/external/images/media/23"); 
    Intent it = new Intent(Intent.ACTION_SEND); 
    it.putExtra("sms_body", "some text"); 
    it.putExtra(Intent.EXTRA_STREAM, uri); 
    it.setType("image/png"); 
    startActivity(it); 

    //發(fā)送郵件 
    Uri uri = Uri.parse("mailto:android123@163.com"); 
    Intent it = new Intent(Intent.ACTION_SENDTO, uri); 
    startActivity(it); 

    Intent it = new Intent(Intent.ACTION_SEND); 
    it.putExtra(Intent.EXTRA_EMAIL, android123@163.com); 
    it.putExtra(Intent.EXTRA_TEXT, "The email body text"); 
    it.setType("text/plain"); 
    startActivity(Intent.createChooser(it, "Choose Email Client")); 

    Intent it=new Intent(Intent.ACTION_SEND); 
    String[] tos={"me@abc.com"}; 
    String[] ccs={"you@abc.com"}; 
    it.putExtra(Intent.EXTRA_EMAIL, tos); 
    it.putExtra(Intent.EXTRA_CC, ccs); 
    it.putExtra(Intent.EXTRA_TEXT, "The email body text"); 
    it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text"); 
    it.setType("message/rfc822"); 
    startActivity(Intent.createChooser(it, "Choose Email Client")); 

    //播放媒體文件 
    Intent it = new Intent(Intent.ACTION_VIEW); 
    Uri uri = Uri.parse("file:///sdcard/cwj.mp3"); 
    it.setDataAndType(uri, "audio/mp3"); 
    startActivity(it); 

    Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1"); 
    Intent it = new Intent(Intent.ACTION_VIEW, uri); 
    startActivity(it); 

    //卸載APK 
    Uri uri = Uri.fromParts("package", strPackageName, null); 
    Intent it = new Intent(Intent.ACTION_DELETE, uri); 
    startActivity(it); 

    //卸載apk 2 
    Uri uninstallUri = Uri.fromParts("package", "xxx", null); 
    returnIt = new Intent(Intent.ACTION_DELETE, uninstallUri); 

    //安裝APK 
    Uri installUri = Uri.fromParts("package", "xxx", null); 
    returnIt = new Intent(Intent.ACTION_PACKAGE_ADDED, installUri); 

    //播放音樂 
    Uri playUri = Uri.parse("file:///sdcard/download/sth.mp3"); 
    returnIt = new Intent(Intent.ACTION_VIEW, playUri); 

    //發(fā)送附近 
    Intent it = new Intent(Intent.ACTION_SEND); 
    it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text"); 
    it.putExtra(Intent.EXTRA_STREAM, "file:///sdcard/cwj.mp3"); 
    sendIntent.setType("audio/mp3"); 
    startActivity(Intent.createChooser(it, "Choose Email Client")); 

    //market上某個(gè)應(yīng)用信,pkg_name就是應(yīng)用的packageName 
    Uri uri = Uri.parse("market://search?q=pname:pkg_name"); 
    Intent it = new Intent(Intent.ACTION_VIEW, uri); 
    startActivity(it); 

    //market上某個(gè)應(yīng)用信息,app_id可以通過www網(wǎng)站看下 
    Uri uri = Uri.parse("market://details?id=app_id"); 
    Intent it = new Intent(Intent.ACTION_VIEW, uri); 
    startActivity(it); 

    //調(diào)用搜索 
    Intent intent = new Intent(); 
    intent.setAction(Intent.ACTION_WEB_SEARCH); 
    intent.putExtra(SearchManager.QUERY,"android123") 
    startActivity(intent); 

    //調(diào)用分享菜單 
    Intent intent=new Intent(Intent.ACTION_SEND); 
    intent.setType("text/plain"); //分享的數(shù)據(jù)類型 
    intent.putExtra(Intent.EXTRA_SUBJECT, "subject"); //主題 
    intent.putExtra(Intent.EXTRA_TEXT, "content"); //內(nèi)容 
    startActivity(Intent.createChooser(intent, "title")); //目標(biāo)應(yīng)用選擇對(duì)話框的標(biāo)題


    獲取Location:
    Criteria criteria = new Criteria();
    criteria.setAccuracy(Criteria.ACCURACY_COARSE);
    criteria.setPowerRequirement(Criteria.POWER_LOW);
    LocationManager locManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    if(locManager.getBestProvider(criteria, true) != null)
    myLocation = locManager.getLastKnownLocation(locManager.getBestProvider(criteria, true));
    else {
    myLocation = new Location("gps");
    myLocation.setLatitude(47.100301);
    myLocation.setLongitude(-119.982465);
    }
    posted @ 2012-05-05 19:41 三人行,必有我?guī)熝?閱讀(850) | 評(píng)論 (0)編輯 收藏


    3.1以下版本升級(jí)到最新版最好先還原到初始檔,然后重新備份一下初始檔。

    如果不希望重新開局,以下提供正確的操作步驟:
    1、進(jìn)入備份與還原界面。
    2、選擇“備份當(dāng)前游戲數(shù)據(jù)“進(jìn)行備份。
    3、選擇“ 還原游戲至初始檔狀態(tài)“進(jìn)行還原。
    4、選擇“設(shè)置當(dāng)前游戲數(shù)據(jù)作為游戲初始檔”進(jìn)行備份。
    5、在還原備份數(shù)據(jù)的列表中選擇步驟2備份的數(shù)據(jù)存檔進(jìn)行還原

    就可以正常進(jìn)入游戲,并且更新了原始檔。


    3.9版更新內(nèi)容:
    1、修正了若干已知Bug。
    2、象兵及戰(zhàn)車數(shù)據(jù)使用兵種第二防御數(shù)據(jù)。
    3、全面更新地圖坐標(biāo)算法,防止無法進(jìn)入游戲或者武將位于山地?zé)o法移動(dòng)。
    4、增加了切換游戲勢(shì)力功能,可以無需開檔游玩任意勢(shì)力。
    5、增加了東州兵和駱駝兵模的防跳補(bǔ)丁。


    3.8版更新內(nèi)容:
    1、增加了解鎖朝廷、在野、亂軍勢(shì)力的功能。
    2、增加了解除諸葛亮外出云游狀態(tài)的腳本補(bǔ)丁,玩家可以使用任何勢(shì)力收買諸葛亮,并且激活三顧茅廬技能。
    3、增加了全勢(shì)力官爵升級(jí)的腳本補(bǔ)丁。
    4、增加了部分武將特殊技能全勢(shì)力激活的腳本補(bǔ)丁。
    5、增加了創(chuàng)建新兵種功能。


    3.7版更新內(nèi)容:
    1、修正了一些細(xì)節(jié)上的bug。
    2、增加了霧隱版呂玲綺衛(wèi)隊(duì)女兵模型的導(dǎo)入。
    3、增加了武將模型作為騎兵模型的導(dǎo)入,并且可自由移除已導(dǎo)入的模型。
    4、步兵的士兵模型可以選擇將軍模型,騎兵的士兵模型可以選擇已導(dǎo)入的將軍模型和霧影女兵模型。

    3.6版更新內(nèi)容:
    1、修正了導(dǎo)入弩兵陷陣營(yíng)戰(zhàn)斗跳出的bug。
    2、修正了收買武將修改器發(fā)生異常的bug。
    3、修正了更換異族武將勢(shì)力游戲跳出的bug。
    4、修改了一些2種勢(shì)力都有的武將相關(guān)的bug。
    5、新建武將后清空武將編輯頁面狀態(tài)。
    6、編輯武將能力頁面新增了編輯武將衛(wèi)隊(duì)經(jīng)驗(yàn)選項(xiàng)。
    7、基本修改頁面增加了所有兵種生產(chǎn)回合、費(fèi)用下調(diào)的修改。
    8、基本修改頁面增加了所有城市建筑生產(chǎn)回合、費(fèi)用下調(diào)的修改。

    3.5版更新內(nèi)容:
    1、修正了兵種修改頁面中兵種名稱顯示錯(cuò)亂的bug,現(xiàn)在很容易分清雇傭兵和城市招募了。
    2、增加了亂軍刷新概率的修改。
    3、增加導(dǎo)入弩騎高順衛(wèi)隊(duì)和弩兵陷陣營(yíng)的功能。

    3.4版更新內(nèi)容:
    1、修正了編輯大眾衛(wèi)隊(duì)武將名字時(shí)會(huì)改變大眾衛(wèi)隊(duì)名稱的bug。
    2、增加了編輯勢(shì)力地圖顏色的功能。
    3、增加了降低敵方所有武將忠誠(chéng)度的功能。
    4、解決游戲中部分武將心灰意冷狀態(tài)下無法被收買的bug。

    3.3版更新內(nèi)容:
    1、修正了一些bug,比如編輯武將坐標(biāo)會(huì)發(fā)生變化的bug。
    2、創(chuàng)建新武將頁面的爵位增加了自定義功能。
    3、難度修改頁面中,增加了禁用電腦驛站加成,禁止電腦生產(chǎn)刺客,以及能夠編輯電腦太守加成幾率的新功能。

    3.2版更新內(nèi)容:
    1、增加了1.9a中特有的馬匹,1.9a特有的馬匹一般沖量都比較大,老版馬匹沖量較小。
    2、修正了武將地圖坐標(biāo)自動(dòng)計(jì)算錯(cuò)誤的bug。我把RGB顏色值寫錯(cuò)了,另外遺漏了森林顏色。
    3、修正了編輯新武將坐標(biāo)和兵模無效生效的bug。
    4、增加了孫劉曹中特殊武將不能被交換到其他勢(shì)力的注釋。

    3.1版更新內(nèi)容:
    1、修正了未對(duì)掌旗官旗幟,城市旗幟,援軍,盟軍旗幟做修改的bug。
    2、修正了編輯武將人物列傳未繁體化,換行的bug。
    3、增加了修改勢(shì)力后代武將姓氏的功能。

    3.0.1版更新內(nèi)容:
    1、更新了壓縮武將圖片的算法,讓武將圖片顯示的更加清晰。
    2、修正了解壓縮更新包,僅支持GBK編碼的bug。

    3.0版更新內(nèi)容:
    1、新增編輯勢(shì)力功能。
    2、修正編輯武將坐標(biāo)可能導(dǎo)致游戲異常的bug。
    3、修正禁止電腦驛站暴兵的bug(此處bug是由于1.9和1.7的驛站代碼不一樣導(dǎo)致的)。
    4、增加了添加勢(shì)力兵種對(duì)兵營(yíng)的要求,提高游戲的可玩性。
    5、增加了對(duì)城墻生命值的修改。
    6、增加了武將身份設(shè)置功能,方便玩家自定義君主或者繼承人。
    7、增加了修改器的自動(dòng)更新功能,3.0及其后續(xù)版本若發(fā)現(xiàn)修改器有新版本,將會(huì)自動(dòng)更新到最新版本。

    注意事項(xiàng):
    因?yàn)?.0版改動(dòng)較大,若使用編輯勢(shì)力功能,請(qǐng)首先還原游戲數(shù)據(jù)到初始狀態(tài),重新做一次原始備份檔,否則編輯勢(shì)力后,無法還原到游戲原始狀態(tài)。


    說明:
    1、修改器安裝文件夾路徑最好不要包含中文或者空格(有個(gè)別用戶因?yàn)橹形暮涂崭衤窂絾栴}無法啟動(dòng)修改器,調(diào)試器會(huì)提示:
    Error occurred during initialization of VM
    java.lang.UnsatisfiedLinkError: no zip in java.library.path


    2、正常情況下,請(qǐng)使用“三國(guó)全面戰(zhàn)爭(zhēng)1.9a修改器”運(yùn)行修改器。

    3、非正常情況下,比如修改器無法啟動(dòng)成功,或者一直處于系統(tǒng)初始化狀態(tài),或者彈出錯(cuò)誤窗口(不包括修改失敗),請(qǐng)使用“三國(guó)全面戰(zhàn)爭(zhēng)1.9a修改器(調(diào)試器)”運(yùn)行修改器。調(diào)試器啟動(dòng)時(shí)會(huì)顯示一個(gè)黑色的dos窗口,如運(yùn)行時(shí)發(fā)生錯(cuò)誤,錯(cuò)誤信息會(huì)打印到黑色dos窗口,請(qǐng)截圖或者復(fù)制錯(cuò)誤信息,發(fā)送到:http://www.1mod.org/thread-37918-1-1.html,我看見后會(huì)及時(shí)修正錯(cuò)誤。

    4、游戲原始備份檔下載地址:http://feeling.sourceforge.net/patch/1.9a/default.zip
    如果你需要恢復(fù)原始數(shù)據(jù),而又未作原始檔備份,可以從此地址下載。
    恢復(fù)原始數(shù)據(jù)的2種方法:
    1、解壓縮后,復(fù)制data目錄下的數(shù)據(jù)文件到游戲中,替換游戲數(shù)據(jù)文件。
    2、復(fù)制壓縮文件到游戲目錄下的/patch/bak目錄下,替換掉你自己的原始備份檔,然后通過修改器恢復(fù)原始備份檔。

    5、關(guān)于殺毒軟件誤報(bào)問題:
    (1)如果是國(guó)產(chǎn)殺毒軟件報(bào)病毒,請(qǐng)你不要抱怨修改器,去抱怨那些垃圾殺毒軟件吧,技術(shù)不過關(guān),老是誤報(bào)。
    (2)如果是國(guó)外知名殺毒軟件報(bào)病毒,比如卡巴斯基,麥咖啡,微軟MSE等等,你可以截圖發(fā)給我。
    (3)推薦使用微軟MSE,口碑不錯(cuò),完全免費(fèi)。


    6、修改需理智,請(qǐng)謹(jǐn)慎修改,方能提高游戲的可玩性。










    下載地址:http://feeling.sourceforge.net/patch/1.9a/patch_1.9a_3.9.zip

    修改器簡(jiǎn)易教程:http://tieba.baidu.com/p/1418490788


    小技巧:
    1.如果希望新建武將成為勢(shì)力君主,可以在創(chuàng)建后和武將勢(shì)力君主交換。
    2.能夠更換所屬勢(shì)力的武將不能有后代,也不能是勢(shì)力君主或者繼承人,如果希望更換這些武將的勢(shì)力,可以先和勢(shì)力內(nèi)的沒有后代的垃圾武將交換一下,讓他們成為自由身,就可以更換武將所屬勢(shì)力了。
    posted @ 2012-01-25 22:57 三人行,必有我?guī)熝?閱讀(119601) | 評(píng)論 (85)編輯 收藏

    關(guān)于PaletteData的生成:
    case Gdip.PixelFormat16bppARGB1555:                                        
    case Gdip.PixelFormat16bppRGB555: 
        paletteData = new PaletteData(0x7C00, 0x3E0, 0x1F); 
    break;
    case Gdip.PixelFormat16bppRGB565: 
        paletteData = new PaletteData(0xF800, 0x7E0, 0x1F); 
    break;
    case Gdip.PixelFormat24bppRGB: 
        paletteData = new PaletteData(0xFF, 0xFF00, 0xFF0000); 
    break;
    case Gdip.PixelFormat32bppRGB:
    case Gdip.PixelFormat32bppARGB: 
        paletteData = new PaletteData(0xFF00, 0xFF0000, 0xFF000000); 
    break;

    32位ImageData中的data是以RGBA的順序存儲(chǔ)的。data[0]:red,data[1]:green,data[2]:blue,data[3]:alpha

    從byte[]中讀取RGB pixel:
    public static int getPixelFromRGBA( int depth, byte[] data )
    {
            switch ( depth )
            {
                case 32 :
                    return ( ( data[0] & 0xFF ) << 24 )
                            + ( ( data[1] & 0xFF ) << 16 )
                            + ( ( data[2] & 0xFF ) << 8 )
                            + ( data[3] & 0xFF );
                case 24 :
                    return ( ( data[0] & 0xFF ) << 16 )
                            + ( ( data[1] & 0xFF ) << 8 )
                            + ( data[2] & 0xFF );
                case 16 :
                    return ( ( data[1] & 0xFF ) << 8 ) + ( data[0] & 0xFF );
                case 8 :
                    return data[0] & 0xFF;
            }
            SWT.error( SWT.ERROR_UNSUPPORTED_DEPTH );
            return 0;
    }

    從pixel中取出RGB值:
    RGB rgb = imagedata.palette.getRGB( pixel );

    生成一個(gè)空的32位圖片:
    ImageData dest = new ImageData( width,
                    height,
                    32,
                    new PaletteData( 0xFF00, 0xFF0000, 0xFF000000 ) );

    24位透明圖片轉(zhuǎn)成32位透明圖片:
        public static ImageData convertToRGBA( ImageData src )
        {
            ImageData dest = new ImageData( src.width,
                    src.height,
                    32,
                    new PaletteData( 0xFF00, 0xFF0000, 0xFF000000 ) );

            for ( int x = 0; x < src.width; x++ )
            {
                for ( int y = 0; y < src.height; y++ )
                {
                    int pixel = src.getPixel( x, y );
                    RGB rgb = src.palette.getRGB( pixel );

                    byte[] rgba = new byte[4];

                    rgba[0] = (byte) rgb.red;
                    rgba[1] = (byte) rgb.green;
                    rgba[2] = (byte) rgb.blue;

                    if ( pixel == src.transparentPixel )
                    {
                        rgba[3] = (byte) ( 0 );
                    }
                    else
                    {
                        rgba[3] = (byte) ( 255 );
                    }
                    dest.setPixel( x, y, getPixelFromRGBA( 32, rgba ) );
                }
            }
            return dest;
        }

    posted @ 2012-01-15 13:49 三人行,必有我?guī)熝?閱讀(3567) | 評(píng)論 (1)編輯 收藏

    SourceForge最近實(shí)在太慢了,忍無可忍,每天浪費(fèi)我大量時(shí)間……終于讓我不得不投向GitHub的懷抱……
    posted @ 2012-01-14 16:33 三人行,必有我?guī)熝?閱讀(2274) | 評(píng)論 (0)編輯 收藏

    JDK1.6的File.createTempFile方法有bug,在我的機(jī)器上第一次調(diào)用該方法需要耗時(shí)5秒時(shí)間,換了好幾個(gè)1.6的版本均有該問題。JDK1.4,1.5則無此問題。

    不一定所有的機(jī)器都有此問題,不過這兒肯定是有問題的,起碼在我的機(jī)器上有問題。
    posted @ 2012-01-13 15:51 三人行,必有我?guī)熝?閱讀(1633) | 評(píng)論 (2)編輯 收藏

    Java應(yīng)用定制工廠(以下簡(jiǎn)稱為JCB,Java Customization Builder)是一個(gè)針對(duì)Java輕量級(jí)桌面應(yīng)用進(jìn)行精簡(jiǎn)優(yōu)化的小工具,使用它可以精簡(jiǎn)你的jar包,并自動(dòng)生成一個(gè)精簡(jiǎn)的JRE,也可以使用它生成一個(gè)Exe啟動(dòng)引導(dǎo)程序,并且能夠?qū)δ愕腏ava應(yīng)用自動(dòng)做Pack200和Unpack200處理。使用本工具定制的Java桌面應(yīng)用通常不會(huì)超過5M(包含JRE),SWT客戶端程序相對(duì)于Swing客戶端程序更小,一般不會(huì)超過3M。

    JCB1.0.3主要功能是可以支持
    添加Exe的版本信息,并且能夠更細(xì)節(jié)的定義Exe的啟動(dòng)行為,比如是否顯示一個(gè)splash窗口,是否優(yōu)先使用精簡(jiǎn)版的jre,以及增加了對(duì)unpack操作的優(yōu)化,讓應(yīng)用程序第一次運(yùn)行啟動(dòng)的更快。同時(shí)也增加了對(duì)系統(tǒng)權(quán)限的支持,不再要求需要管理員權(quán)限才能運(yùn)行軟件,Guest用戶一樣的使用。

    下一個(gè)版本考慮增加一個(gè)Au3的編輯器,具有語法高亮和智能輔助功能,可以讓高級(jí)用戶定制自己的Exe行為。

    軟件主頁:http://jcb.sourceforge.net
    JCB1.0.3下載地址:http://sourceforge.net/projects/jcb/files/JCB_1.0.3.zip/download


    posted @ 2011-12-26 22:13 三人行,必有我?guī)熝?閱讀(1607) | 評(píng)論 (3)編輯 收藏

    在一個(gè)線程中啟動(dòng)了一個(gè)線程鉤子,然后死活拿不到主線程中的消息,全局鉤子就沒問題。折騰了一下午才發(fā)現(xiàn)這個(gè)線程鉤子是在子線程中啟動(dòng)的,GetCurrentThreadId 方法拿到的不是主線程的threadId,自然也就獲取不到主線程的系統(tǒng)消息。Google了好多文章,都沒有提到這一點(diǎn),真TMD郁悶,完全浪費(fèi)我時(shí)間,還以為是我的類庫(kù)寫錯(cuò)了,鬧了半天是調(diào)用的參數(shù)傳的不對(duì)。
    posted @ 2011-12-24 18:58 三人行,必有我?guī)熝?閱讀(1789) | 評(píng)論 (1)編輯 收藏

    同樣的API, IShellFolder遍歷控制面板里面節(jié)點(diǎn)的children,所有的.net代碼都能獲取,所有的非.net代碼都無法獲取???

    本來還以為是代碼的問題,debug一天死活沒找到問題,最后在codeproject上找了十幾個(gè)例子,發(fā)現(xiàn)都一樣的結(jié)果,why? 

    難道僅僅對(duì).net的才開放遍歷的權(quán)限?
    posted @ 2011-12-14 12:35 三人行,必有我?guī)熝?閱讀(1734) | 評(píng)論 (1)編輯 收藏

    1、安裝VS2008
    2、安裝 Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1
    3、修改SDK的SetEnv.cmd的第146行 
    Set "VCTools=%VCRoot%\VC" 為 Set "VCTools=%VCRoot%\VC\Bin"
    4、修改build.bat的環(huán)境配置
    call "C:\Program Files\Microsoft SDKs\Windows\v6.1\Bin\SetEnv" /xp /x86 /Release (不是%PROGRAMFILES%目錄,編譯字幕為綠色,PROGRAMFILES%目錄編譯出來的dll有400多k。)
    call "%PROGRAMFILES%\Microsoft Visual Studio 9.0\VC\vcvarsall.bat"
    posted @ 2011-12-13 13:16 三人行,必有我?guī)熝?閱讀(378) | 評(píng)論 (0)編輯 收藏

    GitHub |  開源中國(guó)社區(qū) |  maven倉(cāng)庫(kù) |  文件格式轉(zhuǎn)換 
    主站蜘蛛池模板: 99re这里有免费视频精品| 亚洲午夜未满十八勿入| 深夜免费在线视频| mm1313亚洲国产精品美女| 精品在线视频免费| 又黄又爽的视频免费看| 精品女同一区二区三区免费播放 | 99精品视频免费观看| 亚洲狠狠综合久久| 久久国产免费观看精品3| 久久亚洲中文字幕精品有坂深雪| 久久国产精品免费视频| 91亚洲va在线天线va天堂va国产 | 亚洲AV无码成人网站在线观看 | 一级女性全黄久久生活片免费| 亚洲国产成人久久精品99| 一级黄色免费大片| 国产亚洲情侣一区二区无码AV | 无码欧精品亚洲日韩一区| 在线免费观看国产| 亚洲伊人久久精品| 日韩免费毛片视频| 免费VA在线观看无码| 国产亚洲精品看片在线观看| a毛看片免费观看视频| 亚洲伊人tv综合网色| 国产精品入口麻豆免费观看| 亚洲中文字幕无码一去台湾| 永久免费观看的毛片的网站| 激情吃奶吻胸免费视频xxxx| 久久久久亚洲精品中文字幕| a毛片免费观看完整| 亚洲色图视频在线观看| 欧美a级成人网站免费| 久久精品国产亚洲av品善| 亚洲性久久久影院| 玖玖在线免费视频| 亚洲一区二区影视| 国产免费AV片无码永久免费| 国产伦精品一区二区免费| 亚洲天堂男人天堂|