顯示具有 Java 標籤的文章。 顯示所有文章
顯示具有 Java 標籤的文章。 顯示所有文章

2012年7月5日 星期四

JDBC與字元集總結


通過JDBC訪問資料庫時遇到的字元集問題中,可以歸納為如下因素:
- JVM對字元集的處理
JVM核心完全使用Unicode字元集,編碼上採用UTF-16LE(x86和Unix)。 Java編譯器掃描.java原始檔案時將完成預轉換,比如在中文Windows上編譯.java檔時,你可能已經注意到.java檔中的字串和.class中的不一樣。因為.java檔本身用的是gb2312編碼,而.class內則是UTF-16LE編碼。如果你的編輯器支持,你可能會選擇直接用UTF-8來書寫.java來源程式,這時Java編譯器就會用UTF-8對來源程式解碼。
在輸出時,比如調用System.out.print方法也將完成一個編碼轉換,在上述情況中經常是將記憶體中的UTF-16LE編碼的字串轉換成控制台上可讀的gb2312編碼。

- JSP頁面使用的字元集
運行JSP頁面前總會被預處理至.java程式並被編譯成.class,注意到JSP總是一個servlet,因此實際上這裡存在兩個字元集,一是.jsp檔本身使用的字元集,另一則是servlet輸出內容的字元集(content-type)。儘量使.jsp檔本身的字元集和輸出內容的字元集保持一致,比如一致採用UTF-8。Response的實現將jvm中的UTF-16LE字串轉換至<%@page encoding=...%>所指定的編碼,

- Connection 使用的字元集
連接的字元集限制了SQL語句可以使用的字元。這在UTF-16中格外明顯,如果連接不使用UTF-16的字元集,那麼由於大多數的Latin-1字元集對'\0'的處理將使大多數SQL語句成為無效語句,比如SELECT語句通過UTF-16LE編碼後將變成"S\0E\0L\0E\0C\0T\0...",伺服器的SQL分析器在遇到第一個'\0'便認為語句已經結束。

但仍然可以將UTF-16LE編碼的字串送入Latin-1字元集的連接,方法是SQL語句本身仍採用Latin-1編碼,而相關的字串(引號內部的)採用UTF-16LE。這種情況下,UTF-16LE的字串不能包括Unicode字元集中編碼小於256的字元(包括拉丁字母和數位、英文符號),否則SQL分析器會報告"字串未結束"之類的錯誤。(為什麼?)
- 資料庫系統
並不是所有資料庫都支援Unicode,你可能有必要通過字元集轉換來保存一些特殊的字元資料。如果資料庫僅支援Latin-1字元集(這樣的系統不在少數),對於中文的情況,你可以將字串用Latin-1編碼,然後用gb2312解碼,覺得困惑?如果你(曾經)是C++程式師,那麼這裡的編碼類似於dynamic_cast, 而解碼則相當於reinterpret_cast。
sql_str = new String( java_str.getBytes("ISO-8859-1"), "gb2312" );
在獲取資料的時候則剛好相反:
java_str = new String( sql_str.getBytes("gb2312"), "ISO-8859-1" );

如果資料庫系統支援Unicode,那麼請儘量採用Unicode。有些手冊上建議你根據具體情況決定是否使用Unicode,因為Unicode將佔用更多的存儲空間,而且如果採用UTF-8,排序的速度將會"減慢30% (mysql)",請不要為這些詞語而顧慮,大多數情況這些都不是問題。
對於SQL Server 2000,這篇文章值得一讀:
http://www.microsoft.com/china/msdn/library/techart/IntlFeaturesInSQLServer2000.asp
最關鍵的就是你需要在字串左邊加上N字元(N一定要大寫),如
INSERT INTO table(name_en, name_native) VALUES('yokohama', N' 橫? ')

對於Sybase資料庫(Sybase 11.5, Sybase 12),系統不支援UTF-16,但支援UTF-8,為了使用Unicode,你可能需要下面的連接字串:
jdbc:sybase:Tds:127.0.0.1:4000/database?charset=utf8&jconnect_version=0
類似的,在SQL語句中使用字元N修飾的字串,使SQL分析器認為字串是Unicode編碼的。
對於MySQL資料庫,系統支援四個級別的字元集設置:
連接,資料庫,表,欄位
MySQL參考手冊第9章有詳細的討論,但注意版本要求4.1.0以上,同時Windows (nt,2k,xp) 的用戶請注意 4.1.0 有個bug,你必須使用4.1.1才能正確使用Unicode。
在 SQL Server 和 Sybase 中都有N開頭的欄位類型,它們被設計用於國際化的字元存儲。在SQL Server中,比如NTEXT實際上就是用Unicode存儲的的欄位類型。
SQL-99規定了Unicode字串統一使用 u 首碼,如 u"??????",但目前還沒有見哪個資料庫系統支援這種語法。

附:幾個字元集支援的測試例子 (需要測試用的源碼可以向我要:jljljjl@yahoo.com)
聲明:
Connection c;
Statement s;
生成資料:
String lit1 = "的文本:中華人民共和國]";
String[] encs = new String[] {
"(default)",
"ISO-8859-1",
"cp850",
"gb2312",
"gbk",
"big5",
"UTF-16LE",
"UTF-16BE",
"UTF-8",
};

String javaSrc = "[這是預設編碼" + lit1;
byte[] rawdata;

s.executeUpdate("DELETE FROM StringTable");
for (int i = 0; i < encs.length; i++) {
String targetEncoding = encs[i];
javaSrc = "[這是" + targetEncoding + lit1;
String testTarget;

if (i == 0) {
rawdata = javaSrc.getBytes();
testTarget = new String(rawdata);
} else {
rawdata = javaSrc.getBytes(targetEncoding);
testTarget = new String(rawdata);
}

System.out.println(testTarget);

String sql = ("INSERT INTO StringTable(charset,text) VALUES(" +
"'" + targetEncoding + "', N'" + testTarget + "')");
System.out.println(sql);

s.executeUpdate(sql);
}
獲取資料:
ResultSet rs = s.executeQuery("SELECT * FROM StringTable");

String charset;
String text;
while (rs.next()) {
charset = rs.getString("charset").trim();
text = rs.getString("text");

System.out.println(charset + ": [" + text + "]");

byte[] raws = text.getBytes();

String restore;
if ("(default)".equals(charset)) {
restore = new String(raws);
} else {
restore = new String(raws, charset);
}
System.out.println(" --> [" + restore + "]");
}
典型測試結果:
SQL-Server, type = ntext
(default): [[這是(default)的文本:中華人民共和國]]
--> [[這是(default)的文本:中華人民共和國]]
ISO-8859-1: [[??ISO-8859-1???????????]]
--> [[??ISO-8859-1???????????]]
cp850: [[??cp850???????????]]
--> [[??cp850???????????]]
gb2312: [[這是gb2312的文本:中華人民共和國]]
--> [[這是gb2312的文本:中華人民共和國]]
gbk: [[這是gbk的文本:中華人民共和國]]
--> [[這是gbk的文本:中華人民共和國]]
big5: [[?琌big5?????㎝?]]
--> [[?是big5的文本:中?人民共和?]]
UTF-8: [[榪欐槸UTF-8鐨?枃鏈細涓??烘皯鍏卞拰鍥絔]
--> [[這是UTF-8的文本:中華人民共和國]]

SQL-Server, type = text
(default): [[這是(default)的文本:中華人民共和國]]
--> [[這是(default)的文本:中華人民共和國]]
ISO-8859-1: [[??ISO-8859-1???????????]]
--> [[??ISO-8859-1???????????]]
cp850: [[??cp850???????????]]
--> [[??cp850???????????]]
gb2312: [[這是gb2312的文本:中華人民共和國]]
--> [[這是gb2312的文本:中華人民共和國]]
gbk: [[這是gbk的文本:中華人民共和國]]
--> [[這是gbk的文本:中華人民共和國]]
big5: [[?琌big5?????㎝?]]
--> [[?是big5的文本:中?三民囝和?]]
UTF-8: [[榪欐槸UTF-8鐨?枃鏈細涓??烘皯鍏卞拰鍥絔]
--> [[這是UTF-8的文本:中華人民共和國]]
Sybase, type = char
(default): [[??(default)???????????]]
--> [[??(default)???????????]]
ISO-8859-1: [[??ISO-8859-1???????????]]
--> [[??ISO-8859-1???????????]]
cp850: [[??cp850???????????]]
--> [[??cp850???????????]]
gb2312: [[??gb2312???????????]]
--> [[??gb2312???????????]]
gbk: [[??gbk???????????]]
--> [[??gbk???????????]]
big5: [[??big5???????????]]
--> [[??big5???????????]]
UTF-16LE
--> [[?啦???????????乎?民共?]]
UTF-16BE:
--> [[??????????????乎?共???]
UTF-8: [[???UTF-8?????????????????]
--> [[???UTF-8?????????????????]

Sybase, type = nchar
(default): [[??(default)???????????]]
--> [[??(default)???????????]]
ISO-8859-1: [[??ISO-8859-1???????????]]
--> [[??ISO-8859-1???????????]]
cp850: [[??cp850???????????]]
--> [[??cp850???????????]]
gb2312: [[??gb2312???????????]]
--> [[??gb2312???????????]]
gbk: [[??gbk???????????]]
--> [[??gbk???????????]]
big5: [[??big5???????????]]
--> [[??big5???????????]]
UTF-16LE
--> [[?啦???????????乎?民共?]]
UTF-16BE:
--> [[??????????????乎?共???]
UTF-8: [[???UTF-8?????????????????]
--> [[???UTF-8?????????????????]
Sybase, type = char, charset=utf8
(default): [[這是(default)的文本:中華人民共和國]]
--> [[這是(default)的文本

2011年11月22日 星期二

Java與圖像的EXIF資訊


首先介紹一下什麼是EXIFEXIF Exchangeable Image File的縮寫,這是一種專門為數碼相機照片設定的格式。這種格式可以用來記錄數位照片的屬性資訊,例如相機的品牌及型號、相片的拍攝時間、拍攝時所設置的光圈大小、快門速度、ISO等等資訊。除此之外它還能夠記錄拍攝資料,以及照片格式化方式,這樣就可以輸出到相容EXIF格式的外設上,例如照片印表機等。

目前最常見的支援EXIF資訊的圖片格式是JPG,很多的圖像工具都可以直接顯示圖片的EXIF資訊,包括現在的一些著名的相冊網站也提供頁面用於顯示照片的EXIF資訊。本文主要介紹Java語言如何讀取圖像的EXIF資訊,包括如何根據EXIF資訊對圖像進行調整以適合使用者流覽。

目前最簡單易用的EXIF資訊處理的Java包是Drew Noakes寫的metadata-extractor,該專案最新的版本是2.3.0,支持EXIF 2.2版本。你可以直接從http://www.drewnoakes.com/code/exif/ 下載該項目的最新版本包括其源碼。

需要注意的是,並不是每個JPG影像檔都包含有EXIF資訊,你可以在Windows資源管理器按一下選中圖片後,如果該圖片包含EXIF資訊,則在視窗狀態列會顯示出相機的型號,如下圖所示:

拍攝設備的型號便是EXIF資訊中的其中一個。下面我們給出一段代碼將這個圖片的所有的EXIF資訊全部列印出來。
package com.liusoft.dlog4j.test;

import java.io.File;
import java.util.Iterator;

import com.drew.imaging.jpeg.JpegMetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import com.drew.metadata.exif.ExifDirectory;

/**
 * 測試用於讀取圖片的EXIF資訊
 * @author Winter Lau
 */
public class ExifTester {
     public static void main(String[] args) throws Exception {
         File jpegFile = new File("D:\\我的文件\\我的相冊\\DSCF1749.JPG");
         Metadata metadata = JpegMetadataReader.readMetadata(jpegFile);
         Directory exif = metadata.getDirectory(ExifDirectory.class);
         Iterator tags = exif.getTagIterator();
         while (tags.hasNext()) {
             Tag tag = (Tag)tags.next();
             System.out.println(tag);
         }
     }
}


metadata-extractor-2.3.0.jar檔加入到類路徑中編譯並執行上面這段代碼後可得到下面的運行結果:

[Exif] Make - FUJIFILM
[Exif] Model - FinePix A205S
[Exif] Orientation - Top, left side (Horizontal / normal)
[Exif] X Resolution - 72 dots per inch
[Exif] Y Resolution - 72 dots per inch
[Exif] Resolution Unit - Inch
[Exif] Software - Digital Camera FinePix A205S  Ver1.00
[Exif] Date/Time - 2005:05:13 22:18:49
[Exif] YCbCr Positioning - Datum point
[Exif] Copyright -    
[Exif] Exposure Time - 1/60 sec
[Exif] F-Number - F3
[Exif] Exposure Program - Program normal
[Exif] ISO Speed Ratings - 320
[Exif] Exif Version - 2.20
[Exif] Date/Time Original - 2005:05:13 22:18:49
[Exif] Date/Time Digitized - 2005:05:13 22:18:49
[Exif] Components Configuration - YCbCr
[Exif] Compressed Bits Per Pixel - 3 bits/pixel
[Exif] Shutter Speed Value - 1/63 sec
[Exif] Aperture Value - F3
[Exif] Brightness Value - -61/100
[Exif] Exposure Bias Value - 0 EV
[Exif] Max Aperture Value - F3
[Exif] Metering Mode - Multi-segment
[Exif] Light Source - Unknown
[Exif] Flash - Flash fired, auto
[Exif] Focal Length - 5.5 mm
[Exif] FlashPix Version - 1.00
[Exif] Color Space - sRGB
[Exif] Exif Image Width - 1280 pixels
[Exif] Exif Image Height - 960 pixels
[Exif] Focal Plane X Resolution - 1/2415 cm
[Exif] Focal Plane Y Resolution - 1/2415 cm
[Exif] Focal Plane Resolution Unit - cm
[Exif] Sensing Method - One-chip color area sensor
[Exif] File Source - Digital Still Camera (DSC)
[Exif] Scene Type - Directly photographed image
[Exif] Custom Rendered - Normal process
[Exif] Exposure Mode - Auto exposure
[Exif] White Balance - Auto white balance
[Exif] Scene Capture Type - Standard
[Exif] Sharpness - None
[Exif] Subject Distance Range - Unknown
[Exif] Compression - JPEG (old-style)
[Exif] Thumbnail Offset - 1252 bytes
[Exif] Thumbnail Length - 7647 bytes
[Exif] Thumbnail Data - [7647 bytes of thumbnail data]
從這個執行的結果我們可以看出該照片是在20050513 221849秒拍攝的,拍攝用的相機型號是富士的FinePix A205S,曝光時間是1/60秒,光圈值F3,焦距5.5毫米,ISO值為320等等。

你也可以直接指定讀取其中任意參數的值,ExifDirectory類中定義了很多以TAG_開頭的整數常量,這些常量代表特定的一個參數值,例如我們要讀取相機的型號,我們可以用下面代碼來獲取。

Metadata metadata = JpegMetadataReader.readMetadata(jpegFile);
Directory exif = metadata.getDirectory(ExifDirectory.class);
String model = exif.getString(ExifDirectory.TAG_MODEL);

上述提到的是如何獲取照片的EXIF資訊,其中包含一個很重要的資訊就是——拍攝方向。例如上面例子所用的圖片的拍攝方向是:Orientation - Top, left side (Horizontal / normal)。我們在拍照的時候經常會根據場景的不同來選擇相機的方向,例如拍攝一顆高樹,我們會把相機豎著拍攝,使景物剛好適合整個取景框,但是這樣得到的圖片如果用普通的圖片流覽器看便是倒著的,需要調整角度才能得到一個正常的圖像,有如下面一張照片。

這張圖片正常的情況下需要向左調整90度,也就是順時針旋轉270度才適合觀看。通過讀取該圖片的EXIF資訊,我們得到關於拍攝方向的這樣一個結果:[Exif] Orientation - Left side, bottom (Rotate 270 CW)。而直接讀取ExitDirectory.TAG_ORIENTATION標籤的值是8。我們再來看這個項目是如何來定義這些返回值的,打開源碼包中的ExifDescriptor類的getOrientationDescription方法,該方法代碼如下:
public String getOrientationDescription() throws MetadataException
{
        if (!_directory.containsTag(ExifDirectory.TAG_ORIENTATION)) return null;
        int orientation = _directory.getInt(ExifDirectory.TAG_ORIENTATION);
        switch (orientation) {
            case 1: return "Top, left side (Horizontal / normal)";
            case 2: return "Top, right side (Mirror horizontal)";
            case 3: return "Bottom, right side (Rotate 180)";
            case 4: return "Bottom, left side (Mirror vertical)";
            case 5: return "Left side, top (Mirror horizontal and rotate 270 CW)";
            case 6: return "Right side, top (Rotate 90 CW)";
            case 7: return "Right side, bottom (Mirror horizontal and rotate 90 CW)";
            case 8: return "Left side, bottom (Rotate 270 CW)";
            default:
                return String.valueOf(orientation);
        }
}

從這個方法我們可以清楚看到各個返回值的意思,如此我們便可以根據實際的返回值來對圖像進行旋轉或者是鏡像處理了。在這個例子中我們需要將圖片順時針旋轉270度,或者是逆時針旋轉90度方可得到正常的圖片。

雖然圖片的旋轉不在本文範疇內,但為了善始善終,下面給出代碼用以旋轉圖片,其他的關於圖片的鏡像等處理讀者可以依此類推。

String path = "D:\\TEST.JPG";
File img = new File(path);
BufferedImage old_img = (BufferedImage)ImageIO.read(img); 
int w = old_img.getWidth();
int h = old_img.getHeight();

BufferedImage new_img = new BufferedImage(h,w,BufferedImage.TYPE_INT_BGR);     
Graphics2D g2d =new_img.createGraphics();
     
AffineTransform origXform = g2d.getTransform();
AffineTransform newXform = (AffineTransform)(origXform.clone());
// center of rotation is center of the panel
double xRot = w/2.0;
newXform.rotate(Math.toRadians(270.0), xRot, xRot); //旋轉270

g2d.setTransform(newXform);
// draw image centered in panel
g2d.drawImage(old_img, 0, 0, null);
// Reset to Original
g2d.setTransform(origXform);
//寫到新的檔
FileOutputStream out = new FileOutputStream("D:\\test2.jpg");
try{
ImageIO.write(new_img, "JPG", out);
}finally{
    out.close();
}

旋轉後的照片如下:

但是利用上面的代碼旋轉照片後,原有照片包含的EXIF資訊不復存在了。至於照片的鏡面翻轉可以直接利用Graphic2DdrawImage方法來實現,方法原形如下:
drawImage

public abstract boolean drawImage(Image img,
                   int dx1,
                                  int dy1,
                                  int dx2,
                                  int dy2,
                                  int sx1,
                                  int sy1,
                                  int sx2,
                                  int sy2,
                                  ImageObserver observer)
該方法的使用請參考JDKAPI文檔。關於照片旋轉後丟失EXIF資訊的問題,需要在照片旋轉之前先把EXIF資訊讀出,然後再在旋轉後寫入新的照片中,你可以使用MediaUtil包來寫EXIF資訊到圖片檔中,關於這個包的使用請參考該項目所給出的例子,本文不再敘述。
 
參考資料:
 
metadata-extractor  http://www.drewnoakes.com/code/exif/
MediaUtil        http://mediachest.sourceforge.net/mediautil/

Java讀取圖片EXIF資訊


首先介紹一下什麼是EXIFEXIFExchangeable Image File的縮寫,這是一種專門為數碼相機照片設定的格式。這種格式可以用來記錄數位照片的屬性資訊,例如相機的品牌及型號、相片的拍攝時間、拍攝時所設置 的光圈大小、快門速度、ISO等等資訊。除此之外它還能夠記錄拍攝資料,以及照片格式化方式,這樣就可以輸出到相容EXIF格式的外設上,例如照片印表機 等。
目前最常見的支援EXIF資訊的圖片格式是JPG,很多的圖像工具都可以直接顯示圖片的EXIF資訊,包括現在的一些著名的相冊網站也提供頁面用於 顯示照片的EXIF資訊。本文主要介紹Java語言如何讀取圖像的EXIF資訊,包括如何根據EXIF資訊對圖像進行調整以適合使用者流覽。
目前最簡單易用的EXIF資訊處理的Java包是Drew Noakes寫的metadata-extractor,該專案最新的版本是2.3.4,支持EXIF 2.2版本。你可以直接從http://www.drewnoakes.com/code/exif/ 下載該項目的最新版本包括其源碼。
需要注意的是,並不是每個JPG影像檔都包含有EXIF資訊,你可以在Windows資源管理器按一下選中圖片後,如果該圖片包含EXIF資訊,則會在屬性->摘要中顯示出來。

拍攝設備的型號便是EXIF資訊中的其中一個。下面我們給出一段代碼將這個圖片的所有的EXIF資訊全部列印出來。
Java代碼  收藏代码
1.  import java.io.File;  
2.  import java.util.Iterator;  
3.     
4.  import com.drew.imaging.jpeg.JpegMetadataReader;  
5.  import com.drew.metadata.Directory;  
6.  import com.drew.metadata.Metadata;  
7.  import com.drew.metadata.Tag;  
8.  import com.drew.metadata.exif.ExifDirectory;  
9.     
10. /** 
11.  * 測試用於讀取圖片的EXIF資訊 
12.  * @author Winter Lau 
13.  */  
14. public class ExifTester {  
15.      public static void main(String[] args) throws Exception {  
16.          File jpegFile = new File("C:/Documents and Settings/Administrator/workspace/ipv6/src/test/a.JPG");  
17.          Metadata metadata = JpegMetadataReader.readMetadata(jpegFile);  
18.          Directory exif = metadata.getDirectory(ExifDirectory.class);  
19.          Iterator tags = exif.getTagIterator();  
20.          while (tags.hasNext()) {  
21.              Tag tag = (Tag)tags.next();  
22.              System.out.println(tag);  
23.          }  
24.      }  
25. }  
 這個結果顯示如下:
Js代碼  收藏代码
1.  [Exif] Make - OLYMPUS OPTICAL CO.,LTD  
2.  [Exif] Model - u10D,S300D,u300D  
3.  [Exif] Orientation - Top, left side (Horizontal / normal)  
4.  [Exif] X Resolution - 72 dots per inch  
5.  [Exif] Y Resolution - 72 dots per inch  
6.  [Exif] Resolution Unit - Inch  
7.  [Exif] Software - 22-1012                          
8.  [Exif] Date/Time - 2005:04:14 13:47:10  
9.  [Exif] YCbCr Positioning - Datum point  
10. [Exif] Exposure Time - 0.01 sec  
11. [Exif] F-Number - F5.2  
12. [Exif] Exposure Program - Program creative (slow program)  
13. [Exif] ISO Speed Ratings - 80  
14. [Exif] Exif Version - 2.20  
15. [Exif] Date/Time Original - 2005:04:14 13:47:10  
16. [Exif] Date/Time Digitized - 2005:04:14 13:47:10  
17. [Exif] Components Configuration - YCbCr  
18. [Exif] Exposure Bias Value - 0 EV  
19. [Exif] Max Aperture Value - F3.1  
20. [Exif] Metering Mode - Multi-segment  
21. [Exif] Light Source - Unknown  
22. [Exif] Flash - Flash did not fire, auto  
23. [Exif] Focal Length - 17.4 mm  
24. [Exif] User Comment -   
25. [Exif] FlashPix Version - 1.00  
26. [Exif] Color Space - sRGB  
27. [Exif] Exif Image Width - 1024 pixels  
28. [Exif] Exif Image Height - 768 pixels  
29. [Exif] File Source - Digital Still Camera (DSC)  
30. [Exif] Windows XP Title - 風景  
31. [Exif] Windows XP Author - 一路風塵  
32. [Exif] Windows XP Keywords - 你是我的唯一  
33. [Exif] Windows XP Subject - 我的第一張  
34. [Exif] Custom Rendered - Normal process  
35. [Exif] Exposure Mode - Auto exposure  
36. [Exif] White Balance - Auto white balance  
37. [Exif] Digital Zoom Ratio - 1  
38. [Exif] Scene Capture Type - Landscape  
39. [Exif] Gain Control - None  
40. [Exif] Contrast - None  
41. [Exif] Saturation - None  
42. [Exif] Sharpness - None  
43. [Exif] Unknown tag (0xc4a5) - 80 114 105 110 116 73 77 0 480 2 -10...  
44. [Exif] Compression - JPEG (old-style)  
45. [Exif] Thumbnail Offset - 2022 bytes  
46. [Exif] Thumbnail Length - 5864 bytes  
47. [Exif] Thumbnail Data - [5864 bytes of thumbnail data]  
 起初的時候,我只想找到圖片的作者,標題,關鍵字這三欄資訊,那如何取得這三者的資訊呢。可以直接使用API如下:
metadata中定義了很多TAG資訊:比如:TAG_WIN_AUTHOR
TAG_WIN_KEYWORDS
TAG_WIN_TITLE
等定義在Windows中資訊。所以我們只要:
Java代碼  收藏代码
1.  package test;  
2.  import java.io.File;  
3.  import java.util.Iterator;  
4.     
5.  import com.drew.imaging.jpeg.JpegMetadataReader;  
6.  import com.drew.metadata.Directory;  
7.  import com.drew.metadata.Metadata;  
8.  import com.drew.metadata.Tag;  
9.  import com.drew.metadata.exif.ExifDirectory;  
10.    
11. /** 
12.  * 測試用於讀取圖片的EXIF資訊 
13.  * @author Winter Lau 
14.  */  
15. public class PicExif {  
16.      public static void main(String[] args) throws Exception {  
17.          File jpegFile = new File(  
18.                           "C:/Documents and Settings/Administrator/workspace/ipv6/src/test/a.JPG");  
19.          Metadata metadata = JpegMetadataReader.readMetadata(jpegFile);  
20.          Directory exif = metadata.getDirectory(ExifDirectory.class);  
21.          Iterator tags = exif.getTagIterator();  
22.   
23.           if(exif.containsTag(ExifDirectory.TAG_WIN_AUTHOR)){  
24.               System.out.println("Pic author is "+exif.getDescription(ExifDirectory.TAG_WIN_AUTHOR));        
25.          }  
26.           if(exif.containsTag(ExifDirectory.TAG_WIN_TITLE)){  
27.             System.out.println("Pic title is "+exif.getDescription(ExifDirectory.TAG_WIN_TITLE));      
28.           }  
29.           if(exif.containsTag(ExifDirectory.TAG_WIN_KEYWORDS)){  
30.         System.out.println("Pic keyword is "+exif.getDescription(ExifDirectory.TAG_WIN_KEYWORDS));  
31.          }  
32.      }  
33. }  
 列印的結果:
Java代碼  收藏代码
1.  Pic author is 一路風塵  
2.  Pic title is 風景  
3.  Pic keyword is 你是我的唯一  
 有了這些API,我們還可以做其他事情。這裡不一一列舉了,有興趣的直接看http://www.drewnoakes.com/code/exif/javadoc/