1. 程式人生 > >Java中以字元流形式操作檔案中的編碼問題

Java中以字元流形式操作檔案中的編碼問題

參考《編碼解碼模型和實現》,以字元流形式操作檔案的時候,一定要指定正確的編碼方案,否則會出現亂碼等問題。

以字元流形式操作檔案包括兩種情形:以字元流的形式讀取檔案內容,將字元流寫入檔案中。

一、以字元流的形式讀取檔案內容
現在有一個檔案a.txt,檔案內容為“你好,Java程式”,採用UTF-8編碼。接下來做2個實驗。

1、實驗1

實驗程式碼:

package com.dslztx;


import java.io.*;
import java.nio.charset.Charset;


public class Encoding {
    public static void main(String[] args) throws IOException {
        BufferedReader reader =
                new BufferedReader(new InputStreamReader(new FileInputStream("a.txt"), Charset.forName("utf-8")));
        String line;
        while ((line = reader.readLine()) != null)
            System.out.println(line);
    }
}

實驗結果:


2、實驗2

實驗程式碼:

package com.dslztx;


import java.io.*;
import java.nio.charset.Charset;


public class Encoding {
    public static void main(String[] args) throws IOException {
        BufferedReader reader =
                new BufferedReader(new InputStreamReader(new FileInputStream("a.txt"), Charset.forName("gbk")));
        String line;
        while ((line = reader.readLine()) != null)
            System.out.println(line);
    }
}

實驗結果:


現在有一個檔案b.txt,檔案內容如下,採用UTF-8編碼。接下來做2個實驗。

你好
你好這是第一行
#Footer
Java程式
你好這是第二行

3、實驗3

實驗程式碼:
package com.dslztx;


import java.io.*;
import java.nio.charset.Charset;
import java.util.Scanner;


public class Encoding {
    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(new File("b.txt"), "utf-8");
        scanner.useDelimiter("\\r\\n#Footer\\r\\n");
        while (scanner.hasNext())
            System.out.println(scanner.next());
    }
}

實驗結果:


4、實驗4

實驗程式碼:
package com.dslztx;


import java.io.*;
import java.nio.charset.Charset;
import java.util.Scanner;


public class Encoding {
    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(new File("b.txt"), "gbk");
        scanner.useDelimiter("\\r\\n#Footer\\r\\n");
        while (scanner.hasNext())
            System.out.println(scanner.next());
    }
}

實驗結果:


分析:

由於亂碼,導致scanner.hasNext()返回值為false

二、將字元流寫入檔案中
將字元流寫入檔案中,做2個實驗。
1、實驗1
實驗程式碼:
package com.dslztx;


import java.io.*;
import java.nio.charset.Charset;
import java.util.Scanner;


public class Encoding {
    public static void main(String[] args) throws IOException {
        BufferedWriter writer =
                new BufferedWriter(new OutputStreamWriter(new FileOutputStream("c.txt"), Charset.forName("utf-8")));
        writer.write("你好,Java程式");
        writer.close();
    }
}
實驗結果:

檢視c.txt檔案的位元組流如下圖所示


2、實驗2

實驗程式碼:
package com.dslztx;


import java.io.*;
import java.nio.charset.Charset;
import java.util.Scanner;


public class Encoding {
    public static void main(String[] args) throws IOException {
        BufferedWriter writer =
                new BufferedWriter(new OutputStreamWriter(new FileOutputStream("c.txt"), Charset.forName("gbk")));
        writer.write("你好,Java程式");
        writer.close();
    }
}
實驗結果:

當沒有明確指定需要使用的字元編碼方案時,Java程式通過“java.nio.charset.Charset.defaultCharset().name()”語句來獲取預設的字元編碼方案,該語句返回的值跟執行Java程式的作業系統的設定有關,在有些作業系統上,該語句返回值可能是UTF-8;在有些作業系統上,該語句返回值可能是GBK;在有些作業系統上,該語句返回值可能是除了UTF-8和GBK以外的其他字元編碼方案。這樣子,程式的可移植性大大降低。