InputStreamReader in = new InputStreamReader(new FileInputStream(“demo.txt”),”UTF-8”);
目前成都創(chuàng)新互聯(lián)已為上千多家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)頁空間、網(wǎng)站托管維護(hù)、企業(yè)網(wǎng)站設(shè)計(jì)、河?xùn)|網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
給InputStreamReader指定解碼編碼,這樣二者統(tǒng)一就不會(huì)出現(xiàn)亂碼了。
下面說說字符輸出流。
字符輸出流的原理和字符輸入流的原理一樣,也可以看做是包裝流,其底層還是采用字節(jié)輸出流來寫文件。只是字符輸出流根據(jù)指定的編碼將字符轉(zhuǎn)換為字節(jié)的。字符輸出流的主要類是:OutputStreamWriter。Java api解釋如下:OutputStreamWriter 是字符流通向字節(jié)流的橋梁:使用指定的 charset 將要向其寫入的字符編碼為字節(jié)。它使用的字符集可以由名稱指定或顯式給定,否則可能接受平臺(tái)默認(rèn)的字符集。說的很明白了,它需要一個(gè)編碼將寫入的字符轉(zhuǎn)換為字節(jié),如果沒有指定則采用GBK編碼,那么輸出的字節(jié)都將是GBK編碼,生成的文件也是GBK編碼的。如果采用以下方式構(gòu)造OutputStreamWriter:
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(“dd.txt”),”UTF-8”);
那么寫入的字符將被編碼為UTF-8的字節(jié),生成的文件也將是UTF-8格式的。
問題二: 既然讀文件要使用和文件編碼一致的編碼,那么javac編譯文件也需要讀取文件,它使用什么編碼呢?
這個(gè)問題從來就沒想過,也從沒當(dāng)做是什么問題。正是因?yàn)閱栴}一而引發(fā)的思考,其實(shí)這里還是有東西可以挖掘的。下面分三種情況來探討,這三種情況也是我們常用的編譯java源文件的方法。
1.javac在控制臺(tái)編譯java類文件。
通常我們手動(dòng)建立一個(gè)java文件Demo.java,并保存。此時(shí)Demo.java文件的編碼為ANSI,中文操作系統(tǒng)下就是GBK.然后使用javac命令來編譯該源文件?!眏avac Demo.java”。Javac也需要讀取java文件,那么javac是使用什么編碼來解碼我們讀取的字節(jié)呢?其實(shí)javac采用了操作系統(tǒng)默認(rèn)的GBK編碼解碼我們讀取的字節(jié),這個(gè)編碼正好也是Demo.java文件的編碼,二者一致,所以不會(huì)出現(xiàn)亂碼情況。讓我們來做點(diǎn)手腳,在保存Demo.java文件時(shí),我們選擇UTF-8保存。此時(shí)Demo.java文件編碼就是UTF-8了。我們?cè)偈褂谩眏avac Demo.java”來編譯,如果Demo.java里含有中文字符,此時(shí)控制臺(tái)會(huì)出現(xiàn)警告信息,也出現(xiàn)了亂碼。究其原因,就是因?yàn)閖avac采用了GBK編碼解碼我們讀取的字節(jié)。因?yàn)槲覀兊淖止?jié)是UTF-8編碼的,所以會(huì)出現(xiàn)亂碼。如果不信的話你可以自己試試。那么解決辦法呢?解決辦法就是使用javac的encoding參數(shù)來制定我們的解碼編碼。如下:javac -encoding UTF-8 Demo.java。這里我們指定了使用UTF-8來解碼讀取的字節(jié),由于這個(gè)編碼和Demo.java文件編碼一致,所以不會(huì)出現(xiàn)亂碼情況了。
2.Eclipse中編譯java文件。
我習(xí)慣把Eclipse的編碼設(shè)置成UTF-8。那么每個(gè)項(xiàng)目中的java源文件的編碼就是UTF-8。這樣編譯也從沒有問題,也沒有出現(xiàn)過亂碼。正是因?yàn)檫@樣才掩蓋了使用javac可能出現(xiàn)的亂碼。那么Eclipse是如何正確編譯文件編碼為UTF-8的java源文件的呢?唯一的解釋就是Eclipse自動(dòng)識(shí)別了我們java源文件的文件編碼,然后采取了正確的encoding參數(shù)來編譯我們的java源文件。功勞都?xì)w功于IDE的強(qiáng)大了。
3.使用Ant來編譯java文件。
Ant也是我常用的編譯java文件的工具。首先,必須知道Ant在后臺(tái)其實(shí)也是采用javac來編譯java源文件的,那么可想而知,1會(huì)出現(xiàn)的問題在Ant中也會(huì)存在。如果我們使用Ant來編譯UTF-8編碼的java源文件,并且不指定如何編碼,那么也會(huì)出現(xiàn)亂碼的情況。所以Ant的編譯命令有一個(gè)屬性” encoding”允許我們指定編碼,如果我們要編譯源文件編碼為UTF-8的java文件,那么我們的命令應(yīng)該如下:
指定了編碼也就相當(dāng)于”javac –encoding”了,所以不會(huì)出現(xiàn)亂碼了。
你是想通過java代碼獲取還是常規(guī)僅僅想知道一個(gè)java源文件的編碼格式?
如果只是想知道java源文件的編碼格式的話用記事本打開源文件,然后 文件-另存為 里面有個(gè)編碼格式,默認(rèn)就是當(dāng)前文件的編碼格式。
如下:
//我寫了一個(gè)程序,你把文字復(fù)制到文本框中點(diǎn)轉(zhuǎn)碼按鈕,就可以了
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
public class Class1 extends JFrame {
private final class AT implements ActionListener {
public void actionPerformed(ActionEvent e) {
jta.setText(fixString(jta.getText()));
}
}
public static void main(String[] args) {
JFrame jf = new Class1();
}
JTextArea jta = new JTextArea();
public Class1() {
setSize(400, 400);
setDefaultCloseOperation(EXIT_ON_CLOSE);
JButton jb = new JButton("轉(zhuǎn)碼");
jb.addActionListener(new AT());
add(jta);
add("North", jb);
setVisible(true);
}
String fixString(String s) {
while (true) {
int index = s.indexOf("\\u");
if (index != -1) {
String s1 = s.substring(index, index + 6);
if (s1.matches("\\\\u[0-9A-F]{4}")) {
char c = (char) Integer.parseInt(s1.replace("\\u", ""), 16);
s = s.substring(0, index) + c + s.substring(index + 6);
}
} else {
break;
}
}
return s;
}
}
java中編碼:URLEncoder.encode(strUri,"utf-8");
java中解碼碼:URLDecoder.decode(strUri,"utf-8");
java編碼和解碼 ? ? ? ?
流讀取文件,具有轉(zhuǎn)換編碼功能的有:OutputStreamWriter和InputStreamReader,
構(gòu)造器有如:
InputStreamReader(InputStream in, String charsetName)
創(chuàng)建使用指定字符集的 InputStreamReader。
OutputStreamWriter(OutputStream out, String charsetName)
創(chuàng)建使用指定字符集的 OutputStreamWriter。
處理字符串編碼問題:
重新對(duì)獲取的字符串進(jìn)行編碼:Byte[] bytes = str.getBytes(String encodeCharsetNam);
重新對(duì)bytes進(jìn)行解碼,創(chuàng)建新的字符串對(duì)象:str = new String(Byte[] bytes,String decodeCharsetName);
一般結(jié)合使用:str = new String(str.getBytes(String encodeCharsetName),String decodeCharsetName);
例如:resultName=new String(username.getBytes("ISO-8859-1"),"UTF-8");
還可以加入判斷:
if(!Charset.forName("gbk").newEncoder().canEncode(str)){str = new Strin(str.getBytes("ISO-8859-1"),"UTF-8");}else{str = new String(str.getBytes("ISO-8859-1"),"gbk");}
處理請(qǐng)求參數(shù)傳遞編碼問題:
java中編碼:URLEncoder.encode(strUri,"utf-8");
java中解碼碼:URLDecoder.decode(strUri,"utf-8");
js中編碼:encodeURIComponent(strUri);encodeURI(strUri);escape(str);
js中解碼:decodeURIComponent(strUri);decodeURI(strUri);unescape(str);
補(bǔ)充概念:
URI組件:主機(jī)、端口、路徑、查詢參數(shù)、片段等。
URI組件分隔符::/?#[]@,冒號(hào)用于分隔協(xié)議和主機(jī),/用于分隔主機(jī)和 路徑,?用于分隔路徑和查詢參數(shù),用于分隔多個(gè)查詢參數(shù)等。
URI中的不安全字符或保留字符: ! * ‘ ( ) ; : @ = + $ , / ? # [ ] 他們具有特殊作用,例如上面的分隔作用。
URI允許出現(xiàn)的字符:只允許包含英文字母(a-zA-Z)、數(shù)字(0-9)、-_.~4個(gè)特殊字符以及所有保留字符,其他字符均需要經(jīng)過編碼之后才能出現(xiàn)在Url中,比如使用保留字符的原意,而不是特殊作用。
js向java/jsp的編碼與解碼:
js中編碼:encodeURI(encodeURI(strUri));decodeURIComponent(decodeURIComponent(strUri));
java/jsp中解碼: java.net.URLDecoder.decode(strUri,"UTF-8");
js中編碼兩次的問題:如果使用一次編碼,在瀏覽器地址欄里,瀏覽器認(rèn)為%是個(gè)轉(zhuǎn)義字符,瀏覽器會(huì)把%與%之間的編碼值,兩位兩位取出后進(jìn)行解碼。
然后再傳遞給處理頁面,然后由處理頁面進(jìn)行再次解碼,這樣前面就缺少了一次編碼過程,所以前面需要連續(xù)兩次編碼。