當前位置:首頁 » 編程語言 » java解碼器

java解碼器

發布時間: 2025-02-08 07:25:35

1. java中classpath的值是多少

查看文章 JAVA中classPath全面解析 2009年08月22日 14:15

# 摘要

Class Path是Java執行時期環境用來搜尋類別與其它資源所用之路徑。Class Sear
ch Path(通常使用Class Path這個縮寫名稱比較為人所知)可以在呼叫SDK工具程
式時使用-classpath或者是設定CLASSPATH環境變數。建議是使用-classpath選項,
因為您可以獨立的為每一個應用程式設定,而不會影響其它的應用程式,且不會有
其它的應用程式來改變這個值。

1 C:> sdkTool -classpath classpath1;classpath2...

-或-

1 C:> set CLASSPATH=classpath1;classpath2...

在這邊:

sdkTool:是一個命令列工具程式,像是java、javac 或 javadoc.

classpath1;classpath2:指向.jar、.zip或 .class檔案的Class Path,每一個cl
asspath都應以檔名或目錄名稱(這與您所要設定的classpath有關)作結束。

* 對於一個包括.class的.jar或.zip檔案而言,class path要以.zip或.jar檔案的
名稱作結束。

* 對於一個未命名的package而言,class path要以包括所有.class檔案的目錄作結
束。

* 對於一個已命名的package而言,class path要以包括"根"package(完整packag
e名稱的第一個package)的目錄名稱作結束。

多個路徑項目要以 分號 作區隔,使用set指令,重要的是等號兩邊不可有空白。

預設的class path是目前的目錄,設定CLASSPATH變數或使用-classpath命令列選項
時會覆蓋這個預設,所以如果您要在目前的搜尋路徑中包括目前的目錄,您必須在
新設定中包括"." 。

即不是目錄也不是文件檔案(.zip或.java)的classpath會被忽略。

# 說明

class path告訴SDK工具程式與應用程式要到哪邊尋找第三元件(third-party)與
使用者定義的classes,也就是它們非Java延伸套件或非Java平台的一部份。在您使
用javac編譯器編譯類別時,需要使用class path來找出任何所需的套件 -- 預設是
目前的目錄,以方便找到這些類別。 Java2 SDK、JVM與其它的SDK工具藉由搜尋Ja
va平台、classes、其它延伸classes與class path來找到所需的classes,以這個順
序(要瞭解搜尋策略的細節,請看如何尋找Classes, How Classes Are Found),
大部份應用程式所用的類別庫就可以利用延伸套件機制(extensions mechanism)
,在您載入一個不在目前目錄的類別或它的其它子目錄且它們不在伸延伸套件機制
中時,您所要作的就是設定class path。

如果您從舊版本的SDK升級上來,在您的啟動設定中可能包括已經不再使用的CLASS
PATH設定,您必須將這些非特定應用程式的設定移除,像是classes.zip,一些使用
到Java虛擬機器的第三元件應用程式可能會更改您的CLASSPATH環境變數,以將它們
所使用的程式庫包括進去,這些設定則可以保留。

在您要求JVM或其它SDK工具程式時,您可以在使用Java工具程式時藉由-classpath
選項來改變class path,或是使用CLASSPATH環境變數來指定。建議是使用-classp
ath選項會比設定CLASSPATH環境變數來得好,因為您可以為每一個應用程式分別設
定,而不會影響其它的應 用程式,而其它應用程式也不會改變這個值。

Classes可以被儲存在目錄(資料夾)或是在文件檔案(archive files),Java平
台的classes是被儲存在rt.jar,要瞭解文件檔案的細節或是class path如何運作的
資訊,請看看稍後小節的 "瞭解class path與package名稱"。

重要、注意:一些舊版本的JDK軟體在預設的class path中包括了<jdk-dir>/class
es項目,這些目錄的存在是為了被JDK軟體使用,而不應被應用程式classes使用。
應用程式類別應該被放在JDK目錄結構之外的其它目錄,用這種方式,新的JDK就不
會強迫您重新安裝應用程式classes,為了要與舊版本相容,必須使用<jdk-dir>/c
lasses目錄作為類別庫的的應用程式,在目前的版本也可以運作,但不保證在未來
的版本中仍可以運作。

# 使用SDK工具程式的-classpath選項

SDK工具程式 java、jdb、javac與javah擁有一個-classpath項目,當執行工具程式
時,它用於取代由CLASSPATH環境變數所設定的路徑,在改變class path設定時,這
是個建議使用的選項,因為每一個應用程式可以擁有自已所需的class path,而不
會與其它應用程式相互干擾。

執行時期工具程式java也有一個 -cp 選項,這個選項是-classpath的縮寫名稱。

對於一些相當特殊的例子來說,java與javac都擁有一些項目可以讓您改變它們用來
找到專屬類別庫的路徑,然而絕大多數的使用者從未需要使用這些項目。

# 使用CLASSPATH環境變數

一般而言,建議您使用-classpath命令列選項,就如同上面所提過的,這個小節將
告讓您如何設定CLASSPATH環境變數,如果您想這麼作的話,或者是想清除之前安裝
所留下的設定。

設定 CLASSPATH:

CLASSPATH環境變數可以藉由set指令來修改,格式是:

1 set CLASSPATH=path1;path2 ....

路徑應該以磁碟機代號開始,例如C:\,用這種方式,即使您切換至另一個磁碟機也
可以找得到classes。(舉個例子來說,假如路徑項目以斜線開始而您在磁碟機D:,
那麼classes將會預期是在D:,而不是C:)

清除 CLASSPATH:

如果您的CLASSPATH環境變數已經被設定為某個值,但是並不正確,或者是您的啟動
檔案或是命令稿被設定了錯誤的路徑,您可以藉由以下來取消CLASSPATH的設定:

1 C:> set CLASSPATH=

這個指令只取消目前的命令列提示視窗CLASSPATH設定,您應當刪除或修正您的啟動
設定,以保證您在下一次操作也會有正確的CLASSPATH設定。

改變啟動設定:

如果CLASSPATH被設定於系統啟動時,設定的地方則視您所使用的作業系統而定:

作業系統方法:

*Windows 95與98 檢查autoexec.bat中的set指令

*其它(Windows NT、Windows 2000、....)使用控制台中的系統工具來設定CLASS
PATH變數

# 瞭解class path與package名稱

Java的classes被組織為packages,它們對應於檔案系統的目錄結構,但是不像檔案
系統,每當您指定一個package名稱時,您指定整個package名稱而不是部份名稱,
例如,java.awt.Button的package名稱是使用java.awt來指定。

例如,假設您要Java執行環境找到一個在 package名稱 utility.myapp 中名叫Coo
l.class的class,假如該目錄的路徑是C:\java\MyClasses\utility\myapp,您要設
定class path以包括 C:\java\MyClasses。

要執行這個應用程式,您可以使用下面的JVM指令:

1 c:> java -classpath C:\java\MyClasses utility.myapp.Cool

當應用程式執行時,JVM會使用class path設定來找到任一其它被定義於utility.m
yapp package(它被Cool類別使用)中的類別。

注意在指令中被指定的整個package名稱,這是不可能的,例如,設定class path包
括C:\java\MyClasses\utility並使用指令java myapp.Cool,這麼作並不會找到cl
ass。

(您可能會想是什麼定義了一個class的package名稱,答案是package名稱是class
的一部份,而且不可被修改,除非重新編譯)

注意:一個package指定機制的有趣的結果是,同一個package中的部份檔案可以存
在於不同的目錄,對於每一個class而言,package名稱將會相同,但是每一個檔案
的路徑將會以class path中不同的目錄開始。

目錄與文件檔案(archive files):

當classes被儲存在目錄(資料夾),像是c:\java\MyClasses\utility\myapp,那
麼class path項目指向包括package名稱第一個元素的目錄(在這個例子中是c:\ja
va\MyClasses,因為package名稱是utility.myapp)

但是當classes被儲存在文件檔案時(a.zip或.jar檔案),class path項目就是指
向且包括.zip或.jar的檔案,例如,使用在.jar檔案中的類別庫,指令會像是:

1 C:> java -classpath C:\java\MyClasses\myclasses.jar utility.myapp.Cool

多個指定:

要尋找C:\java\MyClasses中與C:\java\OtherClasses中的classes,您可以這麼設
定class path:

1 C:> java -classpath C:\java\MyClasses;C:\java\OtherClasses ...

注意兩個路徑是以分號作區隔。

指定順序:

指定多個class path項目的順序很重要,Java解碼器(interpreter)會以class p
ath變數 中的順序來於目錄中尋找classes,在上面的例子中,Java解碼器首先會在
目錄C:\java\MyClasses中尋找所需的類別,只有在它於該目錄中找不到適當名稱的
類別時,解碼器才會於C:\java\OtherClasses目錄中尋找。

///////////
話說回來,
我們有沒有辦法, 將一些常用的 jar file 放到一個目錄中 ex: commons-lib\
透過一個程式來自動 import commons-lib 之下的所有 jar
類似 tomcat 我們只要放到 lib 中, 程式會自動 import .
就可以 import and compile 了 ^^~

我想這是可行的.

但是現實中, 我們還要去判斷重復的 class 該如何去設定.
看來, 要去 trace tomcat sourcecode 並且修改 ^^~

//////////////
javac.exe有一個參數-extdirs可以下, 我看它的說明
很像是下了這個就可以做到自動import指定目錄下的jar檔吧
不過java.exe沒有
///////////
LoadClass
LoadLibrary
so many so on.

JDK allows compile at runtime.
/////////////
dear biology
我要的不是 LoadLibrary , 你這樣還是需要指定你要哪個 library

應該是說, 我想要的是只要將相關的 jar file 放到一個指定的目錄.
可以少去 complie 及 run 時候不需要設定 CLASSPATH.

////////////////////
剛剛測試了一下 ClassLoader 他可以把我們想要的 .jar 檔全部載入 jvm 但是有
個小問題. 那就是 Class.forName(String) 這一個不一定會找到我們要的 class.
... 需要利用 class.forName(className, initialize, classloader). 但是需要
先指定 classloader... 這個是個問題....

原因是 Class.forName(string) 會取代成 Class.forName(string, true, curren
tClass.classloader)... 如果那個 classloader 本身(還有 parent classloader
)沒有 這特定 library 存在, 那就無法抓到指定的 class.... 所以總歸 還是一次
加入 CLASSPATH 比較好... 或則只好拜託人深入研究了...

[事實你可以利用 ClassLoader 半自動達到你要的東西....]

/////////
部分我測試用的 code: 希望多少有幫助...

java.net.URL u[]=new java.net.URL[1];

u[0]=new java.net.URL("http://localhost/onlytest.jar
);

java.net.URLClassLoader cl=java.net.URLClassLoader.newInstance(u,ClassLo
ader.getSystemClassLoader());

cl.loadClass("BioTester.BioTestClass").newInstance();

//org.apache.bcel.util.ClassLoader. //purpose?

//this will be failed: Class.forName("BioTester.something")

Object obj=Class.forName("BioTester.something",true,cl).newInstance();

//Object obj=cl.loadClass("BioTester.something").newInstance();

java.lang.reflect.Method m=obj.getClass().getMethod("aaa",null);

m.invoke(obj, null);

//////////////////
你們不會不知道吧?!

JRE/lib/ext 就是這個用途啊,讓你放 third-party 的 library,JRE 啟動時會把
自動載入里頭的 jar(應該說 classloader 需要 resolve class 時會到這個目錄下
來找)。

主要的問題是,安裝 JDK 時一般人可能會裝兩個 JRE,一在 JDK 安裝目錄下的 J
RE 目錄,一在(預設) Program files 目錄下的 Java 目錄。javac.exe 使用的是
JDK 所附的 private JRE(JDK/JRE),而執行 Java 程式則要看你的 path 定。

JDK\bin\java.exe, JDK\jre\bin\java.exe 使用的是 private JRE,program fil
es\java\jre1.x.x\bin\java.exe, WinNT(Windows)\system32\java.exe 使用的是
public JRE。javaw.exe 同上。

比較保險的做法是把 third-party library jar file 在 private JRE/public JR
E 各放一份,這樣可確保編譯時可以 resolve third-party classes,或是設定 p
ath 使得優先使用 private JRE(或乾脆就移除掉 public JRE)。

Eclipse 比較特別,你可以只把 third-party 放在 public JRE 就好,不需要放在
private JRE 也可以在編譯時讓編譯器去參考到所需要的 class。

///////////////////
沒錯, 這就是我希望的功能,
擺在那邊 install 沒問題, 但是 uninstall 就會有問題了,
因為可能會有重復使用到的 jar files.
所以我希望能夠指定一個目錄

當我是個 application setup 完成之後,
目前的做法是在 run.bat 中設定相關的 CLASSPATH

此外, 對於一個 java 新手,
我也希望提供一個簡單的方法管理及部署 jar files.
避免 CLASSPATH 設定的問題.

簡單來說, 就是執行某個程式可以自由地增加目錄相當 %JAVA_HOME%/lib/ext
接著我開發我的程式或執行我的程式,
而且透過那個程式可以做一些 jar files 的管理
例如說, 優先順序, 重復剔除 等等的功能 ^^~

///////////////
我想jini兄跟Biologic兄應該都知道的...
但是我臆測可能他們認為放在JRE/lib/ext不是很恰當的方法
第一個問題就是將來使用者要自己把使用的classpath放在/jre/lib/ext
會造成使用者的困擾

二來 可能會有一些版本的沖突...
以前就有發生這個例子
就是抓了很多xml parser..
而每個裡面又包了JAXP
結果有的包舊的有的包新的..
錯誤就這樣產生了...

一般來講還是在執行的時候給classpath才是上策
至於太多lib的話
我個人還是不喜歡程式裡面用ClassLoader去抓...
我寧願提供批次檔給他執行
或是提供build.xml.. ant題供**/*.jar的寫法
////////////////
同意 popcorny 的看法, 放在 JRE/lib/ext 下可行, 但"層級"太高, 尤其如果是在
web app(tomcat) 或 J2EE 的環境底下, 必須考慮 class loading 先後順序的問題
(好像在spec中有定義.)

所以應該不會有任何一個java applicaion installation guide 要你把哪個 jar 放在
JRE/lib/ext 中

(但這好像不屬於新手區的討論 ...)
///////////////////////
如果說是同一套 library 不同版本的沖突問題,最基本(可能也是最好的)解法是,
替每一個 application 提供一個批次檔,指定專用的 classpath。或是寫個 clas
sloader 會依照 application 的屬性(xml file),到特定的目錄去找 jar,但是這
沒有辦法套用在其他廠商提供的應用程式上。

一個比較可行的辦法是,寫一個 application launcher,擁有管理 jar library
及每個應用程式所倚賴的 library 的對應關系,然後要求使用者在執行任何 Java
application 時,都得透過 app launcher(app launcher 會啟動特定的 classlo
ader 來載入 app 所需要的 jar)來啟動(這很容易)。

//////////////////////////
很多 ext package 都是要求自己設定 classpath,指示把 ext-package jar 放進
Jre/lib/ext 也是有:Java Communications API。

/////////////////////
"很多 ext package 都是要求自己設定 classpath ..."

這樣比較好.

"指示把 ext-package jar 放進 Jre/lib/ext 也是有 ..."

javax 是 java "extention", 個人認為比較不像 "application",
既然是 Java 的一部份, 建議直接放 jre/lib/ext 下也無可厚非,
但版本的問題可能會是 nightmare.
個人認為還是用 "application specific" classpath 好.

Application 把 jar 直接往 jre/lib/ext 放, 不是不可以, 而是*不應該*.
如果在 jre/lib/ext 下有一個 a.jar, 在classpath中有一個 a.jar,
在 WEB-INF/lib 下也有一個 a.jar,哪一個會先被用呢?
jini 兄提到的 uninstall 亦是個問題.

對新手來說, 建議把所有的 jar 往 jre/lib/ext 放可能方便些,
but may not be a good practice.

2. java怎麼把utf-8的字元串轉換為gb2312格式

Java中字元串轉碼,根據實際運用的環境有以下三種方式

1、使用Java.lang.String

這是最常用的方法,先用對應編碼獲取位元組,然後重新構造新編碼,示例代碼如下:

Strings="清山";
byte[]b=s.getBytes("utf-8");//編碼
Stringsa=newString(b,"gb2312");//解碼:用什麼字元集編碼就用什麼字元集解碼

2、java.io.InputStreamReader/OutputStreamWriter:橋轉換

讀寫文件的應用中,可以使用這種方式,直接在IO流構造中轉換,示例代碼如下:

InputStreamis=newFileInputStream("C:/項目進度跟蹤.txt");//文件讀取
InputStreamReaderisr=newInputStreamReader(is,"utf-8");//解碼
OutputStreamos=newFileOutputStream("C:/項目進度跟蹤_gb2312.txt");//文件輸出
OutputStreamWriterosw=newOutputStreamWriter(os,"gb2312");//開始編碼

3、java.nio.Charset

使用nio中的Charset轉換字元,示例代碼如下:

CharsetinSet=Charset.forName("utf-8");//解碼字元集
CharsetoutSet=Charset.forName("gb2312");//編碼字元集
CharsetDecoderde=inSet.newDecoder();//解碼器
CharsetEncoderen=outSet.newEncoder();//編碼

3. Netty 編碼器和解碼器

每個網路應用程序都必須定義如何解析在兩個節點之間來回傳輸的原始位元組,以及如何將數據格式與目標應用程序的格式進行相互轉換。這一轉換邏輯由編解碼器處理,編解碼器由編碼器和解碼器組成,它們可以將位元組流從一種格式轉換為另一種格式。編碼器操作出站數據,而解碼器處理入站數據。以客戶端應用程序為例,如果事件的運動方向是從客戶端到服務端的,那麼我們稱這些事件為出站。反之稱為入站。

Netty涉及的組件包括Channel、ChannelHandler、ChannelPipe等。ChannelHandler充當了處理入站和出站數據的應用程序邏輯容器。例如,實現ChannelInboundHandler介面(或ChannelInboundHandlerAdapter),就可以接收入站事件和數據,隨後由應用程序的業務邏輯處理。當需要給連接的客戶端發送響應時,也可以從ChannelInboundHandler中沖刷數據。業務邏輯通常寫在一個或多個ChannelInboundHandler中。ChannelOutboundHandler原理相同,但用於處理出站數據。

ChannelPipeline提供了ChannelHandler鏈的容器。對於出站數據,即客戶端發送給服務端的數據會通過pipeline中的一系列ChannelOutboundHandler,並被這些Handler處理,而入站數據則只調用pipeline里的ChannelInboundHandler邏輯。

通過Netty發送或接受一個消息時,就會發生一次數據轉換。入站消息會被解碼,從位元組轉換為另一種格式(如Java對象);如果是出站消息,則會被編碼成位元組。

Netty提供了一系列實用的編碼解碼器,它們實現了ChannelInboundHadnler或ChannelOutboundHandler介面。在這些類中,channelRead方法已經被重寫。以入站為例,對於每個從入站Channel讀取的消息,這個方法會被調用,隨後調用由已知解碼器提供的decode()方法進行解碼,並將已解碼的位元組轉發給ChannelPipeline中的下一個ChannelInboundHandler。

Netty提供了多種編解碼器,例如用於編解碼字元串的StringEncoder和StringDecoder,以及用於編解碼對象的ObjectEncoder和ObjectDecoder等。

解碼器用於將位元組解碼為消息,Netty的解碼器實現了ChannelInboundHandler。解碼器何時使用?當需要將入站數據從一種格式轉換為另一種格式時會用到。得益於ChannelPipeline的設計,可以將多個解碼器鏈接在一起,以實現任意復雜的轉換邏輯。將位元組解碼為消息的抽象類ByteToMessageDecoder,將入站數據進行緩沖,直到准備好處理。這是必須實現的唯一抽象方法,decode()方法被調用時會傳入包含傳入數據的ByteBuf,以及一個用來添加解碼消息的List。方法調用會重復,直到確定沒有新的元素被添加到該List,或者該ByteBuf中沒有更多可讀取的位元組。如果List不為空,它的內容會被傳遞給ChannelPipeline中的下一個ChannelInboundHandler。

將一種消息類型解碼為另一種,用於在兩個消息格式之間進行轉換(例如,從String->Integer)。對於每個需要被解碼為另一種格式的入站消息,該方法都會被調用,解碼消息隨後會被傳遞給ChannelPipeline中的下一個ChannelInboundHandler。

MessageToMessageDecoder,T代表源數據的類型。

Netty中的幾種常用Decoder。

Netty如何解決粘包半包問題?大多數協議(私有或公有)中,協議頭中會攜帶長度欄位,用於標識消息體或整包消息的長度,例如SMPP、HTTP協議等。由於基於長度解碼需求的通用性,Netty提供了LengthFieldPrepender和LengthFieldBasedFrameDecoder來自動屏蔽TCP底層的拆包和粘包問題。通過傳入正確的參數,可以輕松解決「讀半包」問題。

發送方使用LengthFieldPrepender給實際內容添加報文頭Length欄位,接受方使用LengthFieldBasedFrameDecoder進行解碼。協議格式如下:

Length欄位表示Content部分的位元組數,例如Length值為100,那麼意味著Content部分佔用的位元組數就是100。Length欄位本身佔用的位元組數也要存儲在欄位中,一般會使用固定的位元組數表示。例如使用2個位元組(有符號)表示length,可以表示的最大值為32767(約等於32K),這意味著Content部分佔用的位元組數最大不能超過32767。當然,Length欄位存儲的是Content欄位的真實長度。

Content欄位是我們要處理的真實二進制數據。在發送Content內容之前,首先需要獲取其真實長度,添加在內容二進制流之前,然後再發送。Length佔用的位元組數+Content佔用的位元組數,就是總共要發送的位元組數。

事實上,我們可以把Length部分看做報文頭,報文頭包含了解析報文體(Content欄位)的相關元數據。當然,LengthFieldBasedFrameDecoder並沒有限制我們只能添加Length報文頭,我們可以在Length欄位前或後加上一些其他報文頭。

LengthFieldPrepender尤其值得說明的一點是,其提供了實現零拷貝的另一種思路。而LengthFieldPrepender,由於需要在原來的二進制數據之前添加一個Length欄位,因此就需要對二者進行合並發送。但是LengthFieldPrepender並沒有採用CompositeByteBuf,其編碼過程如下:LengthFieldPrepender實際上是先把Length欄位(報文頭)添加到List中,再把msg本身(報文)添加到List中。而在發送數據時,LengthFieldPrepender的父類MessageToMessageEncoder會按照List中的元素下標按照順序發送,因此相當於間接的把Length欄位添加到了msg之前。從而避免了創建一個更大的ByteBuf將Length欄位和msg內容合並到一起。

熱點內容
怎麼在微信發文件夾 發布:2025-02-08 10:09:45 瀏覽:791
cryengine源碼 發布:2025-02-08 09:50:58 瀏覽:392
aardio可以反編譯嗎 發布:2025-02-08 09:50:53 瀏覽:483
公司營業執照密碼是什麼 發布:2025-02-08 09:47:56 瀏覽:854
體驗腳本 發布:2025-02-08 09:46:15 瀏覽:690
醫學生需要什麼配置的筆記本 發布:2025-02-08 09:45:34 瀏覽:771
騷擾電話資料庫 發布:2025-02-08 09:45:34 瀏覽:179
u盤文件加密器 發布:2025-02-08 09:40:35 瀏覽:769
plc數據存儲app 發布:2025-02-08 09:37:17 瀏覽:708
伺服器的峰值高低有什麼區別 發布:2025-02-08 09:35:46 瀏覽:689