黑馬程式設計師——Java基礎---IO流(字元流、位元組流、轉換流、流操作規律)
阿新 • • 發佈:2019-01-11
三、字元編碼
- 字元編碼通過轉換流來完成。
- 在兩個物件進行構造的時候,可以加入字符集(即編碼表),可傳入編碼表的有:
- 轉換流:InuputStreamReader和OutputStreamWriter。
- 列印流:PrintStream和PrintWriter,只有輸出流。
- 轉換流的編碼應用
- 可以將字元以指定編碼格式儲存。
- 可以對文字資料指定編碼格式來解讀。
- 指定編碼表的動作由建構函式完成。
- 編碼和解碼
- 編碼:字串變成位元組陣列
- 預設字符集:
- String ---> byte[] :str.getBytes()
- 指定字符集:
- String ---> byte[] :str.getBytes(charsetName)
- String ---> byte[] :str.getBytes(charsetName)
- 預設字符集:
- 解碼:位元組陣列變成字串
- 預設字符集:
- byte[] ---> String :new String(byte[])
- 指定字符集:
- byte[] ---> String :newString(byte[],charsetName)
- 預設字符集:
- 編碼:字串變成位元組陣列
- 對於編碼和解碼的字符集轉換注意事項
- 如果編碼失敗,解碼就沒意義了。
- 如果編碼成功,解碼出現的是亂碼,需要對亂碼通過再次編碼(用解錯碼的編碼表),然後再通過正確的編碼表解碼。針對於IOS8859-1是通用的。
- 如果用的是GBK編碼,UTF-8解碼,此時通過再次編碼後解碼的方式,就不能成功了,因為UTF-8也支援中文,在UTF-8解的時候,會將對應的位元組數改變,所以不會成功。
- 特別注意:對於中文的”聯通“,這兩個字比較特別,它的二進位制位正好是和在UTF-8中兩個位元組打頭的相同,所以在文字檔案中,如果單獨寫“聯通”或者和滿足UTF-8編碼格式的字元一起儲存時,記事本就會用UTF-8來進行解碼動作,這樣顯示的就會是亂碼。
/* 有五個學生,每個學生有3門課的成績, 從鍵盤輸入以上資料(包括姓名,三門課成績), 輸入的格式:如:zhagnsan,30,40,60計算出總成績, 並把學生的資訊和計算出的總分數高低順序存放在磁碟檔案"stud.txt"中。 1,描述學生物件。 2,定義一個可操作學生物件的工具類。 思想: 1,通過獲取鍵盤錄入一行資料,並將該行中的資訊取出封裝成學生物件。 2,因為學生有很多,那麼就需要儲存,使用到集合。因為要對學生的總分排序。所以可以使用TreeSet。 3,將集合的資訊寫入到一個檔案中。 */ import java.io.*; import java.util.*; //學生類 class Student implements Comparable<Student> { private String name; private int ma,cn,en; private int sum; Student(String name,int ma,int cn,int en) { this.name = name; this.ma = ma; this.cn = cn; this.en = en; sum = ma + cn + en; } //複寫compareTo方法,按分數排序 public int compareTo(Student s) { int num = new Integer(this.sum).compareTo(new Integer(s.sum)); if(num==0) return this.name.compareTo(s.name); return num; } public String getName() { return name; } public int getSum() { return sum; } //複寫hashCode public int hashCode() { return name.hashCode()+sum*78; } //複寫equals,判斷姓名和總成績是否相同 public boolean equals(Object obj) { if(!(obj instanceof Student)) throw new ClassCastException("型別不匹配"); Student s = (Student)obj; return this.name.equals(s.name) && this.sum==s.sum; } //複寫toString方法,返回學生資訊。 public String toString() { return "student["+name+", "+ma+", "+cn+", "+en+"]"; } } //學生工具類 class StudentInfoTool { //從鍵盤讀取學生資訊方法,以學生自身排序方式存入集合中 public static Set<Student> getStudents()throws IOException { return getStudents(null); } //從鍵盤讀取學生資訊方法,以比較器排序方式存入集合中 public static Set<Student> getStudents(Comparator<Student> cmp)throws IOException { //獲取鍵盤錄入 BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); String line = null; //定義一個集合,用來儲存學生物件 Set<Student> stus = null; if(cmp==null) stus = new TreeSet<Student>(); else stus = new TreeSet<Student>(cmp); //讀取資料 while((line=bufr.readLine())!=null) { if("over".equals(line)) break; String[] info = line.split(","); //將學生物件存入集合中 Student stu = new Student(info[0],Integer.parseInt(info[1]), Integer.parseInt(info[2]), Integer.parseInt(info[3])); stus.add(stu); } //關閉流 bufr.close(); return stus; } //把學生資訊按照指定屬性寫入指定檔案中 public static void write2File(Set<Student> stus)throws IOException { //關聯檔案 BufferedWriter bufw = new BufferedWriter(new FileWriter("stuinfo.txt")); //遍歷集合,將學生資訊寫入到指定檔案 for(Student stu : stus) { bufw.write(stu.toString()+"\t"); bufw.write(stu.getSum()+""); bufw.newLine(); bufw.flush(); } bufw.close(); } } class StudentInfoTest { public static void main(String[] args) throws IOException { //定義一個反轉自身比較性的比較器 Comparator<Student> cmp = Collections.reverseOrder(); //呼叫學生工具類的獲取資訊方法,將資訊存入集合中 Set<Student> stus = StudentInfoTool.getStudents(cmp); //將學生資訊寫入指定檔案中 StudentInfoTool.write2File(stus); } }