javac [ options ] [ sourcefiles ] [ @files ]參數可按任意次序排列。
options
- 命令行選項。
sourcefiles
- 一個或多個要編譯的源文件(例如 MyClass.java)。
@files
- 一個或多個對源文件進行列表的文件。
選項)指定其它目標目錄。 工具讀取用 Java 編程語言編寫的類和接口定義,并將它們編譯成字節碼類文件。javac
有兩種方法可將源代碼文件名傳遞給 javac:
- 如果源文件數量少,在命令行上列出文件名即可。
- 如果源文件數量多,則將源文件名列在一個文件中,名稱間用空格或回車行來進行分隔。然后在 javac 命令行中使用該列表文件名,文件名前冠以 @ 字符。
源代碼文件名稱必須含有
.java
后綴,類文件名稱必須含有.class
后綴,源文件和類文件都必須有識別該類的根名。例如,名為MyClass
的類將寫在名為MyClass.java
的源文件中,并被編譯為字節碼類文件MyClass.class
。內部類定義產生附加的類文件。這些類文件的名稱將內部類和外部類的名稱結合在一起,例如
MyClass$MyInnerClass.class
。應當將源文件安排在反映其包樹結構的目錄樹中。例如,如果將所有的源文件放在 /workspace 中,那么
com.mysoft.mypack.MyClass
的代碼應該在 \workspace\com\mysoft\mypack\MyClass.java 中。缺省情況下,編譯器將每個類文件與其源文件放在同一目錄中。可用 -d 選項(請參閱后面的
當編譯源文件時,編譯器常常需要它還沒有識別出的類型的有關信息。對于源文件中使用、擴展或實現的每個類或接口,編譯器都需要其類型信息。這包括在源文件中沒有明確提及、但通過繼承提供信息的類和接口。
例如,當擴展 java.applet.Applet 時還要用到 Applet 的祖先類:java.awt.Panel 、 java.awt.Container、 java.awt.Component 和 java.awt.Object。
當編譯器需要類型信息時,它將查找定義類型的源文件或類文件。編譯器先在自舉類及擴展類中查找,然后在用戶類路徑中查找。用戶類路徑通過兩種途徑來定義:通過設置 CLASSPATH 環境變量或使用 -classpath 命令行選項。(有關詳細資料,請參閱設置類路徑)。如果使用 -sourcepath 選項,則編譯器在 sourcepath 指定的路徑中查找源文件;否則,編譯器將在用戶類路徑中查找類文件和源文件。可用-bootclasspath 和 -extdirs 選項來指定不同的自舉類或擴展類;參閱下面的聯編選項。
成功的類型搜索可能生成類文件、源文件或兩者兼有。以下是 javac 對各種情形所進行的處理:
- 搜索結果只生成類文件而沒有源文件: javac 使用類文件。
- 搜索結果只生成源文件而沒有類文件: javac 編譯源文件并使用由此生成的類文件。
- 搜索結果既生成源文件又生成類文件: 確定類文件是否過時。若類文件已過時,則 javac 重新編譯源文件并使用更新后的類文件。否則, javac 直接使用類文件。
缺省情況下,只要類文件比源文件舊, javac 就認為它已過時。( -Xdepend 選項指定相對來說較慢但卻比較可靠的過程。)
javac注意: javac 可以隱式編譯一些沒有在命令行中提及的源文件。用 -verbose 選項可跟蹤自動編譯。
為縮短或簡化
javac
命令,可以指定一個或多個每行含有一個文件名的文件。在命令行中,采用 '@' 字符加上文件名的方法將它指定為文件列表。當 javac 遇到以 `@' 字符開頭的參數時,它對那個文件中所含文件名的操作跟對命令行中文件名的操作是一樣的。這使得 Windows 命令行長度不再受限制。例如,可以在名為
sourcefiles
的文件中列出所有源文件的名稱。該文件可能形如:MyClass1.java MyClass2.java MyClass3.java然后可用下列命令運行編譯器:
C:> javac @sourcefiles
編譯器有一批標準選項,目前的開發環境支持這些標準選項,將來的版本也將支持它。還有一批附加的非標準選項是目前的虛擬機實現所特有的,將來可能要有變化。非標準選項以 -X 打頭。
- -classpath 類路徑
- 設置用戶類路徑,它將覆蓋 CLASSPATH 環境變量中的用戶類路徑。若既未指定 CLASSPATH 又未指定 -classpath,則用戶類路徑由當前目錄構成。有關詳細信息,請參閱設置類路徑。
若未指定 -sourcepath 選項,則將在用戶類路徑中查找類文件和源文件。
- -d 目錄
- 設置類文件的目標目錄。如果某個類是一個包的組成部分,則 javac 將把該類文件放入反映包名的子目錄中,必要時創建目錄。例如,如果指定 -d c:\myclasses 并且該類名叫
com.mypackage.MyClass
,那么類文件就叫作c:\myclasses\com\mypackage\MyClass.class
。若未指定 -d 選項,則 javac 將把類文件放到與源文件相同的目錄中。
注意: -d 選項指定的目錄不會被自動添加到用戶類路徑中。
- -deprecation
- 顯示每種不鼓勵使用的成員或類的使用或覆蓋的說明。沒有給出 -deprecation 選項的話, javac 將顯示這類源文件的名稱:這些源文件使用或覆蓋不鼓勵使用的成員或類。
- -encoding
- 設置源文件編碼名稱,例如
EUCJIS/SJIS
。若未指定 -encoding 選項,則使用平臺缺省的轉換器。- -g
- 生成所有的調試信息,包括局部變量。缺省情況下,只生成行號和源文件信息。
- -g:none
- 不生成任何調試信息。
- -g:{關鍵字列表}
- 只生成某些類型的調試信息,這些類型由逗號分隔的關鍵字列表所指定。有效的關鍵字有:
- source
- 源文件調試信息
- lines
- 行號調試信息
- vars
- 局部變量調試信息
- -nowarn
- 禁用警告信息。
- -O
- 優化代碼以縮短執行時間。使用 -O 選項可能使編譯速度下降、生成更大的類文件并使程序難以調試。
在 JDK 1.2 以前的版本中,javac 的 -g 選項和 -O 選項不能一起使用。在 JDK 1.2 中,可以將 -g 和 -O 選項結合起來,但可能會得到意想不到的結果,如丟失變量或重新定位代碼或丟失代碼。-O 選項不再自動打開 -depend 或關閉 -g 選項。同樣, -O 選項也不再允許進行跨類內嵌。
- -sourcepath 源路徑
- 指定用以查找類或接口定義的源代碼路徑。與用戶類路徑一樣,源路徑項用分號 (;) 進行分隔,它們可以是目錄、JAR 歸檔文件或 ZIP 歸檔文件。如果使用包,那么目錄或歸檔文件中的本地路徑名必須反映包名。
注意:通過類路徑查找的類,如果找到了其源文件,則可能會自動被重新編譯。
- -verbose
- 冗長輸出。它包括了每個所加載的類和每個所編譯的源文件的有關信息。
缺省情況下,類是根據與 javac 一起發行的 JDK 自舉類和擴展類來編譯。但 javac 也支持聯編,在聯編中,類是根據其它 Java平臺實現的自舉類和擴展類來進行編譯的。聯編時, -bootclasspath 和 -extdirs 的使用很重要;請參閱下面的聯編程序示例。
- -target 版本
- 生成將在指定版本的虛擬機上運行的類文件。缺省情況下生成與 1.1 和 1.2 版本的虛擬機都兼容的類文件。JDK 1.2 中的 javac 所支持的版本有:
- 1.1
- 保證所產生的類文件與 1.1 和 1.2 版的虛擬機兼容。這是缺省狀態。
- 1.2
- 生成的類文件可在 1.2 版的虛擬機上運行,但不能在 1.1 版的虛擬機上運行。
- -bootclasspath 自舉類路徑
- 根據指定的自舉類集進行聯編。和用戶類路徑一樣,自舉類路徑項用分號 (;) 進行分隔,它們可以是目錄、JAR 歸檔文件或 ZIP 歸檔文件。
- -extdirs 目錄
- 根據指定的擴展目錄進行聯編。目錄是以分號分隔的目錄列表。在指定目錄的每個 JAR 歸檔文件中查找類文件。
- -X
- 顯示非標準選項的有關信息并退出。
- -Xdepend
- 遞歸地搜索所有可獲得的類,以尋找要重編譯的最新源文件。該選項將更可靠地查找需要編譯的類,但會使編譯進程的速度大為減慢。
- -Xstdout
- 將編譯器信息送到
System.out
中。缺省情況下,編譯器信息送到System.err
中。- -Xverbosepath
- 說明如何搜索路徑和標準擴展以查找源文件和類文件。
- -J選項
- 將選項傳給 javac 調用的 java 啟動器。例如, -J-Xms48m 將啟動內存設為 48 兆字節。雖然它不以 -X 開頭,但它并不是 javac 的‘標準選項’。用 -J 將選項傳給執行用 Java 編寫的應用程序的虛擬機是一種公共約定。
注意: CLASSPATH 、 -classpath 、 -bootclasspath 和 -extdirs 并 不 指定用于運行 javac 的類。如此濫用編譯器的實現通常沒有任何意義而且總是很危險的。如果確實需要這樣做,可用 -J 選項將選項傳給基本的 java 啟動器。
一個源文件
Hello.java
,它定義了一個名叫 greetings.Hello 的類。greetings
目錄是源文件和類文件兩者的包目錄,且它不是當前目錄。這讓我們可以使用缺省的用戶類路徑。它也使我們沒必要用 -d 選項指定單獨的目標目錄。C:> dir greetings/ C:> dir greetings Hello.java C:> cat greetings\Hello.java package greetings; public class Hello { public static void main(String[] args) { for (int i=0; i < args.length; i++) { System.out.println("Hello " + args[i]); } } } C:> javac greetings\Hello.java C:> dir greetings Hello.class Hello.java C:> java greetings.Hello World Universe Everyone Hello World Hello Universe Hello Everyone
該示例編譯
greetings
包中的所有源文件。C:> dir greetings\ C:> dir greetings Aloha.java GutenTag.java Hello.java Hi.java C:> javac greetings\*.java C:> dir greetings Aloha.class GutenTag.class Hello.class Hi.class Aloha.java GutenTag.java Hello.java Hi.java
對前面示例中的某個源文件進行更改后,重新編譯它:
C:> cd \examples C:> javac greetings\Hi.java由于
greetings.Hi
引用了greetings
包中其它的類,編譯器需要找到這些其它的類。上面的示例能運行是因為缺省的用戶類路徑剛好是含有包目錄的目錄。但是,假設我們想重新編譯該文件并且不關心我們在哪個目錄中的話, 我們需要將\examples
添加到用戶類路徑中。可以通過設置 CLASSPATH 達到此目的,但這里我們將使用 -classpath 選項來完成。C:>javac -classpath \examples \examples\greetings\Hi.java如果再次將
greetings.Hi
改為使用標題實用程序,該實用程序也需要通過用戶類路徑來進行訪問:C:>javac -classpath \examples:\lib\Banners.jar \ \examples\greetings\Hi.java要執行
greetings
中的類,需要訪問greetings
和它所使用的類。C:>java -classpath \examples:\lib\Banners.jar greetings.Hi
將源文件和類文件置于不同的目錄下經常是很有意義的,特別是在大型的項目中。我們用 -d 選項來指明單獨的類文件目標位置。由于源文件不在用戶類路徑中,所以用 -sourcepath 選項來協助編譯器查找它們。
C:> dir classes\ lib\ src\ C:> dir src farewells\ C:> dir src\farewells Base.java GoodBye.java C:> dir lib Banners.jar C:> dir classes C:> javac -sourcepath src -classpath classes:lib\Banners.jar \ src\farewells\GoodBye.java -d classes C:> dir classes farewells\ C:> dir classes\farewells Base.class GoodBye.class注意:編譯器也編譯了
src\farewells\Base.java
,雖然我們沒有在命令行中指定它。要跟蹤自動編譯,可使用 -verbose 選項。
這里我們用 JDK 1.2 的 javac 來編譯將在 1.1 版的虛擬機上運行的代碼。
C:> javac -target 1.1 -bootclasspath jdk1.1.7\lib\classes.zip \ -extdirs "" OldCode.java-target 1.1
JDK 1.2 javac 在缺省狀態下也將根據 1.2 版的自舉類來進行編譯,因此我們需要告訴 javac 讓它根據 JDK 1.1 自舉類來進行編譯。可用 -bootclasspath 和 -extdirs 選項來達到此目的。不這樣做的話,可能會使編譯器根據 1.2 版的 API 來進行編譯。由于 1.1 版的虛擬機上可能沒有該 1.2 版的 API,因此運行時將出錯。
選項可確保生成的類文件與 1.1 版的虛擬機兼容。在 JDK1.2 中, 缺省情況下 javac 編譯生成的文件是與 1.1 版的虛擬機兼容的,因此并非嚴格地需要該選項。然而,由于別的編譯器可能采用其它的缺省設置,所以提供這一選項將不失為是個好習慣。
Java命令行命令詳解
rmic
功能說明:
rmic 為遠程對象生成 stub 和 skeleton。
語法:
rmic [ options ] package-qualified-class-name(s)
補充說明:
rmic 編譯器根據編譯后的 Java 類(含有遠程對象實現)名,為遠程對象生成 stub 和 skeleton(遠程對象是指實現 java.rmi.Remote 接口的對象)。在 rmic 命令中所給的類必須是經 javac 命令成功編譯且是完全包限定的類。
命令選項
-classpath[路徑] 指定 rmic 用于查詢類的路徑。如果設置了該選項,它將覆蓋缺省值或 CLASSPATH 環境變量。目錄用冒號分隔。
-d[目錄] 指定類層次的根目錄。此選項可用來指定 stub 和 skeleton 文件的目標目錄。
-depend 使編譯器考慮重新編譯從其它類引用的類。 一般來說,它只重新編譯從源代碼引用的遺漏或過期的類。
-g 允許生成調試表格。調試表格含有行號和局部變量的有關信息,即 Java 調試工具所使用的信息。缺省情況下,只生成行號。
-J 與 -D 選項聯用,它將緊跟其后的選項( -J 與 -D 之間無空格)傳給 java 解釋器。
-keepgenerated 為 stub 和 skeleton 文件保留所生成的 .java 源文件,并將這些源文件寫到與 .class 文件相同的目錄中,如果要指定目錄,則使用 -d 選項。
-nowarn 關閉警告。如果使用該選項,則編譯器不輸出任何警告信息。
-show 顯示 rmic 編譯器的 GUI(圖形用戶界面)。輸入一個或多個包限定類名(以空格分隔),并按回車鍵或“顯示”按鈕,創建 stub 和 skeleton。
-vcompat (缺省值)創建與 JDK 1.1 和 1.2 stub 協議版本都兼容的 stub 和 skeleton。
-verbose 使編譯器和鏈接器輸出關于正在編譯哪些類和正在加載哪些類文件的信息。
-v1.1 創建 JDK 1.1 stub 協議版本的 stub 和 skeleton。
-v1.2 只創建 JDK 1.2 stub 協議版本的 stub。
rmid
功能說明:
rmid 啟動激活系統守護進程,以便能夠在 Java 虛擬機上注冊和激活對象。
語法:
rmid [-port port] [-log dir]
補充說明:
rmid 工具啟動激活系統守護進程。必須先啟動激活系統守護進程,才能向激活系統注冊可被激活的對象或在 Java 虛擬機上激活可被激活的對象。
命令選項
-C<某些命令行選項> 指定一個選項,在創建每個 rmid 的子守護進程(激活組)時,該選項以命令行參數的形式傳給該子守護進程。
-log[目錄] 指定目錄的名稱,激活系統守護進程在該目錄中寫入其數據庫及相關信息。缺省狀態下,將在執行 rmid 命令的目錄中創建一個 log 目錄。
-port[端口] 指定 rmid 的注冊服務程序所使用的端口。激活系統守護進程將 ActivationSystem 與該注冊服務程序中的名稱java.rmi.activation.ActivationSystem 捆綁在一起。
-stop 停止 -port 選項所指定端口上的當前 rmid 調用。若未指定端口,則將停止在端口 1098 上運行的 rmid。
rmiregistry
功能說明:
rmiregistry 命令可在當前主機的指定端口上啟動遠程對象注冊服務程序。
語法:
rmiregistry [port]
補充說明:
rmiregistry 命令在當前主機的指定 port 上創建并啟動遠程對象注冊服務程序。如果省略 port,則注冊服務程序將在 1099 端口上啟動。rmiregistry 命令不產生任何輸出而且一般在后臺運行。遠程對象注冊服務程序是自舉命名服務。主機上的 RMI 服務器將利用它將遠程對象綁定到名字上。客戶機即可查詢遠程對象并進行遠程方法調用。注冊服務程序一般用于定位應用程序需調用其方法的第一個遠程對象。該 對象反過來對各應用程序提供相應的支持,用于查找其它對象。
java.rmi.registry.LocateRegistry 類的方法可用于在某臺主機或主機和端口上獲取注冊服務程序操作。java.rmi.Naming 類的基于 URL 的方法將對注冊服務程序進行操作,并可用于查詢遠程對象、將簡單(字符串)名稱綁定到遠程對象、將新名稱重新綁定到遠程對象(覆蓋舊綁定)、取消遠程對象 的綁定以及列出綁定在注冊服務程序上的 URL。
serialver
功能說明:
serialver 命令返回 serialVersionUID。
語法:
serialver [ 命令選項 ]
補充說明:
serialver 以適于復制到演變類的形式返回一個或多個類的 serialVersionUID。不帶參數調用時,它輸出用法行。
命令選項
-show 顯示一個簡單的用戶界面。輸入完整的類名并按回車鍵或“顯示”按鈕可顯示 serialVersionUID。
jarsigner
功能說明:
為 Java 歸檔 (JAR) 文件產生簽名,并校驗已簽名的 JAR 文件的簽名。
語法:
jarsigner [ 命令選項 ] jar-file alias
jarsigner -verify [ 命令選項 ] jar-file
補充說明:
jarsigner 工具用于兩個目的:
1:為 Java 歸檔 (JAR) 文件簽名
2:校驗已簽名的 JAR 文件的簽名和完整性
命令選項
-keystore[url] 指定密鑰倉庫的 URL。缺省值是用戶的宿主目錄中的 .keystore 文件,它由系統屬性“user.home”決定。
-storetype[storetype] 指定要被實例化的密鑰倉庫類型。默認的密鑰倉庫類型是安全屬性文件中 "keystore.type" 屬性值所指定的那個類型,由 java.security.KeyStore 中的靜態方法 getDefaultType 返回。
-storepass[password] 指定訪問密鑰倉庫所需的口令。這僅在簽名(不是校驗)JAR 文件時需要。在這種情況下,如果命令行中沒有提供 -storepass 選項,用戶將被提示輸入口令。
-keypass[password] 指定用于保護密鑰倉庫項(由命令行中指定的別名標出)的私鑰的口令。使用 jarsigner 為 JAR 文件簽名時需要該口令。如果命令行中沒有提供口令,且所需的口令與密鑰倉庫的口令不同,則將提示用戶輸入它。
-sigfile[file] 指定用于生成 .SF 和 .DSA 文件的基本文件名。
-signedjar[file] 指定用于已簽名的 JAR 文件的名稱。
-verify 如果它出現在命令行中,則指定的 JAR 文件將被校驗,而不是簽名。如果校驗成功,將顯示“jar verified”。如果試圖校驗未簽名的 JAR 文件,或校驗被不支持的算法(例如未安裝 RSA 提供者時使用的 RSA)簽名的 JAR 文件,則將有如下顯示: "jar is unsigned. (signatures missing or not parsable)" 。
-certs 如果它與 -verify 和 -verbose 選項一起出現在命令行中,則輸出將包括 JAR 文件的每個簽名人的證書信息。
-verbose 如果它出現在命令行中,則代表“verbose”模式,它使 jarsigner 在 JAR 簽名或校驗過程中輸出額外信息。
-internalsf 過去,JAR 文件被簽名時產生的 .DSA(簽名塊)文件包含一個同時產生的 .SF 文件(簽名文件)的完整編碼副本。這種做法已被更改。為了減小輸出 JAR 文件的整個大小,缺省情況下 .DSA 文件不再包含 .SF 文件的副本。但是如果 -internalsf 出現在命令行中,將采用舊的做法。該選項主要在測試時有用;實際上不應使用它,因為這樣將消除有用的優化。
-sectionsonly 如果它出現在命令行中,則 JAR 文件被簽名時生成的 .SF 文件(簽名文件)將不包括含有整個清單文件的散列的頭。它僅包含 與 JAR 中每個單獨的源文件相關的信息和散列。該選項主要在測試時有用;實際上不應使用它,因為這樣將消除有用的優化。
-J [javaoption] 將指定的 javaoption 串直接傳遞到 Java 解釋器。((jarsigner 實際上是解釋器的一個 “wrapper”)。該選項不應含有任何空格。它有助于調整執行環境或內存使用。要獲得可用的解釋器選項的清單,可在命令行鍵入 java -h 或 java -X。
keytool
功能說明:
管理由私鑰和認證相關公鑰的 X.509 證書鏈組成的密鑰倉庫(數據庫)。還管理來自可信任實體的證書。
語法:
keytool [ 命令 ]
補充說明:
keytool 是個密鑰和證書管理工具。它使用戶能夠管理自己的公鑰/私鑰對及相關證書,用于(通過數字簽名)自我認證(用戶向別的用戶/服務認證自己)或數據完整性以及認證服務。它還允許用戶儲存他們的通信對等者的公鑰(以證書形式)。
native2ascii
功能說明:
將含有本地編碼字符(既非 Latin1 又非 Unicode 字符)的文件轉換為 Unicode 編碼字符的文件。
語法:
native2ascii [options] [inputfile [outputfile]]
補充說明:
Java 編譯器和其它 Java 工具只能處理含有 Latin-1 和/或 Unicode 編碼(udddd 記號)字符的文件。native2ascii 將含有其它字符編碼的文件轉換成含 Latin-1 和/或 Unicode 編碼字符的文件。若省略 outputfile,則使用標準輸出設備輸出。此外,如果也省略 inputfile,則使用標準輸入設備輸入。
命令選項
-reverse 執行相反的操作:將含 Latin-1 和/或 Unicode 編碼字符的文件轉換成含本地編碼字符的文件。
-encoding[encoding_name] 指定轉換過程使用的編碼名稱。缺省的編碼從系統屬性 file.encoding 中得到。
appletviewer
功能說明:
Java applet 瀏覽器。appletviewer 命令可在脫離萬維網瀏覽器環境的情況下運行 applet。
語法:
appletviewer [ threads flag ] [ 命令選項 ] urls ...
補充說明:
appletviewer 命令連接到 url 所指向的文檔或資源上,并在其自身的窗口中顯示文檔引用的每個 applet。注意:如果 url 所指向的文檔不引用任何帶有 OBJECT、EMBED 或 APPLET 標記的 applet,那么 appletviewer 就不做任何事情。
命令選項
-debug 在 Java 調試器 jdb 中啟動 appletviewer,使您可以調試文檔中的 applet。
-encoding[編碼名稱] 指定輸入 HTML 文件的編碼名稱。
-J[javaoption] 將 javaoption 字符串作為單個參數傳給運行 appletviewer 的 Java 解釋器。參數不能含有空格。由多重參數組成的字符串,其中的每個參數都必須以前綴 -J 開頭,該前綴以后將被除去。這在調整編譯器的執行環境或內存使用時將很有用。
extcheck
功能說明:
extcheck 檢測目標 jar 文件與當前安裝方式擴展 jar 文件間的版本沖突。
語法:
extcheck [ -verbose ] targetfile.jar
補充說明:
extcheck 實用程序檢查指定 Jar 文件的標題和版本與 JDK TM 軟件中所安裝的擴展是否有沖突。在安裝某個擴展前,可以用該實用程序查看是否已安裝了該擴展的相同版本或更高的版本。
extcheck 實用程序將 targetfile.jar 文件清單的 specification-title 和 specification-version 頭與當前安裝在擴展目錄下所有 Jar 文件的相對應的頭進行比較(缺省擴展目錄為 jre/lib/ext)。extcheck 實用程序比較版本號的方式與 java.lang.Package.isCompatibleWith 方法相同。若未檢測到沖突,則返回代碼為 0。如果擴展目錄中任何一個 jar 文件的清單有相同的 specification-title 和相同的或更新的 specification-version 號,則返回非零錯誤代碼。如果 targetfile.jar 的清單中沒有 specification-title 或 specification-version 屬性,則同樣返回非零錯誤代碼。
命令選項
-verbose 對擴展目錄中的 Jar 文件進行檢查時,列出文件。此外,還報告目標 jar 文件的清單屬性及所有沖突的 jar 文件。
jar
功能說明:
Java歸檔工具
語法:
jar [ 命令選項 ] [manifest] destination input-file [input-files]
補充說明:
jar工具是個java應用程序,可將多個文件合并為單個JAR歸檔文件。jar是個多用途的存檔及壓縮工具,它基于ZIP和ZLIB壓縮格式。然而, 設計jar的主要目的是便于將java applet或應用程序打包成單個歸檔文件。將applet或應用程序的組件(.class 文件、圖像和聲音)合并成單個歸檔文件時,可以用java代理(如瀏覽器)在一次HTTP事務處理過程中對它們進行下載,而不是對每個組件都要求一個新連 接。這大大縮短了下載時間。jar還能壓縮文件,從而進一步提高了下載速度。此外,它允許applet的作者對文件中的各個項進行簽名,因而可認證其來 源。jar工具的語法基本上與tar命令的語法相同。
命令選項
-c 在標準輸出上創建新歸檔或空歸檔。
-t 在標準輸出上列出內容表。
-x[file] 從標準輸入提取所有文件,或只提取指定的文件。如果省略了file,則提取所有文件;否則只提取指定文件。
-f 第二個參數指定要處理的jar文件。在-c(創建)情形中,第二個參數指的是要創建的jar文件的名稱(不是在標準輸出上)。在-t(表(或-x(抽取)這兩種情形中,第二個參數指定要列出或抽取的jar文件。
-v 在標準錯誤輸出設備上生成長格式的輸出結果。
-m 包括指定的現有清單文件中的清單信息。用法舉例:“jar cmf myManifestFile myJarFile *.class”
-0 只儲存,不進行 ZIP 壓縮。
-M 不創建項目的清單文件。
-u 通過添加文件或更改清單來更新現有的 JAR 文件。例如:“jar -uf foo.jar foo.class”將文件 foo.class 添加到現有的JAR文件foo.jar中,而“jar umf manifest foo.jar”則用manifest中的信息更新foo.jar的清單。
-C 在執行 jar 命令期間更改目錄。例如:“jar -uf foo.jar -C classes *”將classes目錄內的所有文件加到foo.jar中,但不添加類目錄本身。
程序示例
1:將當前目錄下所有CLASS文件打包成新的JAR文件:
jar cf file.jar *.class
2:顯示一個JAR文件中的文件列表
jar tf file.jar
3:將當前目錄下的所有文件增加到一個已經存在的JAR文件中
jar cvf file.jar *
javadoc
功能說明
Java API文檔生成器從Java源文件生成API文檔HTML頁。
語法:
javadoc [ 命令選項 ] [ 包名 ] [ 源文件名 ] [ @files ]
其中[ 包名 ]為用空格分隔的一系列包的名字,包名不允許使用通配符,如(*)。[ 源文件名 ]為用空格分隔的一系列的源文件名,源文件名可包括路徑和通配符,如(*)。[ @files ]是以任何次序包含包名和源文件的一個或多個文件。
補充說明
Javadoc解析Java源文件中的聲明和文檔注釋,并產生相應的HTML頁缺省),描述公有類、保護類、內部類、接口、構造函數、方法和域。
在實現時,Javadoc要求且依賴于java編譯器完成其工作。Javadoc調用部分javac編譯聲明部分,忽略成員實現。它建立類的內容豐富的 內部表示,包括類層次和“使用”關系,然后從中生成HTML。Javadoc還從源代碼的文檔注釋中獲得用戶提供的文檔。
當Javadoc建立其內部文檔結構時,它將加載所有引用的類。由于這一點,Javadoc必須能查找到所有引用的類,包括引導類、擴展類和用戶類。
命令選項
-overview i>path/filename 指定javadoc應該從path/filename所指定的“源”文件中獲取概述文檔,并將它放到概述頁中(overview- summary.html)。其中path/filename 是相對于-sourcepath的相對路徑名。
-public 只顯示公有類及成員。
-protected 只顯示受保護的和公有的類及成員。這是缺省狀態。
-package 只顯示包、受保護的和公有的類及成員。
-private 顯示所有類和成員。
-help 顯示聯機幫助,它將列出這些javadoc和doclet命令行選項。
-doclet class 指定啟動用于生成文檔的docle 的類文件。該doclet定義了輸出的內容和格式。如果未使用-doclet選項,則javadoc使用標準doclet生成缺省HTML格式。該類必須 包含start(Root)法。該啟動類的路徑由 -docletpath選項定義。
-docletpath classpathlist 指定doclet類文件的路徑,該類文件用-doclet選項指定。如果doclet已位于搜索路徑中,則沒有必要使用該選項。
-1.1 生成具有用Javadoc 1.1生成的文檔的外觀和功能的文檔。也就是說,頁的背景為灰色,用圖像做頁眉,使用bullet列表而不是表格,具有單層目的目錄結構,不包含繼承 API,不使?*** TML框架,并且不支持內部類。該選項還自動將索引分割成每個字母一個文件。如果想要這種外觀,則該選項比javadoc 1.1優越之處等于修正了一些錯誤。
-sourcepath sourcepathlist
當將包名傳遞到 javadoc命令中時,指定定位源文件(.java)的搜索路徑。注意只有當用 javadoc命令指定包名時才能使用sourcepath選項 -- 它將不會查找傳遞到javadoc命令中的.java文件。如果省略-sourcepath,則javadoc使用類路徑查找源文件。
-classpath classpathlist 指定javadoc將在其中查找引用類的路徑 -- 引用類是指帶文檔的類加上它們引用的任何類。Javadoc將搜索指定路徑的所有子目錄。classpathlist可以包括多個路徑,彼此用逗號分隔。
-bootclasspath classpathlist 指定自舉類所在路徑。它們名義上是Java平臺類。這個bootclasspath是Javadoc將用來查找源文件和類文件的搜索路徑的一部分。在 classpathlist中用冒號(:)分隔目錄。
-extdirs dirlist 指定擴展類所在的目錄。它們是任何使用Java擴展機制的類。這個 extdirs是Javadoc將用來查找源文件和在文件的搜索路徑的一部分。在dirlist中用冒號(:)分隔目錄。
-verbose 在javadoc運行時提供更詳細的信息。不使用verbose選項時,將顯示加載源文件、生成文檔(每個源文件一條信息)和排序的信息。verbose選項導致打印額外的信息,指定解析每個java源文件的毫秒數。
-locale language_country_variant 指定javadoc在生成文檔時使用的環境。
-encoding name 指定源文件編碼名,例如EUCJIS/SJIS。如果未指定該選項,則使用平臺缺省轉換器。
-J[flag] 將flag直接傳遞給運行javadoc的運行時系統java。注意在J和flag之間不能有空格。
標準 Doclet 提供的選項
-d directory 指定javadoc保存生成的HTML件的目的目錄。省略該選項將導致把文件保存到當前目錄中。其中directory可以是絕對路徑或相對當前工作目錄的相對路徑。
-use 對每個帶文檔類和包包括一個“用法”頁。該頁描述使用給定類或包的任何 API 的包、類、方法、構造函數和域。對于給定類 C,使用類 C 的任何東西將包括 C 的子類、聲明為 C 的域、返回 C 的方法以及具有 C 類型參數的方法和構造函數。
-version 在生成文檔中包括 @version 文本。缺省地將省略該文本。
-author 在生成文檔中包括 @author 文本。
-splitindex 將索引文件按字母分割成多個文件,每個字母一個文件,再加上一個包含所有以非字母字符開頭的索引項的文件。
-windowtitle[title] 指定放入 HTML
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/smile_dyf/archive/2008/09/04/2882247.aspx
轉自:http://www.aygfsteel.com/Todd/archive/2009/09/15/295112.html
方法一:在初始化時保存ApplicationContext對象
代碼:
ApplicationContext ac = new FileSystemXmlApplicationContext("applicationContext.xml");
ac.getBean("beanId");
說明:這種方式適用于采用Spring框架的獨立應用程序,需要程序通過配置文件手工初始化Spring的情況。
方法二:通過Spring提供的工具類獲取ApplicationContext對象
代碼:
import org.springframework.web.context.support.WebApplicationContextUtils;
ApplicationContext ac1 = WebApplicationContextUtils.getRequiredWebApplicationContext(ServletContext sc);
ApplicationContext ac2 = WebApplicationContextUtils.getWebApplicationContext(ServletContext sc);
ac1.getBean("beanId");
ac2.getBean("beanId");
說明:
這種方式適合于采用Spring框架的B/S系統,通過ServletContext對象獲取ApplicationContext對象,然后在通過它獲取需要的類實例。
上面兩個工具方式的區別是,前者在獲取失敗時拋出異常,后者返回null。
其中 servletContext sc 可以具體 換成 servlet.getServletContext()或者 this.getServletContext() 或者 request.getSession().getServletContext(); 另外,由于spring是注入的對象放在ServletContext中的,所以可以直接在ServletContext取出 WebApplicationContext 對象: WebApplicationContext webApplicationContext = (WebApplicationContext) servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
方法三:繼承自抽象類ApplicationObjectSupport
說明:抽象類ApplicationObjectSupport提供getApplicationContext()方法,可以方便的獲取到ApplicationContext。
Spring初始化時,會通過該抽象類的setApplicationContext(ApplicationContext context)方法將ApplicationContext 對象注入。
方法四:繼承自抽象類WebApplicationObjectSupport
說明:類似上面方法,調用getWebApplicationContext()獲取WebApplicationContext
要輸出符合要求格式的數據文件只需在select時用字符連接來規范格式。比如有如下表
SQL>; select id,username,password from myuser;//測試表 |
要輸出符合1,John,1234,這樣的數據格式就用select id||','||username||','||password||',' from myuser這樣的語句。
SQL>; select id||','||username||','||password||',' from myuser; |
寫個下面這樣的腳本就行可以輸出符合要求格式的數據至文件中,不會含有其它不需要東西,只有數據部分。
--腳本文件名為expmyusr.sql,存數據的文件名為e:\exp.txt
set echo on --是否顯示執行的命令內容 |
檢查可知結果符合要求。
Oracle SPOOL的兩種方法之對比
通常情況下,我們使用SPOOL方法,將數據庫中的表導出為文本文件的時候會采用兩種方法,如下述:
方法一:采用以下格式腳本
set colsep '' ------設置列分隔符 |
方法二:采用以下腳本
set trimspool on |
比較以上方法,即方法一采用設定分隔符然后由sqlplus自己使用設定的分隔符對字段進行分割,方法二將分隔符拼接在SELECT語句中,即手工控制輸出格式。
在實踐中,我發現通過方法一導出來的數據具有很大的不確定性,這種方法導出來的數據再由sql ldr導入的時候出錯的可能性在95%以上,尤其對大批量的數據表,如100萬條記錄的表更是如此,而且導出的數據文件狂大。
而方法二導出的數據文件格式很規整,數據文件的大小可能是方法一的1/4左右。經這種方法導出來的數據文件再由sqlldr導入時,出錯的可能性很小,基本都可以導入成功。
因此,實踐中我建議大家使用方法二手工去控制spool文件的格式,這樣可以減小出錯的可能性,避免走很多彎路。
from: http://www.psoug.org/reference/utl_file.html --End-- |
轉:本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/huanghui22/archive/2007/05/03/1595166.aspx
有些時候我們希望得到指定數據中的前n列,示例如下:
得到每個部門薪水最高的三個雇員:
先創建示例表
create table emp
as
select * from scott.emp;
alter table emp
add constraint emp_pk
primary key(empno);
create table dept
as
select * from scott.dept;
alter table dept
add constraint dept_pk
primary key(deptno);
先看一下row_number() /rank()/dense_rank()三個函數之間的區別
select emp.deptno,emp.sal,emp.empno,row_number() over (partition by deptno order by sal desc) row_number, --1,2,3
rank() over (partition by deptno order by sal desc) rank, --1,1,3
dense_rank() over (partition by deptno order by sal desc) dense_rank from emp --1,1,2
結果如下:
10 5000.00 7839 1 1 1
10 2450.00 7782 2 2 2
10 1300.00 7934 3 3 3
20 3000.00 7788 1 1 1
20 3000.00 7902 2 1 1
20 2975.00 7566 3 3 2
20 1100.00 7876 4 4 3
20 800.00 7369 5 5 4
30 2850.00 7698 1 1 1
30 1600.00 7499 2 2 2
取每個部門的薪水前三位雇員:
select t.deptno,t.rank,t.sal from
(
select emp.*,row_number() over (partition by deptno order by sal desc) row_number, --1,2,3
rank() over (partition by deptno order by sal desc) rank, --1,1,3
dense_rank() over (partition by deptno order by sal desc) dense_rank from emp --1,1,2
) t
where t.rank<=3
結果如下:
10 1 5000.00
10 2 2450.00
10 3 1300.00
20 1 3000.00
20 1 3000.00
20 3 2975.00
30 1 2850.00
30 2 1600.00
30 3 1500.00
如果想輸出成deptno sal1 sal2 sal3這種類型的格式
步驟一(decode):
select t.deptno,decode(row_number,1,sal) sal1,decode(row_number,2,sal) sal2,decode(row_number,3,sal) sal3 from
(
select emp.*,row_number() over (partition by deptno order by sal desc) row_number, --1,2,3
rank() over (partition by deptno order by sal desc) rank, --1,1,3
dense_rank() over (partition by deptno order by sal desc) dense_rank from emp --1,1,2
) t
where t.rank<=3
結果如下:
10 5000
10 2450
10 1300
20 3000
20 3000
20 2975
30 2850
30 1600
30 1500
步驟二(使用聚合函數去除null,得到最終結果):
select t.deptno,max(decode(row_number,1,sal)) sal1,max(decode(row_number,2,sal)) sal2,max(decode(row_number,3,sal)) sal3 from
(
select emp.*,row_number() over (partition by deptno order by sal desc) row_number, --1,2,3
rank() over (partition by deptno order by sal desc) rank, --1,1,3
dense_rank() over (partition by deptno order by sal desc) dense_rank from emp --1,1,2
) t
where t.rank<=3
group by t.deptno
結果如下:
10 5000 2450 1300
20 3000 3000 2975
30 2850 1600 1500
24/05/2005 14:37 FP 在數據倉庫中的轉換和裝載過程中,經常會使用MERGE語句,這里簡單總結一下。
MERGE語句是Oracle9i新增的語法,用來合并UPDATE和INSERT語句。通過MERGE語句,根據一張表或子查詢的連接條件對另外一張表進行查詢,連接條件匹配上的進行UPDATE,無法匹配的執行INSERT。這個語法僅需要一次全表掃描就完成了全部工作,執行效率要高于INSERT+UPDATE。
下面看個具體的例子:
SQL> CREATE TABLE T AS SELECT ROWNUM ID, A.* FROM DBA_OBJECTS A;
表已創建。
SQL> CREATE TABLE T1 AS
2 SELECT ROWNUM ID, OWNER, TABLE_NAME, CAST('TABLE' AS VARCHAR2(100)) OBJECT_TYPE
3 FROM DBA_TABLES;
表已創建。
SQL> MERGE INTO T1 USING T
2 ON (T.OWNER = T1.OWNER AND T.OBJECT_NAME = T1.TABLE_NAME AND T.OBJECT_TYPE = T1.OBJECT_TYPE)
3 WHEN MATCHED THEN UPDATE SET T1.ID = T.ID
4 WHEN NOT MATCHED THEN INSERT VALUES (T.ID, T.OWNER, T.OBJECT_NAME, T.OBJECT_TYPE);
6165 行已合并。
SQL> SELECT ID, OWNER, OBJECT_NAME, OBJECT_TYPE FROM T
2 MINUS
3 SELECT * FROM T1;
未選定行
MERGE語法其實很簡單,下面稍微修改一下例子。
SQL> DROP TABLE T;
表已丟棄。
SQL> DROP TABLE T1;
表已丟棄。
SQL> CREATE TABLE T AS SELECT ROWNUM ID, A.* FROM DBA_OBJECTS A;
表已創建。
SQL> CREATE TABLE T1 AS SELECT ROWNUM ID, OWNER, TABLE_NAME FROM DBA_TABLES;
表已創建。
SQL> MERGE INTO T1 USING T
2 ON (T.OWNER = T1.OWNER AND T.OBJECT_NAME = T1.TABLE_NAME)
3 WHEN MATCHED THEN UPDATE SET T1.ID = T.ID
4 WHEN NOT MATCHED THEN INSERT VALUES (T.ID, T.OWNER, T.OBJECT_NAME);
MERGE INTO T1 USING T
*
ERROR 位于第 1 行:
ORA-30926: 無法在源表中獲得一組穩定的行
這個錯誤是使用MERGE最常見的錯誤,造成這個錯誤的原因是由于通過連接條件得到的T的記錄不唯一。最簡單的解決方法類似:
SQL> MERGE INTO T1
2 USING (SELECT OWNER, OBJECT_NAME, MAX(ID) ID FROM T GROUP BY OWNER, OBJECT_NAME) T
3 ON (T.OWNER = T1.OWNER AND T.OBJECT_NAME = T1.TABLE_NAME)
4 WHEN MATCHED THEN UPDATE SET T1.ID = T.ID
5 WHEN NOT MATCHED THEN INSERT VALUES (T.ID, T.OWNER, T.OBJECT_NAME);
5775 行已合并。
另外,MERGE語句的UPDATE不能修改用于連接的列,否則會報錯,詳細信息可以參考:http://blog.itpub.net/post/468/14844
===============================================================
ref: http://tomszrp.itpub.net/post/11835/263865
在Oracle 10g之前,merge語句支持匹配更新和不匹配插入2種簡單的用法,在10g中Oracle對merge語句做了增強,增加了條件選項和DELETE操作。下面我通過一個demo來簡單介紹一下10g中merge的增強和10g前merge的用法。
參考Oracle 的SQL Reference,大家可以看到Merge Statement的語法如下:
MERGE [hint] INTO [schema .] table [t_alias] USING [schema .]
{ table | view | subquery } [t_alias] ON ( condition )
WHEN MATCHED THEN merge_update_clause
WHEN NOT MATCHED THEN merge_insert_clause;
下面我在windows xp 下10.2.0.1版本上做一個測試看看
SQL> select * from v$version; BANNER ---------------------------------------------------------------- Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod PL/SQL Release 10.2.0.1.0 - Production CORE 10.2.0.1.0 Production TNS for 32-bit Windows: Version 10.2.0.1.0 - Production NLSRTL Version 10.2.0.1.0 - Production SQL> 一、創建測試用的表 SQL> create table subs(msid number(9), 2 ms_type char(1), 3 areacode number(3) 4 ); 表已創建。 SQL> create table acct(msid number(9), 2 bill_month number(6), 3 areacode number(3), 4 fee number(8,2) default 0.00); 表已創建。 SQL> SQL> insert into subs values(905310001,0,531); 已創建 1 行。 SQL> insert into subs values(905320001,1,532); 已創建 1 行。 SQL> insert into subs values(905330001,2,533); 已創建 1 行。 SQL> commit; 提交完成。 SQL> 二、下面先演示一下merge的基本功能 1) matched 和not matched clauses 同時使用 merge into acct a using subs b on (a.msid=b.msid) when MATCHED then update set a.areacode=b.areacode when NOT MATCHED then insert(msid,bill_month,areacode) values(b.msid,'200702',b.areacode); 2) 只有not matched clause,也就是只插入不更新 merge into acct a using subs b on (a.msid=b.msid) when NOT MATCHED then insert(msid,bill_month,areacode) values(b.msid,'200702',b.areacode); 3) 只有matched clause, 也就是只更新不插入 merge into acct a using subs b on (a.msid=b.msid) when MATCHED then update set a.areacode=b.areacode Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 Connected as study SQL> select * from subs; MSID MS_TYPE AREACODE ---------- ------- -------- 905310001 0 531 905320001 1 532 905330001 2 533 SQL> select * from acct; MSID BILL_MONTH AREACODE FEE ---------- ---------- -------- ---------- SQL> SQL> merge into acct a 2 using subs b on (a.msid=b.msid) 3 when MATCHED then 4 update set a.areacode=b.areacode 5 when NOT MATCHED then 6 insert(msid,bill_month,areacode) 7 values(b.msid,'200702',b.areacode); Done SQL> select * from acct; MSID BILL_MONTH AREACODE FEE ---------- ---------- -------- ---------- 905320001 200702 532 0.00 905330001 200702 533 0.00 905310001 200702 531 0.00 SQL> insert into subs values(905340001,3,534); 1 row inserted SQL> select * from subs; MSID MS_TYPE AREACODE ---------- ------- -------- 905340001 3 534 905310001 0 531 905320001 1 532 905330001 2 533 SQL> SQL> merge into acct a 2 using subs b on (a.msid=b.msid) 3 when NOT MATCHED then 4 insert(msid,bill_month,areacode) 5 values(b.msid,'200702',b.areacode); Done SQL> select * from acct; MSID BILL_MONTH AREACODE FEE ---------- ---------- -------- ---------- 905320001 200702 532 0.00 905330001 200702 533 0.00 905310001 200702 531 0.00 905340001 200702 534 0.00 SQL> update subs set areacode=999; 4 rows updated SQL> select * from subs; MSID MS_TYPE AREACODE ---------- ------- -------- 905340001 3 999 905310001 0 999 905320001 1 999 905330001 2 999 SQL> select * from acct; MSID BILL_MONTH AREACODE FEE ---------- ---------- -------- ---------- 905320001 200702 532 0.00 905330001 200702 533 0.00 905310001 200702 531 0.00 905340001 200702 534 0.00 SQL> SQL> merge into acct a 2 using subs b on (a.msid=b.msid) 3 when MATCHED then 4 update set a.areacode=b.areacode; Done SQL> select * from acct; MSID BILL_MONTH AREACODE FEE ---------- ---------- -------- ---------- 905320001 200702 999 0.00 905330001 200702 999 0.00 905310001 200702 999 0.00 905340001 200702 999 0.00 SQL> 三、10g中增強一:條件操作 1) matched 和not matched clauses 同時使用 merge into acct a using subs b on (a.msid=b.msid) when MATCHED then update set a.areacode=b.areacode where b.ms_type=0 when NOT MATCHED then insert(msid,bill_month,areacode) values(b.msid,'200702',b.areacode) where b.ms_type=0; 2) 只有not matched clause,也就是只插入不更新 merge into acct a using subs b on (a.msid=b.msid) when NOT MATCHED then insert(msid,bill_month,areacode) values(b.msid,'200702',b.areacode) where b.ms_type=0; 3) 只有matched clause, 也就是只更新不插入 merge into acct a using subs b on (a.msid=b.msid) when MATCHED then update set a.areacode=b.areacode where b.ms_type=0; Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 Connected as study SQL> select * from subs; MSID MS_TYPE AREACODE ---------- ------- -------- 905310001 0 531 905320001 1 532 905330001 2 533 SQL> select * from acct; MSID BILL_MONTH AREACODE FEE ---------- ---------- -------- ---------- SQL> SQL> merge into acct a 2 using subs b on (a.msid=b.msid) 3 when MATCHED then 4 update set a.areacode=b.areacode 5 where b.ms_type=0 6 when NOT MATCHED then 7 insert(msid,bill_month,areacode) 8 values(b.msid,'200702',b.areacode) 9 where b.ms_type=0; Done SQL> select * from acct; MSID BILL_MONTH AREACODE FEE ---------- ---------- -------- ---------- 905310001 200702 531 0.00 SQL> insert into subs values(905360001,0,536); 1 row inserted SQL> select * from subs; MSID MS_TYPE AREACODE ---------- ------- -------- 905360001 0 536 905310001 0 531 905320001 1 532 905330001 2 533 SQL> SQL> merge into acct a 2 using subs b on (a.msid=b.msid) 3 when NOT MATCHED then 4 insert(msid,bill_month,areacode) 5 values(b.msid,'200702',b.areacode) 6 where b.ms_type=0; Done SQL> select * from acct; MSID BILL_MONTH AREACODE FEE ---------- ---------- -------- ---------- 905310001 200702 531 0.00 905360001 200702 536 0.00 SQL> update subs set areacode=888 where ms_type=0; 2 rows updated SQL> select * from subs; MSID MS_TYPE AREACODE ---------- ------- -------- 905360001 0 888 905310001 0 888 905320001 1 532 905330001 2 533 SQL> select * from acct; MSID BILL_MONTH AREACODE FEE ---------- ---------- -------- ---------- 905310001 200702 531 0.00 905360001 200702 536 0.00 SQL> SQL> merge into acct a 2 using subs b on (a.msid=b.msid) 3 when MATCHED then 4 update set a.areacode=b.areacode 5 where b.ms_type=0; Done SQL> select * from acct; MSID BILL_MONTH AREACODE FEE ---------- ---------- -------- ---------- 905310001 200702 888 0.00 905360001 200702 888 0.00 SQL> 四、10g中增強二:刪除操作 An optional DELETE WHERE clause can be used to clean up after a merge operation. Only those rows which match both the ON clause and the DELETE WHERE clause are deleted. merge into acct a using subs b on (a.msid=b.msid) when MATCHED then update set a.areacode=b.areacode delete where (b.ms_type!=0); SQL> select * from subs; MSID MS_TYPE AREACODE ---------- ------- -------- 905310001 0 531 905320001 1 532 905330001 2 533 SQL> select * from acct; MSID MS_TYPE AREACODE ---------- ------- -------- 905310001 0 531 905320001 1 532 905330001 2 533 SQL> SQL> merge into acct a 2 using subs b on (a.msid=b.msid) 3 when MATCHED then 4 update set a.areacode=b.areacode 5 delete where (b.ms_type!=0); Done SQL> select * from acct; MSID MS_TYPE AREACODE ---------- ------- -------- 905310001 0 531 SQL> 更為詳盡的語法,請參考Oracle SQL Reference手冊!
awk處理文本總結 - Alex.Wang 2008-2-19 15:55
作為技術支持工程我們最最經常的工作就是經常碰到要處理文本文件,不管是什么數據庫最后都可以導成文本,我們就可以對他進行處理了,這樣即使你不是對所有數據庫操作都很熟悉也可以對他的數據進行處理了。
我們必須的工具有兩個一個是shell一個是awk,awk對于處理文本文件是最最適合的掌握了awk我們就可以很方便的處理文本文件再借助一些shell命令我們可以很方便得到自己想要的結果。現在從簡單的例子來總結一下我覺得會經常碰到的問題。
--------------------------------------------------------------------------------
awk入門篇
awk入門,文本內容example1.txt.
user1 password1 username1 unit1 10
user2 password2 username2 unit2 20
user3 password3 username3 unit3 30
在unix環境中我們可以使用一下命令來打印出第一列
[root@mail awk]# awk '{print $1}' example1.txt
得到的結果是如下,解釋一下"'{" 單引號大括號包含awk語句是為了和shell 命令區別,$1的意思就是文本文件的第一列,正常的awk命令跟隨-F參數指定間隔符號,如果是空格或tab鍵就可以省略了。
user1
user2
user3
[root@mail awk]# awk '{if($5>20) {print $1}}' example1.txt
這行命令和上一行比較增加了“if($5>20)”,得到的結果是
user3
這個if語句就沒有必要更詳細的解釋了吧!就是第5列大于20的顯示出滿足條件的第一列
[root@mail awk]# awk '{if($5>20 || $5==10) {print $1}}' example1.txt
user1
user3
在來一個初級的又增加了一個“if($5>20 || $5==10)” 做邏輯判斷邏輯判斷的三個“|| && !” 或、與、非三個可以任意加到里面,這個語句的意思是如果第5列大于20或者等于10的都顯示處理,在我們的工作中可能有用戶會要求找出所有空間大于多少的或者是空間等于多少的賬戶然后再做批量修改。
if是awk循環中的一個還有其他很多,man awk可以看到,
Control Statements
The control statements are as follows:
if (condition) statement [ else statement ]
while (condition) statement
do statement while (condition)
for (expr1; expr2; expr3) statement
for (var in array) statement
break
continue
delete array[index]
delete array
exit [ expression ]
{ statements }
學習awk可以經常使用一下man awk 可以看到所有的函數和使用方法。
了解每個符號的意義我們才能更好的使用awk,最開始先記住幾個命令知道他可實現的結果我們慢慢的再去理解。
--------------------------------------------------------------------------------
awk中級篇
這里順便介紹一下vi的一個替換命令,現在我們要把example1.txt文本里的空格都替換為“:”冒號這里在vi里使用的命令就是:
%s/ /:/g
這個命令對于使用vi的人來說是用得最多的。我們現在做了一個新的文件example2.txt。
user1:password1:username1:unit1:10
user2:password2:username2:unit2:20
user3:password3:username3:unit3:30
現在我們來做一個awk腳本,之前都是在命令行操作,實際上所有的操作在命令行上是可以都實現的,已我們最經常使用的批量添加用戶來開始!
script1.awk
#!/bin/awk -f # 當文件有可執行權限的時候你可以直接執行
# ./script1.awk example2.txt
# 如果沒有以上這行可能會出現錯誤,或者
# awk -f script1.awk example2.txt 參數f指腳本文件
BEGIN { # “BEGIN{”是awk腳本開始的地方
FS=":"; # FS 是在awk里指分割符的意思
}
{ # 接下來的“{” 是內容部分
print "add {"; # 以下都是使用了一個awk函數print
print "uid=" $1;
print "userPassword=" $2;
print "domain=eyou.com" ;
print "bookmark=1";
print "voicemail=1";
print "securemail=1"
print "storage=" $5;
print "}";
print ".";
} # “}” 內容部分結束
END { # “END{” 結束部分
print "exit";
}
執行結果
[root@mail awk]# awk -f script1.awk example2.txt
add {
uid=user1
userPassword=password1
domain=eyou.com
bookmark=1
voicemail=1
securemail=1
storage=10
}
.
.
.
.
.
.
exit
文本操作就是更方便一些。
下面給兩個返回效果一樣的例子
[root@mail awk]# awk -F: '{print $1"@"$2}' example2.txt
[root@mail awk]# awk -F: '{printf "%s@%s\n",$1,$2}' example2.txt
user1@password1
這里的區別是使用print 和printf的區別,printf格式更自由一些,我們可以更加自由的指定要輸出的數據,print會自動在行尾給出空格,而printf是需要給定" \n"的,如果感興趣你可以把“\n”去掉看一下結果。%s代表字符串%d 代表數字,基本上%s都可以處理了因為在文本里一切都可以看成是字符串,不像C語言等其他語言還要區分數字、字符、字符串等。
awk還有一些很好的函數細細研究一下還是很好用的。
這次碰到了一個問題客戶有一個用戶列表,大概有2w用戶,他有一個有趣的工作要做,就是把每個賬戶目錄放到特定的目錄下,例如13910011234這個目錄要放到139/10/這個目錄下,從這里可以看出規律是手機號碼的前三位是二級目錄名,手機的第3、4為是三級目錄名,我們有的就只有一個用戶列表,規律找到了我們現在開始想辦法處理吧。
example3.txt
13910011234
15920312343
13922342134
15922334422
......
第一步是要找到一個方法來吧,就是要把每一個手機號分開,最初可能你就會想到這個也沒有任何間隔,我們怎么用awk分開他們呢?說實話最初我也考慮了20多分鐘,后來想起原來學習python的時候有split函數可以分就想找找awk里是不是有類似的函數,man awk 發現substr 這個函數子串,
[root@mail awk]# awk '{print substr($1,1,3)}' example3.txt
[root@mail awk]# awk '{printf "%s/%s\n",substr($1,1,3),substr($1,4,2)}' example3.txt
[root@mail awk]# awk '{printf "mv %s %s/%s\n",$1,substr($1,1,3),substr($1,4,2)}' example3.txt
以上的兩步的返回自己做一下,最后我們就得到了我們想要的結果。
mv 13910011234 139/10
mv 15920312343 159/20
mv 13922342134 139/22
mv 15922334422 159/22
把這部分輸出拷貝到一個shell腳本里,在數據當前目錄下執行就可以了!
substr(s, i [, n]) Returns the at most n-character substring of s
starting at i. If n is omitted, the rest of s
is used.
substr函數解釋,s代表我們要處理的字符串,i 是我們從這個字符串的第幾個位置上開始,n 是我們從開始的位置取多少個字符。多看看man英文也會有所提高的。
awk有很多有趣的函數如果感興趣可以自己去查查看,
man awk
String Functions 字符串函數,舉幾個覺得常用的函數
length([s]) Returns the length of the string s, or the
length of $0 if s is not supplied.
length 你可以得到字符串的長度,這個是比較常用的一個函數
split(s, a [, r]) Splits the string s into the array a on the
regular expression r, and returns the number of
fields. If r is omitted, FS is used instead.
The array a is cleared first. Splitting
behaves identically to field splitting,
described above.
tolower(str) Returns a copy of the string str, with all the
upper-case characters in str translated to
their corresponding lower-case counterparts.
Non-alphabetic characters are left unchanged.
toupper(str) Returns a copy of the string str, with all the
lower-case characters in str translated to
their corresponding upper-case counterparts.
Non-alphabetic characters are left unchanged.
Time Functions 時間函數,我們最最常用到的是時間戳轉換函數
strftime([format [, timestamp]])
Formats timestamp according to the specification in format.
The timestamp should be of the same form as returned by sys-
time(). If timestamp is missing, the current time of day is
used. If format is missing, a default format equivalent to
the output of date(1) is used. See the specification for the
strftime() function in ANSI C for the format conversions that
are guaranteed to be available. A public-domain version of
strftime(3) and a man page for it come with gawk; if that
version was used to build gawk, then all of the conversions
described in that man page are available to gawk.
這里舉例說明時間戳函數是如何使用的
[root@ent root]# date +%s | awk '{print strftime("%F %T",$0)}'
2008-02-19 15:59:19
我們先使用date命令做一個時間戳,然后再把他轉換為時間
還有一些我們現在可能不經常用到的函數,詳細內容man awk 自己可以看一下。
Bit Manipulations Functions 二進制函數
Internationalization Functions 國際標準化函數
USER-DEFINED FUNCTIONS 用戶也可以自己定義自己的函數,感興趣自己可以再深入研究一下。
For example:
function f(p, q, a, b) # a and b are local
{
...
}
/abc/ { ... ; f(1, 2) ; ... }
DYNAMICALLY LOADING NEW FUNCTIONS 動態加載新函數,這個可能就更高級一些了!
--------------------------------------------------------------------------------
awk高級篇
不管學習任何語言,我們學到的都是工具,工具知道的越多,我們做起工作來就越方便,但是工具在你的手里并不一定能造出好的產品,編輯腳本和編程序也是一樣的重要的是算法,別人不知道怎么處理的問題你要知道如何處理。這才能證明你比別人更高,工具只要你慢慢練習都會使用。
下面給大家一個我認為是比較高級的問題了,感興趣的可以自己再想想更好的解決辦法。問題是這樣的我們有一個從ldap里導出的文件,它都是一行一個字段來說明的,每個用戶的數據是已空行分割的。我們必須把對應的uid 和userPassword找出來而且是對應的。
例子:example4.txt
dn: uid=cailiying,domain=ccc.com.cn,o=mail.ccc.com.cn
uid: cailiying
userPassword:: e21kNX0zREl4VEIwODBJdXZkTnU3WFFtS3lRPT0=
letters: 300
quota: 100
dn: uid=caixiaoning,domain=ccc.com.cn,o=mail.ccc.com.cn
userPassword:: e21kNX1kejFXU0doZWprR2RNYnV5ajJJRWl3PT0=
letters: 300
quota: 100
uid: chenzheng
domain: cqc.com.cn
dn: uid=caixiaoning,domain=ccc.com.cn,o=mail.ccc.com.cn
userPassword:: e21kNX1kejFXU0doZWprR2RNYnV5ajJJRWl3PT0=
letters: 300
quota: 100
dn: uid=caixiaoning,domain=ccc.com.cn,o=mail.ccc.com.cn
userPassword:: e21kNX1kejFXU0doZWprR2RNYnV5ajJJRWl3PT0=
letters: 300
quota: 100
uid: chenzheng
domain: cqc.com.cn
處理這個文本我們需要考慮的問題是:
1 uid 和userPassword 并不是每一個段落里都有
2 在每一段里面uid和userPassword 先后順序是隨機的
3 有的段落里可能只有uid 或者只有userPassword
從文本上分析可以看出必須使用的間隔符號,一個是空行,一個是冒號。
冒號我們awk -F:就可以了,不過空行我們不好判斷現在想到length()這個函數,在unix里空行最多只有一個\n字符,如果一行字符數小于2我們判斷為空行,好現在間隔符號問題解決,空行只能通過循環來實現對空行的判斷。
現在碰到的另外一個問題是我們的某個段里的信息是不完全的,我們就要放棄這段這兒如何來做,就是要做兩個標記變量u 和 p 再做一個循環如果u 和 p 同事滿足我們才輸出結果下面的awk腳本就是通過這個思考來解決ldif文本的處理的!
# 此腳本的目的是方便我們以后導ldap的其他郵件的數據,
# 我們之前使用slapdcat -l 導出所有信息,然后我們需要
# 整理出uid password , 這里的設置都是默認以":" 間隔的
# 例slapcat -l user.ldif 如果想得到一份uid 和userPassword 對應的文件,
# 修改username = "dn"; password = "userpassword"; awk -f ldap2txt.awk user.ldif | grep uid | more 可以查看結果 (有可能是多域的郵件)
# 如果想得到domain 所對應的密碼,修改username = "dn"; password = "userpassword"; 運行 awk -f ldap2txt.awk user.ldif |grep domain | more
#!/bin/awk -f
# File name: ldap2txt.awk
BEGIN {
FS = ":";
username = "uid";
password = "userPassword";
}
{
if(length($0) == 0 )
{
if (name != "u" && pword != "p")
{
printf ("%s:%s\n", name,pword);
name = "u";
pword = "p";
}
}
else
{
if ($1 == username)
{
name = "u";
name = $0;
}
else if($1 == password)
{
pword = "p";
pword = $0;
}
}
}
END {
}
實際上對于學習語言首先是熟悉一些常用的函數,然后就是試著去解決別人解決過的問題,然后自己再思考一下是不是有更好,速度更快的解決辦法,實際上大部分的程序員都是在重復的使用著別人好的解決辦法,把別人的方法轉變為自己的方法,就是反復練習解決不同的問題,思考更好的方法!
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/blackbillow/archive/2009/01/21/3847425.aspx