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

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

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

    posts - 262,  comments - 221,  trackbacks - 0
    package example.encoding;

    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.io.UnsupportedEncodingException;
    import java.io.Writer;
    import java.nio.charset.Charset;
    import java.util.Iterator;
    import java.util.Set;
    import java.util.SortedMap;

    /**
     * <pre>
     * The Class IOEncodeTest is a tester class for java encoding. Mainnaly contains
     * two parts:
     *  1.Test written by FileWriter, with or without given character encoding value
     *  2.Test written by OutputStreamWriter, with or without given character encoding value
     * </pre>
     * 
     * 
    @author Paul Lin
     * 
    @version 1.0
     
    */

    public class OutputEncodingTest {

        
    private static String word = "Hello world! 中國";

        
    private static final String ENCODING_EN = "ISO-8859-1";

        
    private static final String ENCODING_CN = "GB2312";

        
    private static final String ENCODING_UTF = "UTF-8";

        
    private static final String DEFAULT_SYSTEM_ENCODING = System
                .getProperty(
    "file.encoding");

        
    /**
         * The main method.
         * 
         * 
    @param args the arguments
         
    */

        
    public static void main(String args[]) {
            OutputEncodingTest tester 
    = new OutputEncodingTest();
            tester.testFileWriter();
            tester.testOutputStreamWriter();
        }


        
    /**
         * Test file writer.
         
    */

        
    public void testFileWriter() {
            
    // Create test result folder
            String resultFolder = createResultFolder(System
                    .getProperty(
    "user.language"), getBasePath());
            
    // With default platform encoding
            writeByFileWriter(word, resultFolder);
            
    // With given system file.encoding property
            writeByFileWriter(word, ENCODING_EN, resultFolder);
            writeByFileWriter(word, ENCODING_CN, resultFolder);
            writeByFileWriter(word, ENCODING_UTF, resultFolder);
        }


        
    /**
         * Test output stream writer.
         
    */

        
    public void testOutputStreamWriter() {
            
    // Create test result folder
            String resultFolder = createResultFolder(System
                    .getProperty(
    "user.language"), getBasePath());
            
    // With default platform encoding
            writeByOutputStreamWriter(word, resultFolder);
            
    // With given system file.encoding property
            writeByOutputStreamWriter(word, ENCODING_EN, resultFolder);
            writeByOutputStreamWriter(word, ENCODING_CN, resultFolder);
            writeByOutputStreamWriter(word, ENCODING_UTF, resultFolder);
        }


        
    /**
         * Prints the available charset.
         
    */

        
    public void printAvailableCharset() {
            SortedMap
    <String, Charset> charsets = Charset.availableCharsets();
            Set
    <String> charsetKeys = charsets.keySet();
            System.out.println(
    "\n<<<< Canonical name -- Display name -- "
                    
    + " Can encode >>>>\n");

            Iterator
    <String> i = charsetKeys.iterator();
            
    while (i.hasNext()) {
                String key 
    = (String) i.next();
                Charset charset 
    = (Charset) charsets.get(key);
                String displayName 
    = charset.displayName();
                
    boolean canEncode = charset.canEncode();
                System.out.println(key 
    + " - " + displayName + " - " + canEncode);
            }

        }


        
    /**
         * Write by file writer.
         * 
         * 
    @param content the content
         
    */

        
    private void writeByFileWriter(String content, String destination) {
            String defaultEncoding 
    = System.getProperty("file.encoding");
            System.out.println(
    "Using default system encoding: " + defaultEncoding);
            writeByFileWriter(content, defaultEncoding, destination);
        }


        
    /**
         * Write by file writer.
         * 
         * 
    @param content the content
         * 
    @param encoding the encoding
         
    */

        
    private void writeByFileWriter(String content, String encoding,
                String destination) 
    {
            printDebugInformation(
    "FileWriter", encoding, content);

            
    // Get system default encoding
            String defaultEncoding = System.getProperty("file.encoding");

            
    // Reset underlying platform character encoding
            if (!defaultEncoding.equalsIgnoreCase(encoding)) {
                System.setProperty(
    "file.encoding", encoding);
            }


            
    // Save as file with given encoding value
            String file = returnFileName(destination, "write_by_filewriter_",
                    encoding, 
    ".txt");
            
    try {
                Writer writer 
    = new BufferedWriter(new FileWriter(file));
                writer.write(content);
                writer.flush();
                writer.close();
            }
     catch (IOException ioe) {
                ioe.printStackTrace();
            }


            
    // Reset character encoding to system default value
            resetDefaultSystemEncoding();
        }


        
    /**
         * Write by output stream writer.
         * 
         * 
    @param content the content
         
    */

        
    private void writeByOutputStreamWriter(String content, String destination) {
            String defaultEncoding 
    = System.getProperty("file.encoding");
            System.out.println(
    "Using default system encoding: " + defaultEncoding);
            writeByOutputStreamWriter(content, defaultEncoding, destination);
        }


        
    /**
         * Write by output stream writer.
         * 
         * 
    @param content the content
         * 
    @param encoding the encoding
         
    */

        
    private void writeByOutputStreamWriter(String content, String encoding,
                String destination) 
    {
            printDebugInformation(
    "OutputStreamWriter", encoding, content);

            
    // Save as file with given encoding value
            String file = returnFileName(destination,
                    
    "write_by_outputStreamWriter_", encoding, ".txt");
            
    try {
                Writer writer 
    = new PrintWriter(
                        
    new BufferedWriter(new OutputStreamWriter(
                                
    new FileOutputStream(file), encoding)));
                writer.write(content);
                writer.flush();
                writer.close();
            }
     catch (FileNotFoundException fnfe) {
                fnfe.printStackTrace();
            }
     catch (UnsupportedEncodingException uee) {
                uee.printStackTrace();
            }
     catch (IOException ioe) {
                ioe.printStackTrace();
            }


            
    // Reset character encoding to system default value
            resetDefaultSystemEncoding();
        }


        
    /**
         * Gets the base path.
         * 
         * 
    @return the base path
         
    */

        
    private String getBasePath() {
            StringBuffer finalPath 
    = new StringBuffer();
            String dir 
    = System.getProperty("user.dir");

            finalPath.append(dir);
            finalPath.append((dir.endsWith(
    "\\"|| dir.endsWith("/")) ? "" : "/");
            finalPath.append(
    "src").append("/");
            finalPath.append(
    "example").append("/");
            finalPath.append(
    "encoding").append("/");
            
    return finalPath.toString();
        }


        
    /**
         * Return file name.
         * 
         * 
    @param basePath the base path
         * 
    @param prefix the prefix
         * 
    @param content the content
         * 
    @param subfix the subfix
         * 
         * 
    @return the string
         
    */

        
    private String returnFileName(String basePath, String prefix,
                String content, String subfix) 
    {
            StringBuffer name 
    = new StringBuffer(basePath);
            
    if ((!basePath.endsWith("\\"&& (!basePath.endsWith("/")))) {
                name.append(
    "/");
            }

            name.append(prefix);
            name.append(content);
            name.append(subfix);
            
    return name.toString();
        }


        
    /**
         * Creates the result folder.
         * 
         * 
    @param platform the platform
         * 
    @param fullPath the full path
         * 
         * 
    @return the string
         
    */

        
    private String createResultFolder(String platform, String fullPath) {
            StringBuffer resultFolder 
    = new StringBuffer();

            
    if (fullPath.endsWith("\\"|| fullPath.endsWith("/")) {
                resultFolder.append(fullPath);
            }
     else {
                resultFolder.append(fullPath).append(
    "/");
            }

            resultFolder.append(
    "Test_Result_Of_").append(platform);

            File file 
    = new File(resultFolder.toString());
            
    if (!file.exists()) {
                file 
    = new File(resultFolder.toString());
                file.mkdir();
                
    return resultFolder.toString();
            }
     else {
                
    return file.getAbsolutePath();
            }

        }


        
    /**
         * Prints the debug information.
         * 
         * 
    @param writerName the writer name
         * 
    @param encoding the encoding
         
    */

        
    private void printDebugInformation(String writerName, String encoding,
                String content) 
    {
            StringBuffer msg 
    = new StringBuffer();
            msg.append(
    "\n<<<<----------------------------------");
            msg.append(
    " Test written by ").append(writerName);
            msg.append(
    " with encoding ").append(encoding);
            msg.append(
    " ---------------------------------->>>>\n");
            msg.append(
    " \nOriginal string: ").append(content).append("\n");
            System.out.println(msg.toString());
        }


        
    /**
         * Reset default system encoding.
         
    */

        
    private void resetDefaultSystemEncoding() {
            System.setProperty(
    "file.encoding", DEFAULT_SYSTEM_ENCODING);
        }

    }

    【1】中文平臺情況下,測試結果如下:


     1.如果采用FileWriter,并指定GBK編碼:編碼后字符長度為15,可以正常保存和讀取
     2.如果采用FileWriter,并指定UTF-8編碼:編碼后字節長度為16,可以正常保存和讀取
     3.如果采用FileWriter,并指定ISO8859-1編碼:編碼后字節長度為17,可以正常保存和讀取
     
     4.如果采用OutputStreamWriter,并指定GBK編碼:編碼后字符長度為15,可以正常保存和讀取
     5.如果采用OutputStreamWriter,并指定UTF-8編碼:編碼后字節長度為16,可以正常保存和讀取
     6.如果采用OutputStreamWriter,并指定ISO-8859-1編碼:編碼后字節長度為17,變成?

    【2】英文平臺情況下,測試結果如下:

     1.如果采用FileWriter,并指定GBK編碼:編碼后字符長度為15,變成?
     2.如果采用FileWriter,并指定UTF-8編碼:編碼后字節長度為16,變成?
     3.如果采用FileWriter,并指定ISO-8859-1編碼:編碼后字節長度為17,變成?
     
     4.如果采用OutputStreamWriter,并指定GBK編碼:編碼后字符長度為15,可以正常保存和讀取
     5.如果采用OutputStreamWriter,并指定UTF-8編碼:編碼后字節長度為16,可以正常保存和讀取
     6.如果采用OutputStreamWriter,并指定ISO-8859-1編碼:編碼后字節長度為17,變成?

    【結論】

    ①在中文平臺下,如果使用FileWriter,不論你如何設置字符集都不會起作用。因為它采用的是默認的系統字符集。即便你設置了System.setProperty("file.encoding", "ISO-8859-1"),或者在運行時給予參數-Dfile.encoding=UTF-8都不會起作用。你會發現它最終還是都已"GB2312"或者"GBK"的方式保存。
      
    在中文平臺下,如果使用OutputStreamWriter,則在后臺寫入時會把字符流轉換成字節流,此時指定的編碼字符集就起作用了。可以看到在指定GBK、UTF-8的情況下中文可以正常的保存和讀取,同時文件按照我們給定的方式保存了。而對于ISO-8859-1則變成了?,這再次證明了采用ISO-8859-1是不能保存中文的,而且會因為中文編碼在ISO-8859-1的編碼中找不到對應的字符而默認轉換成?。
     
    ②在英文平臺下,如果使用FileWriter,不論你如何設置字符集同樣都不會起作用。所有的文件都將按照ISO-8859-1的編碼方式保存,毫無疑問地變成了?。在英文平臺下,如果使用OutputStreamWriter,則只有當我們把字符和文件的編碼方式正確設置為GBK、UTF-8的情況下,中文才能正確的保存并顯示。

    ③通過上述的實驗證明,為了確保在不同的平臺下,客戶端輸入的中文可以被正確地解析、保存、讀取。最好的辦法就是使用OutputStreamWriter配合UTF-8編碼。
      
    如果不想使用UTF-8編碼,那么可以考慮使用GB2312,不建議使用GBK、GB18030。因為對于某些老式的文本編輯器,甚至不支持GBK、GB18030的編碼,但是對于GB2312則是一定支持的。因為前兩者都不是國標但后者是。

    ④關于String的getBytes(),getBytes(encoding)和new String(bytes, encoding)這三個方法,非常值得注意:
      
      A.getBytes():使用平臺默認的編碼方式(通過file.encoding屬性獲取)方式來將字符串轉換成byte[]。得到的是字符串最原始的字節編碼值。
      
      B.getBytes(NAME_OF_CHARSET):使用指定的編碼方式將字符串轉換成byte[],如果想要得到正確的字節數組,程序員必須給出正確的NAME_OF_CHARSET。否則得到的就不會得到正確的結果。
       
      C.new String(bytes, encoding):如果我們在客戶端使用UTF-8編碼的JSP頁面發出請求,瀏覽器編碼后的UTF-8字節會以ISO-8859-1的形式傳遞到服務器端。所以要得到經HTTP協議傳輸的原始字節,我們需要先調用getBytes("ISO-8859-1")得到原始的字節,但由于我們客戶端的原始編碼是UTF-8,如果繼續按照ISO-8859-1解碼,那么得到的將不是一個中文字符,而是3個亂碼的字符。所以我們需要再次調用new String(bytes,"UTF-8"),將字節數組按照UTF-8的格式,每3個一組進行解碼,才能還原為客戶端的原始字符。

      D.String的getBytes()、getBytes(NAME_OF_CHARSET)方法都是比較微妙的方法,原則上:傳輸時采用的是什么編碼,我們就需要按照這種編碼得到字節。new String(bytes, NAME_OF_CHARSET)則更加需要小心,原則上:客戶端采用的是什么編碼,那么這里的NAME_OF_CHARSET就必須和客戶端保持一致。
        
       例如JSP頁面是GBK,那么我們接收頁面傳遞而來的參數時就必須使用new String(parameter.getBytes("ISO-8859-1"), "GBK");如果使用了錯誤的解碼方式,如使用了UTF-8,那么得到的很有可能就是亂碼了。
        
       也就是說:GBK--->ISO-8859-1--->GBK、UTF-8--->ISO-8859-1--->UTF-8的轉換過程是沒有問題的。但是GBK--->ISO-8859-1--->UTF-8、UTF-8--->ISO-8859-1--->GBK的字節直接轉碼則可能導致亂碼,需要另外的轉換過程。
     
    記住:

    謹慎地使用getBytes(NAME_OF_CHARSET)和new String(bytes, NAME_OF_CHARSET),除非你很清楚的知道原始的字符編碼和傳輸協議使用的編碼。

    推薦使用基于服務器的配置、過濾器設置request/response的characterEncoding、content type屬性。還有就是JSP頁面的pageEncoding屬性、HTML meta元素的content type屬性。盡量避免頻繁的在代碼中進行字符串轉碼,即降低了效率又增加了風險



    -------------------------------------------------------------
    生活就像打牌,不是要抓一手好牌,而是要盡力打好一手爛牌。
    posted on 2010-02-22 17:39 Paul Lin 閱讀(3042) 評論(4)  編輯  收藏 所屬分類: J2SE


    FeedBack:
    # re: 【Java基礎專題】編碼與亂碼(04)---輸出時的編碼與亂碼
    2010-05-13 18:16 | 風中搖曳
    聽君一席話,勝過搜索無數次,謝謝你的分享,真的  回復  更多評論
      
    # re: 【Java基礎專題】編碼與亂碼(04)---輸出時的編碼與亂碼[未登錄]
    2011-05-28 11:06 | ZOE
    可以轉載么?  回復  更多評論
      
    # re: 【Java基礎專題】編碼與亂碼(04)---輸出時的編碼與亂碼[未登錄]
    2011-05-29 00:00 | Paul Lin
    @ZOE

    可以,歡迎轉載。只要保留原始出處就可以了  回復  更多評論
      
    # re: 【Java基礎專題】編碼與亂碼(04)---輸出時的編碼與亂碼
    2012-12-12 17:55 | 砂銀
    學到了不少  回復  更多評論
      
    <2010年2月>
    31123456
    78910111213
    14151617181920
    21222324252627
    28123456
    78910111213

    常用鏈接

    留言簿(21)

    隨筆分類

    隨筆檔案

    BlogJava熱點博客

    好友博客

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲三级高清免费| 亚洲精品免费观看| 西西大胆无码视频免费| 爱丫爱丫影院在线观看免费| 老司机免费午夜精品视频| 亚洲乱码无限2021芒果| 亚洲国产精品久久久久久| 亚洲日韩国产成网在线观看| 毛片免费观看的视频| 亚欧免费视频一区二区三区| 中文字幕av无码不卡免费 | 最近中文字幕无吗高清免费视频| 久久精品电影免费动漫| 精精国产www视频在线观看免费| 国产成人综合久久精品亚洲| 亚洲综合偷自成人网第页色| 亚洲美女视频免费| 亚洲欧洲在线观看| 久久国产精品亚洲综合| 亚洲人成精品久久久久| 亚洲日韩中文无码久久| 国产亚洲精品激情都市| 亚洲日本一区二区一本一道| 亚洲精品国产精品国自产观看| 精品国产麻豆免费网站| 免费高清av一区二区三区| 67194成是人免费无码| 毛片免费视频播放| 日韩精品成人无码专区免费| 91在线品视觉盛宴免费| 亚洲成在人线aⅴ免费毛片| 欧美在线看片A免费观看| 午夜宅男在线永久免费观看网| 99久久99这里只有免费费精品| 2021免费日韩视频网| 免费影院未满十八勿进网站| 中文字幕人成无码免费视频| 妞干网免费观看视频| 国产18禁黄网站免费观看| 亚洲AV网站在线观看| 亚洲中文久久精品无码ww16|