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

2019年2月27日 星期三

[Java] 解決匯出CSV檔的中文問題

BOM (Byte Order Mark) 是用於表示文件採用何種編碼模式,一般藏於文件開頭的前幾碼,目的是讓不同的編輯器知道要採用何種方式進行打開。

在Windows下,若要以UTF-8來儲存,則必須在文件的最開頭寫入 {0xEF, 0xBB, 0xBF},此三碼即是BOM。故在Java端的撰寫如下:


    File file = new File("test.csv");
    FileOutputStream out=null;
    OutputStreamWriter osw=null;
    BufferedWriter bw=null;
    
    out = new FileOutputStream(file);
    byte[] uft8bom={(byte)0xef,(byte)0xbb,(byte)0xbf};
    out.write(uft8bom);
    osw = new OutputStreamWriter(out,StandardCharsets.UTF_8);
    bw = new BufferedWriter(osw);
    bw.append("TEST,中文,是否\r\n");
    bw.close();
    

Reference :
[1] BOM (隐藏字符)
[2] JAVA/SERVLET 以UTF-8导出CSV文件时产生乱码的解决方法

2016年5月17日 星期二

[Ubuntu] Ubuntu14.04 安裝 Java + Tomcat + Mysql

安裝步驟
  • 安裝Java
  • #apt-get install openjdk-7-jdk

  • 安裝Tomcat
  • #apt-get install tomcat7

  • 安裝Mysql
  • #apt-get install mysql-server libmysql-java

  • tomcat7設定檔
  • #vim /etc/default/tomcat7
    JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom -Djava.awt.headless=true -Xmx512m -XX:MaxPermSize=256m -XX:+UseConcMarkSweepGC"

  • 預設Tomcat開啟的Port 8080,若想改接收Port 80,可加入以下iptables command
  • #iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

Reference :
[1] How To Install Apache Tomcat 7 on Ubuntu 14.04 via Apt-Get

2015年4月3日 星期五

[Java] Hashtable 提供 get功能

Hashtable map = new Hashtable();

....

Object get(int i) {
    int j = 1;
    for ( Object key : map.keySet() ) {
        if ( i == j++ ) {
            return  map.get(key);
        }
    }
    return null;
}   
 

2014年9月25日 星期四

[Java] ResultSet 序列化/反序列化應用於HTTP Protocol

ResultSet是JDBC用來回傳SQL結果的物件,原先設計考慮大量資料擷取並不會一次性將資料取回至ResultSet,而是可能會採取類似Cache概念,當發生Cache Error時,在動態跟後端資料庫拿取資料,因此,這樣的特性就不適用於Serialiable。那如果還是需要使用ResultSet來做訊息傳遞怎麼辦? 可以考慮以下這些做法
  1. 使用com.sun.rowset.jar來達成(Android上不能使用,kernel core衝突)
  2. 自幹搭配mockrunner
  3. 自幹
自幹方法還蠻容易的,只要做一個Convert來做轉換ResultSet與SerialiableResultSet的轉換,並implements會用到的JDBC Interfaces即可。

Scenario 就如圖一,Client發送Request,Server執行SQL Query後得到的結果(ResultSet),透過Convert Class轉換成一個可Serialiable的物件,然後透過Serialiable傳遞後,再透過Convert轉換回ResultSet即可,程式可參考 https://github.com/linuxxunil/blog/tree/master/Java/SerialiableResultSet



圖一: Request / Response Scenario

Reference :
[1] Java 序列化/反序列化 (Serialization/Deserialization)
[2] http://mockrunner.github.io/

2014年8月27日 星期三

[Java] Add Web Development (Tomcat) to Eclipse

  1. 下載Tomcat執行檔
  2.  安裝Eclipse Plugin
    • [Eclipse] -> [Help] -> [Install New Software]
    • Work with : Luna - http://download.eclipse.org/releases/luna
    • 安裝套件 :
      [Web, XML, Java EE and OSGI Enterprise Development] ->
      • <v> JST Server Adapter Extensions ( for apache tomcat)
      • <v> Eclipse Java EE Developer Tools
  3. 設定 Eclipse
    • [Eclipse] -> [Windows] -> [Preferences] -> [Server] -> [Runtime Environment]
    • 加入新的Profile,設定tomcat路徑(tomcat執行檔路徑)
      add new server profile
    • 重新執行專案即可

2014年7月7日 星期一

[Java] 如何對HashTable裡的值做sort

public static Hashtable<String,Integer> getTablesInfo() {
    Hashtable<String,Integer> tables = new Hashtable<String,Integer>();
    tables.put("AAA", 5);
    tables.put("BBB", 4);
    tables.put("CCC", 7);
    tables.put("DDD", 2);
    tables.put("EEE", 1);
    return tables;
}
   
public static void sort(Hashtable<String, Integer> t){
    //Transfer as List and sort it
    ArrayList<Map.Entry<String, Integer>> l = new ArrayList(t.entrySet());
    Collections.sort(l, new Comparator<Map.Entry<String, Integer>>(){
        public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
            return o1.getValue().compareTo(o2.getValue());
        }});
   
    System.out.println(l);
}
   
public static void main (String[] args) {
       
        Hashtable<String,Integer> tables = getTablesInfo();
        
        sort(tables);
}

Reference: 
[1] How to sort a Java Hashtable?

2014年6月17日 星期二

[Java] 如何使用Java處理多回傳值

寫慣C/C++的人,處理多回傳值,都會使用Call by Reference or Call by Address的方式來達成目標。但非常可惜的,Java並不提供這兩種傳遞參數的方式,只有Call by Value,故Java要使用常規寫法,是無法達成多回傳值處理,不過還是可以透過一些特殊方式來達成。

首先,先探討一下Java 的傳參數的概念,上述提及Java只有Call by value[1][2],以下用個簡單的例子說明

Sample1 :
    public static void main(String[] args){
        int a1 = 5;
        int[] a2 = new int[1];              
        System.out.println("a1 value = " + a1);
        System.out.println("a2 value = " + a2);
    }

Output :
a1 value = 5
a2 value = [I@3771ed5e

Java本身並無指標的概念,所以變數只會儲存Value,如a1是存儲存5,而a2則是存儲address value(也是Value)。故以這樣的概念,只要call by value的value是address,那就可以達成如C/C++的操作,以下提供兩種方式來達成多變數回傳。

Sample2: 陣列法
陣列法缺點在於,陣列大小必須在外層就決定,無法從內層決定,故如果必須從內層決定,那只能用物件法。

    public static void swap(int[] a, int[] b) {
        int tmp  = 0;
            tmp  = a[0];
            a[0] = b[0];
            b[0] = tmp;
    }
     
    public static void main(String[] args){
      
        int[] a = {1};
        int[] b = {2};
        swap(a,b);
        System.out.println("a value = " + a[0] );
        System.out.println("b value = " + b[0] );
    }

Sample3: 物件法(也是傳address方式)
public class SampleRef {
  
    int x;
  
    public SampleRef(int x) {
        this.x = x;
    }
  
    public static void swap(SampleRef a, SampleRef b) {
        int tmp = 0 ;
            tmp = a.x;
            a.x = b.x;
            b.x = tmp;
    }
  
    public static void main(String[] args){
        SampleRef a = new SampleRef(1);
        SampleRef b = new SampleRef(2);
      
        swap(a,b);
        System.out.println("a value = " + a.x );
        System.out.println("b value = " + b.x );  
    }
}

Reference
[1] Java沒有指標? - 淺談參考(Reference)與物件的複製(Object copy)
[2] 獅子的鬃毛--Java 的物件傳遞是 Call By Reference
[3] How do I pass a primitive data type by reference

2014年3月17日 星期一

[Java] 常用字串處理

1.  字符串長度不足左補0

String   str = String.format("%05d", 5) ;

>> 00005

String str = String.format("%05s","5");

>> 00001


2.字串轉Integer

int num  = Integer.parseInt("0001");

>> 1

2014年3月5日 星期三

[Java] Exception 觀念筆記




圖一

Java Exception 分成兩類,
  • Checked exception : Checked exceptions for recoverable conditions. 
    • 此類型的Exception,都是繼承Exception類別
    • Java認為這類Exception,是可以修復的或處理的,故強迫開發者進行處理

  • Unchecked exceptions :  Runtime (unchecked) exceptions for programming errors.
    • 此類型的Exception,均是繼承RuntimeException類別,雖然說RuntimeException本身也繼承Exception,不過在理念上,這兩種屬於不同類型。
    • Java認為這類Exception,是無法進行處理的,即所謂的Bug。(Ex: 除零)
而發生Excpetion的情況,又可分成三種,
  • Exceptions due to programming errors
    這類錯誤,屬於程式撰寫上錯誤(NullPointerException,IllegalArgumentException),並且這類型錯誤是無法修復的,故屬於Unchecked Exception。
  • Exceptions due to client code errors這類錯誤,屬於不正常API所產生的錯誤,例如試圖開啟某個File,結果發生IOException,此類型是可以修復,如嘗試開啟其他路徑的備份檔案,故此類型較類似Checked Exception。
  • Exceptions due to resource failures 這類錯誤,屬於資源分配錯誤,因系統資源不足而導致發生Excpetion,故也屬於Unchecked Exception。

雖然大致上如上定義,但在使用上其實會有些issue,例如當發生SQLException時,雖然知道他屬於Checked Exception,但其實這是一個無法Recovery的程式,而把定義成CheckedException是乎也不太合適,在 Best Practices for Exception Handling 提出,

When deciding on checked exceptions vs. unchecked exceptions, ask yourself, "What action can the client code take when the exception occurs?"


簡單的說,若是你覺得這個Exception無法復原,你就把他定義成 Unchecked Exception,若原本是Checked Excpetion,那就轉換成 RuntimeException(如下),來讓開發者清楚這其實是個Bug。

public void dataAccessCode(){
    try{
        ..some code that throws SQLException
    }catch(SQLException ex){
        throw new RuntimeException(ex);
    }
}

Reference
[1] Checked or unchecked exceptions (1)
[2] Best Practices for Exception Handling
[3]  Java Exception处理之最佳实践

2013年9月4日 星期三

[Java] FTPClient 使用Binary Mode

檔案,是一組Binary Code的集合,故又會稱做Binary File(通常使用HEX表示),但這樣的檔案是不具有可讀性的,所以又定義由ASCII字元所組成的檔案, 稱做ASCII File或Text File。

一般在做檔案複製,若使用ASCII File來處理,在不同的作業系統間,則可能會發生錯誤,因不同作業系統之間的 "換行字元"定義不一樣,如
  • Windows : \r\n (0x0D 0x0A)
  • Linux : \n (0x0A)
故通常,在做複製檔案時,會使用Binary的方式做處理。

  

 上圖是使用FTPClient,從Windows透過FTP傳送檔案到Linux系統上,
  • 左邊 : Windows下的原始檔
  • 右邊 : 透過FTPClient 傳送給Linux下的檔案
圖中清楚顯示了透過FTPClient傳送到Linux下的檔案多了0x0D,這是因為FTPClient預設是使用ASCII Mode,並且在Windows作業系統底下,以至於當要寫入段行時,會增加0x0D字元,故要解決這個問題,只要將讀取檔案的模式改成 Binary Mode即可。

FTPClient 的設定如下:

FTPClient client = new FTPClient();
client.setFileType(FTP.BINARY_FILE_TYPE);
client.setFileTransferMode(FTP.BINARY_FILE_TYPE); 

 Reference :
[1]  Ascii vs. Binary Files 
[2]  Jave FTPClient Document

2013年7月31日 星期三

[Java] 使用Java實做,AES encrypt and decrypt

AES (Advanced Encryption Standard,AES)是用來取代DES的新的進階加密法,又稱Rijndael加密法,是美國聯邦政府採用的一種區塊加密標準。
 
AES 有幾個概念,
  • Key : 長度分成128bit(16byte)、192bit(24byte)和256bit(byte)
  • Mode :
    • ECB:為基礎加密模式,plain text 被分割成相同長度的區塊,然後再一一的加密組成cipher text。(本文使用模式)
    • CBC:是一種循環模式,前一個分組的密文和當前分組的明文異或操作後再加密,這樣做的目的是增強破解難度。
    • CFB/OFB 實際上是一種反饋模式,目的也是增強破解的難度。
    • ECB和CBC 的加密結果是不一樣的,兩者的模式不同,而且CBC會在第一個密碼塊運算時加入一個初始化向量。 
       
  • PKCS5Padding : 當一次加密的長度不足16byte時,須做填充補足,而PKCS5Padding及填充的方式。 
Java本身就提供了完整的crypt library( javax.crypto.* ),只要有安裝完整的JDK,就不需要在額外安裝或下載jar file。

  • Java 支援的功能
    • AES/CBC/NoPadding (128)
    • AES/CBC/PKCS5Padding (128)
    • AES/ECB/NoPadding (128)
    • AES/ECB/PKCS5Padding (128)

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

class Convert {
   
    /**
     * str2byte : String to Byte
     * Eg. 00010203 --> 0x00 0x01 0x02 0x03
     */
    public static byte[] str2byte(String key)
    {
        byte[] b = new byte[key.length()/2];

        for(int i=0, bStepper=0; i<key.length()+2; i+=2)
            if(i !=0)
                b[bStepper++]=((byte)Integer.parseInt((key.charAt(i-2)+""+key.charAt(i-1)), 16));

        return b;
    }
   
    /**
     * byte2str : Byte to String
     * Eg. 0x00 0x01 0x02 0x03 --> 00010203
     */
    public static String byte2str (byte buf[]) {
        StringBuffer strbuf = new StringBuffer(buf.length * 2);
        int i;

        for (i = 0; i < buf.length; i++) {   
            if (((int) buf[i] & 0xff) < 0x10)
                strbuf.append("0");
            strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
            strbuf.append(" ");
        }
        return strbuf.toString();
    }
}

class AESEncrypt {
    private SecretKeySpec skeySpec;
    private Cipher cipher;
    private Cipher noPadding;
    private Cipher padding;
    private byte[] key;
   
    public AESEncrypt() throws NoSuchAlgorithmException, NoSuchPaddingException{
        KeyGenerator keyG = KeyGenerator.getInstance("AES");
        keyG.init(128);
        SecretKey secuK = keyG.generateKey();
        this.key = secuK.getEncoded();
        init();
    }
   
    public AESEncrypt(String key) throws NoSuchAlgorithmException, NoSuchPaddingException{
        this.key = Convert.str2byte(key);
        init();
    }
   
    private void init() throws NoSuchAlgorithmException, NoSuchPaddingException{
        this.skeySpec = new SecretKeySpec(this.key, "AES");
        this.noPadding = Cipher.getInstance("AES/ECB/NoPadding"); 
        this.padding = Cipher.getInstance("AES/ECB/PKCS5Padding");
        this.cipher = noPadding;
    }
   
    public void setNoPadding() {
        this.cipher = noPadding;
    }
   
    public void setPKCS5Padding() {
        this.cipher = padding;
    }
   
    public  byte[] encrypt( byte[] byteArray, int offset, int len ) throws Exception{
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        return cipher.doFinal(byteArray, offset, len);
    }
   
    public  byte[] encrypt( byte[] byteArray ) throws Exception{
        return encrypt( byteArray, 0, byteArray.length);
    }
   
    public  byte[] decrypt( byte[] byteArray, int offset, int len ) throws Exception{
        this.cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        return cipher.doFinal(byteArray, offset, len);
    }   
   
    public  byte[] decrypt( byte[] byteArray ) throws Exception{
        return decrypt( byteArray, 0, byteArray.length);
    }
   
    public void encryptFile(FileInputStream fim, FileOutputStream fom) throws Exception {
         byte[] buffer = new byte[16];
         int length = -1;
       
         while((length = fim.read(buffer, 0, buffer.length)) != -1) {
             if ( length < buffer.length ) setPKCS5Padding();
             else setNoPadding();
           
             byte[] decoder = encrypt(buffer, 0, length);
             fom.write(decoder, 0, decoder.length);
         }
    }
   
    public void decryptFile(FileInputStream fim, FileOutputStream fom) throws Exception {
        byte[] buffer = new byte[8192];
        int length = -1;
      
        while((length = fim.read(buffer,0,buffer.length)) != -1) {
            if ( length < buffer.length ) setPKCS5Padding();
            else setNoPadding();
           
            byte[] decoder = decrypt(buffer, 0, length);
            fom.write(decoder, 0, decoder.length);
        }
    }
}

public class SampleAES {
   
    public static void demoStringCrypt() throws Exception {
        System.out.println("### Demo String Encrypt and Decrypt");
       
        String plainText = "HelloWorld";
       
        // 128 bit
        AESEncrypt aes = new AESEncrypt("000102030405060708090A0B0C0D0E0F");
       
        // encode
        if ( (plainText.getBytes().length % 16) == 0) aes.setNoPadding();
        else aes.setPKCS5Padding();
        byte[] encoder = aes.encrypt(plainText.getBytes());
       
        System.out.println("Encoder: " + Convert.byte2str(encoder));
       
        // decode
        aes.setPKCS5Padding();
        String decoder = new String(aes.decrypt(encoder));
        System.out.println("Decoder: " + decoder);
    }
   
    public static void demoFileCrypt()  throws Exception {
        System.out.println("### Demo File Encrypt and Decrypt");
       
        String plainFile = "plainText.txt";
        String encodeFile = "encode.txt";
        String decodeFile = "decode.txt";
       
        FileInputStream plainText =
                new FileInputStream(new File(plainFile));
        
        FileOutputStream encode =
                new FileOutputStream(new File(encodeFile));
   
        AESEncrypt aes = new AESEncrypt();
       
        // encrypt file
        System.out.println(plainFile + " encrypt to " + encodeFile);
        aes.encryptFile(plainText, encode);
       
        FileInputStream cipherText =
                new FileInputStream(new File(encodeFile));
       
        FileOutputStream decode =
                new FileOutputStream(new File(decodeFile));
       
        // decrypt file
        System.out.println(encodeFile + " decrypt to " + decodeFile);
        aes.decryptFile(cipherText, decode);
       

        plainText.close();
        encode.close();
        cipherText.close();
        decode.close();   
    }
   
    public static void main(String[] args) throws Exception {
       
        demoStringCrypt();

        demoFileCrypt();
     }
}

  •  Note: 以下記錄在撰寫中發生的Error Message
    • Give final block not properly padded : 再測試加密檔案時,一直發生此錯誤,後來發現是由padding的所造成的,在進行加解密時,都必須確認要做加解密的陣列, 是否需要做padding,需要則呼叫setPKCS5Padding(),不需要則呼叫setNoPadding()。


Reference : 
[1] 分组对称加密模式:ECB/CBC/CFB/OFB
[2] Java AES Encrypt & Decrypt Example(加解密)
[3] 使用 Java 進行 AES 加密
[4] Class Cipher

2013年7月18日 星期四

[Java] synchronized 的用法

Java在建立critical section是透過 synchronized這個關鍵字來實現,synchronized提供兩種語法 :

1. synchronized method

public synchronized void increment() { // critical section }
public synchronized void decrement() { // critical section }

2. Synchronized Statements 

public void increment() {
    synchronized(this) {
            // critical section
    }
}

從Synchronized Statements注意到,synchronized是針對整個物件做lock,故如果Class有多的地方使用的 synchronized功能,須注意到是否會產生deadlock。

Reference :
[1] http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

2013年6月23日 星期日

[Java] Security Manager (Security Excetpion)

最近在執行以前撰寫的Applet時,都會無法執行,並且產生Security Exception的訊息或一些安全性的問題。

傳統上,一個web applet通常是運作在一個Security manager上,而通常是由Browser或Java Web Start plugin來啟動,而一般的applications是不需運作在security manager,當然你也可以使用Security Manager來執行,VM參數加入(-Djava.security.manager)。

而透過Browser開啟某個applet網頁,Browser是先到相對應網址去下載jar檔,然後再透果本機端的jvm來執行,但其實這樣的行為是不安全的,故browser在開啟applet時,將會啟動Security Manager模式,所造成的結果,即所有執行的jar檔裡沒有包含signer的,一律不給予執行,有的將會在詢問使用者是否可執行。(如下圖)


所以說,現在只要是要透過Browser開啟的jar檔(即使是自己寫的也是),都必須加入Certificate 。

步驟如下:
1. 申請 Certificate (windows檔案在..\Java\jdk1.6.0_43\bin\keytool.exe )
#keytool -genkey

Note:預設檔案將會被建立在user目錄下.keystore檔別名為 mykey,而此檔案包含用戶的public key,private key和Certificate。(windows:C:\Documents and Settings\UserName\.keystore)

2. 將Certificate加入到jar檔裡(windows檔案在..\Java\jdk1.6.0_43\bin\jarsigner.exe )
指令 : jarsigner [jar file] [alias name]
#jarsigner calculator.jar mykey

Reference :
1. Java Keytool的使用及申請憑證(以Microsoft Active Directory Certificate Services為例)
2. Java(含Applet)的安全機制(Security Manager)

2013年6月6日 星期四

[Java] Complier Java on Linux

[Java] java.lang.ClassNotFoundException on Eclipse 介紹了如何使用Ecslipse來產生Jar,接下來介紹一下如何在Linux下,Compiler Java。
雖然是在寫Java的程式,不過還是利用Linux的習慣來建立Java專案,以下是我的目錄架構以及分類


bin : 所產生的class目錄
lib : 使用到的外部jar
Makefile : Compiler Process
META-INF : MANIFEST.MF的目錄
out : 產出的jar檔
src : source code目錄,須使用java的目錄格式


  • Makefile
  • 要使用外部jar檔,有幾個需要注意的部分
    1. 如果你希望把外部的jar包進你的jar檔裡面,那要使用外部的jar檔,必須在自己的程式裡面撰寫動態load class。

    2. 外部import jar檔進來,也分成兩個方法(以下介紹此方法),
        2-1. 執行jar檔時,加入-cp .:lib/commons-io-2.4.jar (note: 有一個 .)。
        2-2. 寫入在MANIFEST.MF,當執行jar檔時,就會找MANIFEST.MF定義的位置。
    BIN = bin
    SRC = $(shell find src -name *.java)
    OUT = out
    LIBS = lib/commons-io-2.4.jar;lib/jtds-1.2.7.jar
    MANIFEST = META-INF/MANIFEST.MF
    TARGET = $(OUT)/test.jar

    all: build-class create-jar
    build-class:#compiler src/com/test.java,並放置bin下
        javac -sourcepath $(SRC) -classpath $(LIBS) -d bin $(MAIN_FILE)

    # Note : javac Options :
    # -sourcepath : .java檔的位置 # -classpath : 指定外部jar檔或class
    # -d : class放置的位置

    create-jar: # 封裝成jar檔
        jar cvfm $(TARGET) $(MANIFEST) -C $(BIN) .
        cp $(LIBS) $(OUT)

    # Note : jar Options :
    # c : 建立一個新的jar檔
    # v : 顯示包裝運作的過程.
    # f : 指定要放到jar檔的檔案
    # C : change dir

    clean:
        rm -rf $(BIN)/* $(OUT)/*



  • META-INF/MANIFEST.MF
  • Class-Path 指的是外部jar檔
    Manifest-Version: 1.0
    Sealed: true
    Main-Class: com.test
    Class-Path: lib/commons-io-2.4.jar


  • src/com/test.java

  • package com;
    import org.apache.commons.io.FileUtils;
    import java.io.File;
    import java.io.IOException;
    public class test {
        static public void main(String[] args) {
            File src = new File ( args[0] );
            File dst = new File ( args[1] );
            try {
                FileUtils.copyFile(src,dst);
            } catch ( IOException e ) {
                System.out.println("copy error");
            }
        }
    }


  • 以上都設定好後,就可以make

  • make
    #在output可以得到兩個檔案
    1. lib/commons-io-2.4.jar
    2. test.jar


  • 執行結果

  • cd output
    java -jar test.jar lib/commons-io-2.4.jar lib/tst

    #note : 如果在MANIFEST.MF沒有填寫Class-Path,則下另一個command
    java -cp lib/commons-io-2.4.jar -jar test.jar lib/commons-io-2.4.jar lib/tst

    2013年5月23日 星期四

    [Java] com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

    使用兩台主機,一台為MySQL Server,而另一台則是使用java撰寫的程式,要利用jdbc 連線到Mysql時,發生了com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure的問題,從網路查到的資料,發現這個訊息可能的問題有好幾種,不過主要原因都是因為MySQL為了安全性的部分,所做的一些策略,而所導致。

    由網路上得知:
    1. 只有本機才能使用root登入
    2. 若需要遠端連線,須開啟User遠端連線的權限

    方法:

  • 登入MySQL
  • #mysql -h localhost -u root -p #登入MySQL

  • 建立帳號
  • 語法 :
    create user '[username]'@'[remote_ip]' identified by '[password]';
    grant all on *.* to '[username]'@'[remote_ip]';

    [username] : 帳號
    [password] : 密碼
    [remote_ip] : 遠端連到MySQL的IP,若不指定則填"%"

    mysql>create user 'jesse'@'%' identified by '1234';
    mysql>grant all on *.* to 'jesse'@'%';

  • 修改Mysql config
  • 編輯 /etc/mysql/my.cnf,並註解兩個Option。

    #skip-networking
    #bind-address = 127.0.0.1

  • 測試可否連線
  • 使用另一台主機,使用mysq指令,確認是否可連線成功。

    #mysql -h 192.168.11.200 -u root -p #登入MySQL

    2013年5月9日 星期四

    [Java] Overloading vs. Overriding 傻傻分不清

    老是傻傻分不清楚的了個字Orz....,即使每次都了解完意思之後,但過幾個月後,還是傻傻分不清!!! 只好努力的想一個方法來記憶摟。
    • Overloading (多載)  --> over(超過) loading(負載)
    • Overriding    (覆載)  --> over(超過) riding(騎)
    簡單記憶:
  • Overloading,表示loding太多,需要增加更多人(方法)來處理

  • public class Person {
        public wear(Clothe clothe) {...} // 穿衣服
        public wear(Pant pant) {...} // 穿褲子
        public wear(Shoe shoe) {...} // 穿鞋子
    }

  • Overriding , riding有騎或覆蓋的意思,即表示覆蓋掉父親

  • public class Parent {
        public wear(Clothe clothe) {...} //父親穿的衣服
    }

    public class Child extends Parent {
        @override
        public wear(Cloth clothe) {...}//兒子穿的衣服
    }

    2013年4月8日 星期一

    [Java] java.lang.OutOfMemoryError: Java heap space

    最近在測試使用Tomcat傳送大型檔案時

    發生 java.lang.OutOfMemoryError: Java heap space

    從結果可得知,當使用java.net.HttpURLConnection的OutputStream

    會先所有的Data暫存到memory,然後再一次性的送出

    而這樣的設計方式,也造成當在傳送大檔時,會有memory不足的問題

    要解決這個問題,基本上就兩個方法,加大memory或不要一次全部存完再送

    幸運的是 java.net.HttpURLConnection 提供設定internal buffering的功能

    以下提供兩種方式解決此問題

    方法一:(設定setChunkedStreamingMode)
    ...
    import java.net.HttpURLConnection;
    ......
    URL url = new URL("http://192.168.11.11:9981");
    URLConnection conn = url.openConnection();
    HttpURLConnection httpConn = (HttpURLConnection)conn;
    httpConn.setChunkedStreamingMode(ChunkLen);
    ......

    方法二:(加大memoory)

    [Run As]->[Run Configurations...]->[Arguments]->[VM arguments]
    -Xms512m
    -Xmx1024m


    Referece:
    1. 此網站有更詳盡的解說HttpURLConnection ( http://www.mzone.cc/article/198.html )
    2. Why Developers Should Not Write Programs That Call 'sun' Packages

    2013年3月1日 星期五

    [Java] java.lang.ClassNotFoundException on Eclipse

    發生 java.lang.ClassNotFoundException 這個訊息,可由以下幾個步驟來解決。

    1. 確認此程式主要是做成 jar (即library),還是 Runnable jar (即執行檔)
    2. JAR file :
      a. [Project] -> [Export] -> [Java] -> [JAR file]


      b. 選擇自行定義MANIFEST.MF


      c. MANIFEST.MF
    Manifest-Version: 1.0
    Sealed: true
    Main-Class: com.Main
    Class-Path: lib/commons-io-2.4.jar lib/xxx.jar
    (記得最後一行空白)

    3. Runnable JAR file :
      a. [Project] -> [Export] -> [Java] -> [Runnable JAR file]

    2013年1月30日 星期三

    [Java] Config Parser

    1. Class Name
        java.util.Properties

    2. Description
    如果需要使用到Config Parser,可使用這個Class來完成。

    3. Example
    @network.cfg
    address=192.168.11.11
    network=255.255.255.0
    gateway=192.168.11.1

    @SourceCode
    package sample.properties;
    import java.io.*;
    import java.util.Properties;

    public class SampleProperties {

      private static Properties props;

      private static void loadConfig(String cfgPath) {
        props = new Properties();
        try {
          props.load(new FileInputStream(cfgPath));
        } catch (Exception e) {
          e.printStackTrace();
        }
      }

      private static String getProperty(String key) {
        return props.getProperty(key);
      }

      public static void main(String[] args) {
        loadConfig("network.cfg");
        String address = getProperty("address");
        String network = getProperty("network");
        String gateway = getProperty("gateway");
        System.out.println("address : " + address );
        System.out.println("network : " + network);
        System.out.println("gateway : " + gateway);

      }
    }

    4. Output
    address : 192.168.11.11
    network : 255.255.255.0
    gateway : 192.168.11.1

    2012年12月26日 星期三

    [Java] tomcat localhost-config is missing

    [Error Message] 利用Eclipse執行Tomcat時發生以下狀況


    [Solution]
    原因還不確定,不過只要照著以下步驟即可解決。

    Step1. Stop tomcat server
    Step2. Open Configuration
    [Eclipse Menu] -> [Window] -> [Show view] -> [Others] -> [Servers]
    Step3. Delete Configuration
    點選紅色框框的設定,右鍵可將tomcat刪除,然後再重新執行即可