---------- android培訓、java培訓、期待與您交流! ----------
一、File類
(一)概述
1、File類:文件和目錄路徑名的抽象表現形式
2、作用:
(1)用來將文件或文件夾封裝成對象
(2)方便于對“文件”與“文件夾屬性信息”進行操作
(3)File對象,可以作為參數傳遞給流的構造函數
(二)構造方法
* 通過File的構造函數創建File對象
方式1:File f = new File("c://a.txt");
方式2:File f2 = newFile("c://abc","a.txt");
方式3:File dir = new File("c://abc"); File f3 = new File(dir , "a.txt");
(三)字段屬性
File f4 = new File(“c:” + File.separator + “abc” + File.separator + “a.txt”);
(四)File類常見方法:
1、獲取
String getName():獲取文件名
String getPath():獲取文件的相對路徑
String getParent():獲取文件父目錄
String getAbsolutePath():獲取文件的絕對路徑
long lastModified():返回文件最后一次被修改的時間
long length():返回文件長度
2、創建和刪除
(1)創建文件
File file = new File(“c://a.txt”);
File.createNewFile();//返回boolean值,和輸出流不同,如果文件存在,則不創建。如果文件不存在,則創建。
file.delete():返回boolean值。
(2)創建文件夾
File dir = new File(“abc”);
boolean b = dir.mkdir();//創建單級目錄
boolean bs = dir.mkdirs();//創建多級目錄
boolean d = dir.delete();//刪除空文件夾
3、判斷
File f = new File(“a.txt”);
(1) boolean b = f.exists();//判斷是否存在
(2) boolean f.isFile();//判斷是否是文件
(3) boolean f.isDirectory();//判斷是否是目錄
(4) boolean isHidden();//是否是隱藏文件
4、重命名
(1)boolean renameTo(File dest);
(2)用法:
File f1 = new File(“1.mp3”);
File f2 = new File(“d://2.mp3”);
F1.renameTo(f2);
5、系統根目錄和容量獲取
(1)系統根目錄:File[] files = File.listRoots();//listRoots是靜態方法。
(2)容量獲取:
file.getFreeSpace();
file.getTotalSpace();
file.getUsableSpace();
6、獲取目錄內容
File file = new File(“c://”);
(1)String[] names = file.list();
注:調用list方法的File對象中封裝的必須是目錄,否則出現空指針異常。如果訪問的是“系統級”目錄,也會發生空指針異常。如果目錄存在但是沒有內容,返回長度為零的數組。
(2)File[] files = file.listFiles();//返回一個抽象路徑名數組,獲取當前文件夾下的所有文件和文件夾
7、過濾器
(1)String[] list(FilenameFilter filter);//返回一個字符串數組,獲取目錄中滿足指定過濾器的文件或目錄。
(2)File[] ListFiles(FilenameFilter filter); 或File[] ListFiles(FileFilter filter); //返回抽象路徑名數組,獲取目錄中滿足指定過濾器的文件或目錄。
注: FilenameFilter是一個接口,它有一個accept(File dir , String name) 方法,返回值是boolean型,測試指定文件是否應該包含在某一文件列表中。。
FileFilter是一個接口,它有一個accept(File pathname)方法,返回值是boolean型,測試指定抽象路徑名是否應該包含在某個路徑名列表中。
(五)應用練習
1、深度遍歷文件夾。
1 /* 2 3 * 需求:深度遍歷,對指定目錄進行所有內容的列出(包含子目錄中的內容) 4 5 */ 6 7 import java.io.File; 8 9 public class FileTest {10 11 public static void main(String[] args) {12 13 File dir = new File("e://demodir"); 14 15 listAll(dir,0);16 17 }18 19 public static void listAll(File dir,int level) {20 21 22 23 System.out.println(getSpace(level)+dir.getName());24 25 //獲取指定目錄下當前的所有文件夾或者文件對象26 27 28 29 level++;30 31 File[] files = dir.listFiles();32 33 for(int x=0; x<files.length; x++){34 35 if(files[x].isDirectory()){36 37 listAll(files[x],level);38 39 }40 41 else42 43 System.out.println(getSpace(level)+files[x].getName());44 45 }46 47 }48 49 private static String getSpace(int level) {50 51 StringBuilder sb = new StringBuilder(); 52 53 sb.append("|--");54 55 for(int x=0; x<level; x++){56 57 sb.insert(0,"| ");58 59 }60 61 return sb.toString();62 63 }64 65 }2、刪除一個帶內容的目錄。
1 /* 刪除一個帶內容的目錄。 2 3 * 原理:必須從最里面往外刪。 4 5 * 需要進行深度遍歷。 6 7 */ 8 9 import java.io.File;10 11 public class RemoveDirTest {12 13 public static void main(String[] args) {14 15 File dir = new File("e://demodir");16 17 removeDir(dir);18 19 }20 21 public static void removeDir(File dir) {22 23 File[] files = dir.listFiles();24 25 for(File file : files){ 26 27 if(file.isDirectory()){28 29 removeDir(file);30 31 }else{32 33 System.out.println(file+":"+file.delete());34 35 }36 37 }38 39 System.out.println(dir+":"+dir.delete());40 41 }42 43 }二、Properties集合
(一)概述
1、Properties是Hashtable的子類,表示一個持久的屬性集,它具備Map集合的特點,是集合中和IO技術相結合的集合。
2、特點:
(1)集合中的鍵和值都是字符串類型。
(2)集合中的數據可以保存到流中,或從流中獲取。
(3)該集合通常用于操作以“鍵值對”形式存在的的配置文件。
(二)Properties操作步驟
1、創建
Properties prop = new Properties();
2、存儲
Prop.setProperties(“zhangsan” , 30);
3、取出
Set<String> names = prop.stringPropertyNames();
value = prop.getProperty(name);
4、修改
prop.setProperty(“zhangsan” , 26);
(三)Properties集合的方法
1、設置
Object setProperty(String key, String value);//設置鍵和值,調用Hashtable的方法put
2、獲取
Set<String> stringPropertyName();//返回屬性列表的鍵集,存入Set集合
String getProperty(String key); //指定key,獲取對應的value
3、調試方法
void list(PrintStream out);//將屬性列表輸出到指定的輸出流
4、載入流方法
void load(InputStream ism); //從輸入字節流中讀取屬性列表(鍵和元素對)。又稱將流中的數據加載進集合。
void load(Reader reader); //從輸入字符流中讀取屬性列表(鍵和元素對)。又稱將流中的數據加載進集合。
5、寫入流方法
void store(OutputStreamout , String comments); //對應load(InputStream )將屬性列表(鍵值對)寫入輸出流。comments屬性列表的描述。
void store(Writer writer, String comments); //對應load(Reader)將屬性列表(鍵值對)寫入輸出流。comments屬性列表的描述。
(四)Properties應用示例:
1 /* 2 3 * 定義功能,獲取一個應用程序運行的次數,如果超過5次,給出使用次數已到請注冊的提示。并不要在運行程序。 4 5 * 思路: 6 7 * (1) 應該有計數器。每次程序啟動都需要計數一次,并且是在原有的次數上進行計數。 8 9 * (2) 計數器就是一個變量。 突然冒出一想法,程序啟動時候進行計數,計數器必須存在于內存并進行運算。 10 11 * 可是程序一結束,計數器消失了。那么再次啟動該程序,計數器又重新被初始化了。 12 13 * 而我們需要多次啟動同一個應用程序,使用的是同一個計數器。 14 15 * 這就需要計數器的生命周期變長,從內存存儲到硬盤文件中。 16 17 * (3) 如何使用這個計數器呢? 18 19 * 首先,程序啟動時,應該先讀取這個用于記錄計數器信息的配置文件。獲取上一次計數器次數,并進行試用次數的判斷。 20 21 * 其次,對該次數進行自增,并自增后的次數重新存儲到配置文件中。 22 23 * (4) 文件中的信息該如何進行存儲并體現。 24 25 * 直接存儲次數值可以,但是不明確該數據的含義。 所以起名字就變得很重要。 26 27 * 這就有了名字和值的對應,所以可以使用鍵值對。 28 29 * 可是映射關系map集合搞定,又需要讀取硬盤上的數據,所以map+io = Properties. 30 31 */ 32 33 import java.io.File; 34 35 import java.io.FileInputStream; 36 37 import java.io.FileOutputStream; 38 39 import java.io.IOException; 40 41 import java.util.Properties; 42 43 public class PropertiesTest { 44 45 public static void main(String[] args) throws IOException { 46 47 getAppCount(); 48 49 } 50 51 public static void getAppCount() throws IOException{ 52 53 //將配置文件封裝成File對象。 54 55 File confile = new File("count.properties"); 56 57 if(!confile.exists()){ 58 59 confile.createNewFile(); 60 61 } 62 63 FileInputStream fis = new FileInputStream(confile); 64 65 Properties prop = new Properties(); 66 67 prop.load(fis); 68 69 //從集合中通過鍵獲取次數。 70 71 String value = prop.getProperty("time"); 72 73 //定義計數器。記錄獲取到的次數。 74 75 int count =0; 76 77 if(value!=null){ 78 79 count = Integer.parseInt(value); 80 81 if(count>=5){ 82 83 throw new RuntimeException("使用次數已到,請注冊,付錢購買!"); 84 85 } 86 87 } 88 89 count++; 90 91 //將改變后的次數重新存儲到集合中。 92 93 prop.setProperty("time", count+""); 94 95 FileOutputStream fos = new FileOutputStream(confile); 96 97 prop.store(fos, ""); 98 99 fos.close();100 101 fis.close();102 103 }104 105 }
三、IO包中的其他類
IO包中的其他類包括:打印流、序列流、操作對象
(一)打印流
1、概述
(1)打印流包括:PrintStream和PrintWriter,可以直接操作輸入流和文件。
(2)該流提供了打印方法,可將對多種數據類型進行打印,并保持數據的表現形式。
(3)它不拋異常。
2、PrintStream構造函數:接收三種類型的值。
(1)字符串路徑
(2)File對象
(3)字節輸出流
3、PrintWriter:字符打印流,其構造函數的參數類型
(1)字符串路徑
(2)File對象
(3)字節輸出流
(4)字符輸出流
4、打印流代碼示例:
1 import java.io.*; 2 3 class PrintStreamDemo{ 4 5 public static void main(String[] args) throws IOException{ 6 7 //鍵盤錄入 8 9 BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));10 11 //打印流關聯文件,自動刷新12 13 PrintWriter out = new PrintWriter(new FileWriter("a.txt"),true);14 15 String line = null;16 17 while((line=bufr.readLine())!=null) {18 19 if("over".equals(line))//結束字符20 21 break;22 23 out.println(line.toUpperCase());24 25 }26 27 //關流28 29 out.close();30 31 bufr.close();32 33 }34 35 }(二)序列流
1、概述
(1)SequenceInputStream對多個流進行合并,也被稱為合并流。
(2)構造函數:SequenceInputStream(Enumeration<? extends InputStream> e)
2、常見合并多個流文件步驟
(1)創建集合Vector,并將流對象添加進集合
(2)創建Enumeration對象,將集合元素加入。
(3)創建SequenceInputStream對象,合并流對象
(4)創建寫入流對象,FileOutputStream關聯寫入文件
(5)利用SequenceInputStream對象和FileOutputStream對象讀數據進行反復讀寫操作。
3、應用示例代碼:
1 /* SequenceInputStream合并流 2 3 需求:將三個文本文件中的數據合并到一個文本文件中 4 5 思路:1、創建一個Vector集合,將三個文本文件字節流添加到集合中 6 7 2、創建Enumeration對象,創建SequnceInputStream對象關聯Enumeration 8 9 3、輸出流關聯新文本文件10 11 4、反復讀寫操作12 13 */14 15 import java.util.*;16 17 import java.io.*;18 19 class SequenceInputStreamDemo{20 21 public static void main(String[] args)throws IOException{22 23 Vector<InputStream> ve=new Vector<InputStream>();//創建vector集合,并添加相關流對象24 25 ve.add(new FileInputStream("1.txt"));26 27 ve.add(new FileInputStream("2.txt"));28 29 ve.add(new FileInputStream("3.txt")); 30 31 Enumeration<InputStream> en=ve.elements();//創建枚舉對象32 33 SequenceInputStream sis=new SequenceInputStream(en);//合并流34 35 FileOutputStream fos=new FileOutputStream("4.txt");//關聯寫入文件36 37 //反復讀寫操作38 39 byte[] buf=new byte[1024];40 41 int len=0;42 43 while((len=sis.read(buf))!=-1){44 45 fos.write(buf,0,len);46 47 }48 49 //關流50 51 fos.close();52 53 sis.close();54 55 }56 57 }》文件切割示例:
1 /* 文件切割器。 */ 2 3 import java.io.File; 4 5 import java.io.FileInputStream; 6 7 import java.io.FileOutputStream; 8 9 import java.io.IOException; 10 11 import java.util.Properties; 12 13 public class SplitFileDemo { 14 15 private static final int SIZE = 1024 * 1024; 16 17 public static void main(String[] args) throws Exception { 18 19 File file = new File("c://aa.mp3"); 20 21 splitFile_2(file); 22 23 } 24 25 private static void splitFile_2(File file) throws IOException { 26 27 28 29 // 用讀取流關聯源文件。 30 31 FileInputStream fis = new FileInputStream(file); 32 33 34 35 // 定義一個1M的緩沖區。 36 37 byte[] buf = new byte[SIZE]; 38 39 40 41 // 創建目的。 42 43 FileOutputStream fos = null; 44 45 46 47 int len = 0; 48 49 int count = 1; 50 51 /* 切割文件時,必須記錄住被切割文件的名稱,以及切割出來碎片文件的個數。 以方便于合并。 52 53 * 這個信息為了進行描述,使用鍵值對的方式。用到了properties對象 54 55 */ 56 57 Properties prop = new Properties(); 58 59 File dir = new File("c://partfiles"); 60 61 if (!dir.exists()) 62 63 dir.mkdirs(); 64 65 while ((len = fis.read(buf)) != -1) { 66 67 fos = new FileOutputStream(new File(dir, (count++) + ".part")); 68 69 fos.write(buf, 0, len); 70 71 fos.close(); 72 73 } 74 75 //將被切割文件的信息保存到prop集合中。 76 77 prop.setProperty("partcount", count+""); 78 79 prop.setProperty("filename", file.getName()); 80 81 fos = new FileOutputStream(new File(dir,count+".properties")); 82 83 84 85 //將prop集合中的數據存儲到文件中。 86 87 prop.store(fos, "save file info"); 88 89 90 91 fos.close(); 92 93 fis.close(); 94 95 } 96 97 public static void splitFile(File file) throws IOException { 98 99 // 用讀取流關聯源文件。100 101 FileInputStream fis = new FileInputStream(file);102 103 104 105 // 定義一個1M的緩沖區。106 107 byte[] buf = new byte[SIZE];108 109 110 111 // 創建目的。112 113 FileOutputStream fos = null;114 115 116 117 int len = 0;118 119 int count = 1;120 121 122 123 File dir = new File("c://partfiles");124 125 if (!dir.exists())126 127 dir.mkdirs();128 129 130 131 while ((len = fis.read(buf)) != -1) {132 133 134 135 fos = new FileOutputStream(new File(dir, (count++) + ".part"));136 137 fos.write(buf, 0, len);138 139 }140 141 fos.close();142 143 fis.close();144 145 }146 147 }》文件合并示例:
1 import java.io.File; 2 3 import java.io.FileInputStream; 4 5 import java.io.FileOutputStream; 6 7 import java.io.IOException; 8 9 import java.io.SequenceInputStream; 10 11 import java.util.ArrayList; 12 13 import java.util.Collections; 14 15 import java.util.Enumeration; 16 17 import java.util.Properties; 18 19 public class MergeFile { 20 21 public static void main(String[] args) throws IOException { 22 23 File dir = new File("c://partfiles"); 24 25 mergeFile_2(dir); 26 27 } 28 29 public static void mergeFile_2(File dir) throws IOException { 30 31 /* 32 33 * 獲取指定目錄下的配置文件對象。 34 35 */ 36 37 File[] files = dir.listFiles(new SuffixFilter(".properties")); 38 39 if(files.length!=1) 40 41 throw new RuntimeException(dir+",該目錄下沒有properties擴展名的文件或者不唯一"); 42 43 //記錄配置文件對象。 44 45 File confile = files[0]; 46 47 48 49 //獲取該文件中的信息============== 50 51 Properties prop = new Properties(); 52 53 FileInputStream fis = new FileInputStream(confile); 54 55 prop.load(fis); 56 57 String filename = prop.getProperty("filename"); 58 59 int count = Integer.parseInt(prop.getProperty("partcount")); 60 61 62 63 //獲取該目錄下的所有碎片文件。 ============= 64 65 File[] partFiles = dir.listFiles(new SuffixFilter(".part")); 66 67 68 69 if(partFiles.length!=(count-1)){ 70 71 throw new RuntimeException(" 碎片文件不符合要求,個數不對!應該"+count+"個"); 72 73 } 74 75 76 77 //將碎片文件和流對象關聯 并存儲到集合中。 78 79 ArrayList<FileInputStream> al = new ArrayList<FileInputStream>(); 80 81 for(int x=0; x<partFiles.length; x++){ 82 83 al.add(new FileInputStream(partFiles[x])); 84 85 } 86 87 88 89 //將多個流合并成一個序列流。 90 91 Enumeration<FileInputStream> en = Collections.enumeration(al); 92 93 SequenceInputStream sis = new SequenceInputStream(en); 94 95 96 97 FileOutputStream fos = new FileOutputStream(new File(dir,filename)); 98 99 100 101 byte[] buf = new byte[1024];102 103 104 105 int len = 0;106 107 while((len=sis.read(buf))!=-1){108 109 fos.write(buf,0,len);110 111 } 112 113 fos.close();114 115 sis.close();116 117 }118 119 120 121 public static void mergeFile(File dir) throws IOException{ 122 123 ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();124 125 126 127 for(int x=1; x<=3 ;x++){128 129 al.add(new FileInputStream(new File(dir,x+".part")));130 131 }132 133 134 135 Enumeration<FileInputStream> en = Collections.enumeration(al);136 137 SequenceInputStream sis = new SequenceInputStream(en);138 139 140 141 FileOutputStream fos = new FileOutputStream(new File(dir,"1.bmp"));142 143 144 145 byte[] buf = new byte[1024];146 147 148 149 int len = 0;150 151 while((len=sis.read(buf))!=-1){152 153 fos.write(buf,0,len);154 155 } 156 157 fos.close();158 159 sis.close(); 160 161 }162 163 }(三)操作對象
1、概述
將堆內存中的對象存入硬盤,保留對象中的數據,稱之為對象的持久化(或序列化)。使用到的兩個類:ObjectInputStream和ObjectOutputStream。
2、特有方法
(1)ObjectInputStream類:
Object readObject():從ObjcetInputStream中讀取對象
(2)ObjectOutputStream類:
void writeObject(Objcet obj):將指定對象寫入ObjcetOutputStream
注意:被操作的對象需要實現Serializable接口(也稱標記接口)
3、序列化接口-Serializable
(1)作用:用于給被序列化的類加入ID號。
(2)序列化運行時使用一個稱為 serialVersionUID的版本號與每個可序列化類相關聯。在反序列化中,用于驗證序列化對象的發送者和接收者是否為該對象加載了與序列化兼容的類。
(3)可序列化類可以通過聲明名為 "serialVersionUID"的字段(該字段必須是靜態 (static)、最終 (final)的 long 型字段)顯式聲明其自己的serialVersionUID,如:public static final long serialVersionUID = 42L;
強烈建議:顯式聲明serialVersionUID.
4、序列化對象操作步驟:
(1)寫入流對象:創建對象寫入流,與文件關聯,即傳入目的。通過寫入writeObject(Object obj)方法,將對象作為參數傳入,即可寫入文件。代碼示例:
ObjecOutputStream oos = new ObjectOutputStream(new FileOutputStream(obj.object));
oos.writeObject(new Person(“小強” , 30));
oos.close();
注:Person類要實現Serializable接口,僅用于標識可序列化的語義。
(2)讀取流對象:創建對象讀取流,與文件關聯,即傳入源。通過readObject()方法,讀取文件中的對象,并返回這個對象。代碼示例:
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(obj.object));
Person p = (Person) ois.readObject();//可能會拋出ClassNotFoundException異常
System.out.println(p.getName()+”:”+p.getAge());
ois.close();
5、補充說明
(1)靜態成員不能被序列化。
(2)非靜態成員要不被序列化,可以用關鍵字transient修飾,保證非靜態成員保存在堆內存中,不能存入文件中。
四、類RandomaccessFile
(一)特點
1、RandomAccessFile類的實例支持對隨機訪問文件的讀取和寫入,它既能讀,又能寫。
2、該類不算是IO體系的子類,而是直接繼承Object,但是它是IO包成員,因為它具備讀寫功能,內部封裝了一個數組,通過指針可以操作數組中的元素。
3、可以通過getFilePointer方法獲取指針位置,通過seek方法,設置文件指針的位置。
4、該對象將字節輸入流和輸出流封裝。
5、該對象的源或目的只能是文件,通過構造函數就可以看出。
(二)構造函數
1、RandomAccessFile( File file , String mode):從它的構造函數可以看出,該類只能操作文件(可以傳入文件名字符串)。其中,mode 參數指定用以打開文件的訪問模式,有四種取值:
(1)"r" 以只讀方式打開。
(2)"rw" 打開以便讀取和寫入。
(3)"rws" 打開以便讀取和寫入。
(4)"rwd" 打開以便讀取和寫入。
注:如果模式為只讀r,則不會創建文件,會去讀一個已存在的文件,若文件不存在,則會出現異常。如果模式為讀寫rw,且該對象的構造函數要操作的文件不存在,會自動創建;如果存在,則不會覆蓋。
2、特有方法
(1)seek(long pos):設置文件的指針位置。
(2)int skipBytes(int n):跳過指定字節數,不可往前跳
(3)String readLine():從此文件讀取文本的下一行。
3、操作步驟
(1)創建RandomAccessFile對象
(2)將數據寫入到指定文件中
(3)讀取指定文件中的數據
4、應用示例
(1)寫入信息
1 RandomAccessFile raf = new RandomAccessFile(“ranacc.txt” , “rw”); 2 3 raf.write(“張三”.getBytes()); 4 5 raf.write(97); 6 7 raf.write(“小強”.getBytes()); 8 9 raf.write(99);10 11 raf.close();
(2)讀取信息
1 byte[] buf = new byte[4]; 2 3 raf.read(buf); 4 5 String name = new String(buf); 6 7 int age = raf.readInt(); 8 9 System.out.println(“ name ” + name);10 11 System.out.println(“ age” + age);
注:可以使用文件指針seek方法或skipBytes方法尋找寫入或讀出的位置。
5、練習:使用RandomAccessFileDemo進行讀寫操作
1 //需求:使用RandomAccessFileDemo進行讀寫操作 2 3 import java.io.*; 4 5 class RandomAccessFileDemo{ 6 7 public static void main(String[] args)throws IOException{ 8 9 //指定文件 10 11 File file =new File("ran.txt"); 12 13 14 15 //寫數據 16 17 writeFile(file); 18 19 20 21 //讀數據 22 23 readFile(file); 24 25 } 26 27 28 29 //讀取指定文件中的數據 30 31 public static void readFile(File file)throws IOException{ 32 33 //創建對象 34 35 RandomAccessFile raf=new RandomAccessFile(file,"r"); 36 37 38 39 //設置指針位置 40 41 raf.seek(8); 42 43 44 45 //設置跳過的字節數 46 47 //raf.skipBytes(8); 48 49 50 51 //讀取四個字節存入 52 53 byte[] by=new byte[4]; 54 55 //讀數據 56 57 raf.read(by); 58 59 //將存入數據的字節數組轉換為字符串 60 61 String name=new String(by); 62 63 //根據寫入規律,讀取年齡,這里用到了讀一個int方法 64 65 int age=raf.readInt(); 66 67 68 69 System.out.println("name="+name+"age="+age); 70 71 72 73 raf.close();//關流 74 75 } 76 77 78 79 //將數據寫入指定文件中 80 81 public static void writeFile(File file)throws IOException{ 82 83 //創建對象 84 85 RandomAccessFile raf=new RandomAccessFile(file,"rw"); 86 87 88 89 //寫入姓名 90 91 raf.write("張三".getBytes()); 92 93 //寫入年齡,這里調用了寫一個int方法 94 95 raf.writeInt(23); 96 97 98 99 raf.write("李四".getBytes());100 101 raf.writeInt(100);102 103 104 105 raf.seek(8*0);//改變指針106 107 raf.write("小三".getBytes());108 109 raf.writeInt(3);110 111 112 113 raf.skipBytes(8*2);//改變指針114 115 raf.write("王五".getBytes());116 117 raf.writeInt(5);118 119 120 121 raf.close();//關流122 123 }124 125 }五、管道流
(一)概述
1、管道流:需要和多線程技術相結合的流對象。它包括:PipedInputStream、PipedOutputStream。
2、特點:
(1)輸入輸出可以直接進行連接,不需要數組或集合等臨時緩沖區。
(2)需要和線程一同使用。
3、操作步驟
(1)要先創建一個讀和寫的兩個類,實現Runnable接口,覆蓋run方法。
(2)創建兩個管道流,并用connect()方法將兩個流連接
(3)創建讀寫對象,并傳入兩個線程內,調用start執行。
4、應用示例
1 import java.io.IOException; 2 3 import java.io.PipedInputStream; 4 5 import java.io.PipedOutputStream; 6 7 public class PipedStream { 8 9 public static void main(String[] args) throws IOException {10 11 PipedInputStream input = new PipedInputStream();12 13 PipedOutputStream output = new PipedOutputStream();14 15 input.connect(output);// 用connect()方法將兩個流連接16 17 new Thread(new Input(input)).start();18 19 new Thread(new Output(output)).start();20 21 }22 23 }24 25 class Input implements Runnable{26 27 private PipedInputStream in;28 29 Input(PipedInputStream in){30 31 this.in = in;32 33 }34 35 public void run(){36 37 try {38 39 byte[] buf = new byte[1024];40 41 int len = in.read(buf);42 43 44 45 String s = new String(buf,0,len);46 47 48 49 System.out.println("s="+s);50 51 in.close();52 53 } catch (Exception e) {54 55 // TODO: handle exception56 57 }58 59 }60 61 }62 63 class Output implements Runnable{64 65 private PipedOutputStream out;66 67 Output(PipedOutputStream out){68 69 this.out = out;70 71 }72 73 public void run(){74 75 try {76 77 Thread.sleep(5000);78 79 out.write("hi,管道流來了!".getBytes());80 81 } catch (Exception e) {82 83 // TODO: handle exception84 85 }86 87 }88 89 }六、操作基本類型數據的流對象(DateStream)
(一)概述
1、操作基本數據類型的流對象:DataInputStream和DataOutputStream
2、這兩個讀寫對象,可用于操作基本數據類型的流對象,包含讀寫各種基本數據類型的方法。
(二)讀寫方法
1、讀:String readUTF():對應writeUTF,從包含的輸入流中讀取此操作需要的字節。
2、寫:writeUTF(String str):以與機器無關方式使用 UTF-8 修改版編碼將一個字符串寫入基礎輸出流。
(三)應用示例
1 import java.io.DataInputStream; 2 3 import java.io.DataOutputStream; 4 5 import java.io.FileInputStream; 6 7 import java.io.FileOutputStream; 8 9 import java.io.IOException;10 11 public class DataSteamDemo {12 13 public static void main(String[] args) throws IOException {14 15 writeData();16 17 readData();18 19 }20 21 public static void readData() throws IOException {22 23 DataInputStream dis = new DataInputStream(new FileInputStream("data.txt")); 24 25 String str = dis.readUTF();26 27 System.out.println(str);28 29 }30 31 public static void writeData() throws IOException {32 33 DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));34 35 dos.writeUTF("你好");36 37 dos.close();38 39 }40 41 }七、操作字節數組、字符數組、字符串
(一)操作字節數組
1、用流的思想操作數組,只操作內存。
2、包括:ByteArrayInputStream、ByteArrayOutputStream
3、方法:當源或目的是內存時:
(1)當源是內存時,ByteArrayInputStream bis = new ByteArrayInputStream(“abced”.getBytes());
(2)當目的是內存時,ByteArrayOutputStream bos = new ByteArrayOutputStream();
4、特有方法:
(1)ByteArrayInputStream方法有:toString(); toByteArray();
(2)ByteArrayOutputStream方法有:
writeTo(OutputStream out):將此 byte 數組輸出流的全部內容寫入到指定的輸出流參數中,這與使用out.write(buf, 0, count)調用該輸出流的 write 方法效果一樣。
int size():當前緩沖區的大小
String toString():使用平臺默認的字符集,通過解碼字節將緩沖區內容轉換為字符串。
(二)操作字符數組
CharArrayReader、CharArrayWriter
(三)操作字符串
StringReader、StringWriter
八、編碼、解碼
(一)概述
1、字符流的出現為了方便操作字符。
2、更重要的是加入了編碼的轉換,即轉換流。
3、通過子類轉換流來完成。在兩個對象進行構造的時候,可以加入字符集(即編碼表),可傳入編碼表的有:
(1)轉換流:InuputStreamReader和OutputStreamWriter
(2)打印流:PrintStream和PrintWriter,只有輸出流
4、編碼表的由來
計算機只能識別二進制數據,早期由來是電信號。為了方便應用計算機,讓它可以識別各個國家的文字。就將各個國家的文字用數字來表示,并一一對應,形成一張表。這就是編碼表。
5、常見的編碼表:
(1)ASCII:美國標準信息交換碼表,用一個字節的7位表示。
(2)IOS8859-1:拉丁碼表;歐洲碼表,用一個字節的8位表示。
(3)GB2312:早期中文編碼表。
(4)GBK:中國的中文編碼表升級,融合了更多的中文文字字符,打頭的是高位為1的兩個字節編碼。
(5)Unicode:國際標準碼,融合了多種文字。所有文字都用兩個字節來表示,Java語言使用的就是unicode。
(6)UTF-8:最多用三個字節表示一個字符的編碼表,根據字符所占內存空間不同,分別用一個、兩個、三個字節來編碼。
(二)轉換流的編碼應用
1、可以將字符以指定編碼格式存儲。
2、可以對文本數據指定編碼格式來解讀。
3、指定編碼表的動作由構造函數完成。
(三)編碼和解碼
1、編碼:字符串變成字節數組
(1)默認字符集:String--->byte[]:srt.getBytes()
(2)指定字符集:String--->byte[]:srt.getBytes(charsetName)
2、解碼:字節數組變成字符串
(1)默認字符集:byte[] ---> String:new String(byte[])
(2)指定字符集:byte[]--->String:newString(byte[],charsetName)
(四)對于編碼和解碼的字符集轉換注意事項
1、如果編碼失敗,解碼就沒意義了。
2、如果編碼成功,解碼出來的是亂碼,,則需對亂碼通過再次編碼(用解錯碼的編碼表),然后再通過正確的編碼表解碼。針對于IOS8859-1是通用的。
3、如果用的是GBK編碼,UTF-8解碼,此時通過再次編碼后解碼的方式,就不能成功了,因為UTF-8也支持中文,在UTF-8解的時候,會將對應的字節數改變,所以不會成功。
4、特別注意:對于中文的”聯通“,這兩個字比較特別,它的二進制位正好是和在UTF-8中兩個字節打頭的相同,所以在文本文件中,如果單獨寫“聯通”或者和滿足UTF-8編碼格式的字符一起保存時,記事本就會用UTF-8來進行解碼動作,這樣顯示的就會是亂碼。
---------- android培訓、java培訓、期待與您交流! ----------
新聞熱點
疑難解答