IO包中的其他流:
1.打印流
a)PrintWriter(寫-->print打印) 與PrintStream (字符流)
1 PrintWriter用法一:其實它是對一個Writer進行了封裝 2 package com.javami.kudyTest; 3 import java.io.FileNotFoundException; 4 import java.io.PrintWriter; 5 public class PrintWriterTest { 6 /* 7 * PrintWriter 是對Writer 進行了一個封裝 8 */ 9 public static void main(String[]args) throws FileNotFoundException 10 { 11 PrintWriter pw = new PrintWriter("src/a.txt"); 12 int num = 98; //char類型占了一個類型 13 // pw.write(num); //輸出了一個char類型的 14 pw.print(num); //輸出的是int類型的 15 /* 16 * 其實里面做的事情 17 * String str = str.valueOf(int) //轉換成字符串 再轉換為字節 98 18 * 而我們系統默認的字節編碼格式每一個字符是占了1位的,所以顯示出來的結果為是2bytes 19 * --------------------------------- 20 * String str = str.valueOf(num); 21 * byte[]buf = str.getBytes(); //轉換成字節 22 * for(byte ch :buf) 23 * while(ch); 24 */ 25 pw.close(); 26 27 } 28 } 29 第二:PrintStream 30 是繼承于OutputStream(輸出流(字節流)) 31 package com.javami.kudyTest; 32 import java.io.FileNotFoundException; 33 import java.io.PrintStream; 34 public class PrintStreamTest { 35 /* 36 * PrintStream 的應用: 37 * 這是一個字節流: 輸出字節流 38 * (寫數據) 39 * 繼承于:OutputStream 40 */ 41 public static void main(String[]args) throws FileNotFoundException 42 { 43 PrintStream ps = new PrintStream("src/b.txt"); 44 // int num = 98; 45 // ps.write(num); 46 47 int num = 97; 48 ps.print(num); //本質上是沒有區別.但是內部實現原理就有區別 (占了2個字節) 49 50 /* 51 * 實現原理和PrintWriter很想: 52 * String str = str.valueOf(num); //轉換成字符 53 * byte[] buf = str.getBytes(); 54 * for(byte b : buf) 55 * { 56 * 字節數現在為2 存入的是字節.之后系統會根據系統的編碼格式進行了一個解碼 57 * } 58 */ 59 } 60 }
2.序列流
b)SequencelnputStream(假設我有多個文本.需要合并成一個文本)
1 package com.javami.kudyTest; 2 3 import java.io.FileInputStream; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.io.OutputStream; 7 import java.io.FileOutputStream; 8 import java.io.SequenceInputStream; 9 import java.util.Enumeration; 10 import java.util.Vector; 11 import java.util.Iterator; 12 public class SequenceInputStreamTest { 13 /* 14 * 序列流 15 */ 16 public static void main(String[]args) throws IOException 17 { 18 /* 19 * 讀取兩個文本的方式 20 */ 21 InputStream is1 = new FileInputStream("src/a.txt"); 22 InputStream is2 = new FileInputStream("src/b.txt"); 23 OutputStream os = new FileOutputStream("src/c.txt"); 24 //讀取兩個參數 25 SequenceInputStream sis = new SequenceInputStream(is1,is2); 26 byte[] buf = new byte[1024]; 27 int ch; 28 while((ch=sis.read(buf))!=-1) 29 { 30 os.write(buf,0,ch); 31 } 32 33 //關流,由于SequenceInputStream 是一個包裝類.但把這個流關閉.會把底層的兩個流也關 34 sis.close(); 35 os.close(); 36 37 /* 38 * 如果我有很多文本需要合并內容的,但是構造方法只能傳遞進去.這時候如果用到帶兩個參數的構造方法來傳遞就不是太方便啦~~ 39 * 那么我可以使用使用到枚舉+集合 40 */ 41 InputStream isone = new FileInputStream("src/a.txt"); 42 InputStream istwo = new FileInputStream("src/b.txt"); 43 InputStream isthree = new FileInputStream("src/c.txt"); 44 OutputStream osone = new FileOutputStream("src/happy.txt"); 45 Vector<InputStream> v = new Vector<InputStream>(); 46 v.add(isone); 47 v.add(istwo); 48 v.add(isthree); 49 /* //枚舉里面我需要使用的是InputStream 50 Enumeration<InputStream> e = v.elements(); 51 //讀取枚舉里面的內容.再寫入到一個文本里面去 52 //里面只能放一個枚舉類型.并且這個枚舉類型的泛型是繼承于InputStream的 53 SequenceInputStream sisone = new SequenceInputStream(e); //讀寫集合里面的內容.已經合并在一起啦 54 int len; 55 while((len=sisone.read())!=-1) 56 { 57 osone.write(len); 58 } 59 //關流 60 sisone.close(); //這個如果關流.已經把底層的三個流已經被關閉 61 osone.close();*/ 62 63 //看第二種方式: 產生一個迭代器 64 final Iterator<InputStream> it = v.iterator(); 65 SequenceInputStream sistwo = 66 new SequenceInputStream(new Enumeration<InputStream>(){ 67 68 @Override 69 //這里面是否有更多的元素呢? 70 public boolean hasMoreElements() { 71 72 return it.hasNext(); 73 } 74 75 @Override 76 //下一個元素為多少呢? 77 public InputStream nextElement() { 78 // TODO Auto-generated method stub 79 return it.next(); 80 } 81 82 }); 83 int len; 84 //一個字符一個字符讀取進去的方式啊?沒有包裝的.哥們.難道你忘記啦? 85 //不讀出來怎么寫? 您教我. 86 while((len=sistwo.read())!=-1) 87 { 88 osone.write(len); //讀一個字節.寫一個字節 89 } 90 91 } 92 }
3.操作對象
c)ObjectinputStream與ObjectOutputStream(對象必須要實現Serializable這個接口,做為標記需要使用序列 或者序列化
1 package com.javami.kudyTest; 2 import java.io.FileInputStream; 3 import java.io.FileNotFoundException; 4 import java.io.IOException; 5 import java.io.ObjectInputStream; 6 import java.io.ObjectOutputStream; 7 import java.io.FileOutputStream; 8 import java.io.Serializable; 9 10 public class ObjectStreamTest { 11 /* 12 * 對象序列化: 13 * 有的時候我們需要找一種數據對內存中的對象進行描述.便于保存.這時,可能每個程序員都有自己的想法. 14 * 都會去使用自己習慣的方式,對象的序列化,就是按照java規定格式對對象轉換成一種數據,編譯保存.這個過程就是對象的序列化 15 * 將數據的格式轉換成對象就是叫做反序列化 16 */ 17 public static void main(String[]args) throws FileNotFoundException, IOException, ClassNotFoundException 18 { 19 /* Person p1 = new Person("張三",18); 20 Person p2 = new Person("王五",19); 21 Person p3 = new Person("李四",20); 22 Person p4 = new Person("大毛",21);*/ 23 24 /* 25 ObjectOutputStream oos = 26 new ObjectOutputStream(new FileOutputStream("src/1.txt")); 27 oos.writeObject(p1); //父類型的引用可以指向子類型的對象 28 oos.writeObject(p2); 29 oos.writeObject(p3); 30 oos.writeObject(p4); 31 oos.close(); 32 /1.對象的序列化的第一種方式 33 */ 34 35 /* 36 * 假設我們已經序列化:現在需要反序列化>需要把對象里面的內容輸出去 37 */ 38 ObjectInputStream ois = 39 new ObjectInputStream(new FileInputStream("src/1.txt")); 40 41 42 43 while(true) 44 { 45 try 46 { 47 Person p =(Person)ois.readObject(); 48 System.out.println(p); 49 }catch(IOException e) 50 { 51 return ; 52 } 53 54 //如果是異常的,咱們就不執行 55 } 56 57 } 58 } 59 60 61 62 /* 63 * 類通過實現 java.io.Serializable 接口以啟用其序列化功能。未實現此接口的類將無法使其任何狀態序列化或反序列化。 64 * 由于我們希望序列化的是Person 這個類.所以我們要實現這個接口 65 * 這個主要就是做一個下標識 66 * 但異常出現的錯誤為:NotSerializableException 就是說明了: 有一個類還沒有被標記即將要序列化 67 */ 68 class Person implements Serializable 69 { 70 private String name; 71 private int age; 72 Person(){} 73 Person(String name,int age) 74 { 75 this.name = name; 76 this.age = age; 77 } 78 @Override 79 public String toString() 80 { 81 return this.name +"@"+this.age; 82 } 83 } 84 85 第二種方式: 可以利用集合去做一個問題 86 (輸入數據 通過集合讀 通過遍歷集合寫.) 建議使用哦 87 package com.javami.kudyTest; 88 89 import java.io.FileInputStream; 90 import java.io.FileNotFoundException; 91 import java.io.FileOutputStream; 92 import java.io.IOException; 93 import java.io.ObjectInputStream; 94 import java.io.ObjectOutputStream; 95 import java.io.Serializable; 96 import java.util.ArrayList; 97 98 /* 99 * 可以通過集合去寫入數據 ... 之后再通過集合遍歷數據.. 100 */ 101 public class ObjetcStreamTest2 { 102 public static void main(String[]args) throws FileNotFoundException, IOException, ClassNotFoundException 103 { 104 105 /* 106 * 1.序列化 107 108 Person p1 = new Person("張三",18); 109 Person p2 = new Person("王五",19); 110 Person p3 = new Person("李四",20); 111 Person p4 = new Person("大毛",21); 112 ObjectOutputStream oos = 113 new ObjectOutputStream(new FileOutputStream("src/Object.txt")); 114 ArrayList<Person> al = new ArrayList<Person>(); 115 al.add(p1); 116 al.add(p2); 117 al.add(p3); 118 al.add(p4); 119 oos.writeObject(al); 120 oos.close();*/ 121 122 /* 123 * 反序列化 124 */ 125 ObjectInputStream ois = 126 new ObjectInputStream(new FileInputStream("src/Object.txt")); 127 //要把這個類型強制轉換 128 ArrayList<Person> al = (ArrayList<Person>)ois.readObject(); 129 for(Person p : al) 130 { 131 System.out.println(p); 132 } 133 ois.close(); 134 } 135 } 136 137 /* 138 * Person 實現一個接口,標記為即將序列化或者反序列化 139 */ 140 class Person implements Serializable 141 { 142 private String name; 143 private int age; 144 Person(){} 145 Person(String name,int age) 146 { 147 this.name = name; 148 this.age = age; 149 } 150 @Override 151 public String toString() 152 { 153 return this.name +"@"+this.age; 154 } 155 }
將圖片切割成若干份,每10k一個文件, 再使用序列流組合成圖片(為什么第一張圖片可以看得到呢.特征碼的問題)
小練習:
1 package com.javami.kudyTest; 2 import java.io.File; 3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.io.FileOutputStream; 6 import java.io.IOException; 7 import java.io.InputStream; 8 import java.io.SequenceInputStream; 9 import java.util.Enumeration; 10 import java.util.Vector; 11 public class PictureCut { 12 13 14 public static void main(String[] args) { 15 File file = new File("f:/a/1.jpg"); 16 try 17 { 18 //cutPicture(file); 19 splicePicture(); 20 }catch (IOException e) { 21 // TODO: handle exception 22 e.printStackTrace(); 23 } 24 } 25 /** 26 * 將圖片分成若干份,每10K一份,再使用序列流組合圖片 27 * 思路: 需要定義一個FileinputStream 讀取一個圖片. 再寫入到一個FileInputStream里面去 28 * 定義一個byte[] buf = new byte[1024]; //緩沖區定義成1k 29 * int count = 0; //標記循環10次.也就是10K 30 * int num = 1; //標記圖片命名 31 * int len ; //返回的字符 32 * 循環讀取一個圖片.當讀取到10K的時候.咱們就寫入到一個新的字節流里面去.. 33 * 注意count每一次標記一下.當count等于10的時候.咱們要重新清空一下. 34 * 35 * 36 */ 37 private static void cutPicture(File file) throws IOException 38 { 39 FileInputStream fis = null;//輸入 40 FileOutputStream fos = null; //輸出流 41 try 42 { 43 fis = new FileInputStream(file); 44 fos = new FileOutputStream("f:/a/a1.jpg"); //寫入到這個文本里面去 45 byte[] buf = new byte[1024]; //1K的大小 46 int count = 0; //標記如果是讀到10K就是一個圖片 47 int len; 48 int num = 1; //等待給一個圖片標號 49 while((len=fis.read(buf))!=-1) //意思: 從緩沖區讀取10K的字節內容賦給len 0,len最大字符數 50 { 51 //每次從緩沖區那里邊讀取1K 52 if(count==10) 53 { 54 count=0; //清空一下. 55 fos.close(); //關閉上一次的流 56 fos = new FileOutputStream("f:/a/a"+(++num)+".jpg"); 57 } 58 //從緩沖區里面寫入buf 0 ,len的內容 .是不是剛好1K的內容 59 fos.write(buf,0,len); //把10K內容寫入進去 //0-9 剛好10次 60 //標記是否是10次 0 - 9 剛好10次 10 -19 剛好10次 ... 61 count++; 62 } 63 64 }finally 65 { 66 try 67 { 68 if(fis!=null) 69 fis.close(); 70 }finally 71 { 72 if(fos!=null) 73 fos.close(); 74 } 75 } 76 } 77 78 79 80 /* 81 * 并且一個圖片,咱們可以先讀取一個圖片 82 * 可以所以用到枚舉 83 */ 84 private static void splicePicture() throws IOException 85 { 86 /* 87 * Vector是一個集合 88 */ 89 90 Vector<InputStream> v = new Vector<InputStream>(); //讀取圖片 91 SequenceInputStream sis = null; 92 FileOutputStream fos = null; 93 v.add(new FileInputStream("F:/a/a1.jpg")); 94 v.add(new FileInputStream("F:/a/a2.jpg")); 95 v.add(new FileInputStream("F:/a/a3.jpg")); 96 v.add(new FileInputStream("F:/a/a4.jpg")); 97 v.add(new FileInputStream("F:/a/a5.jpg")); 98 v.add(new FileInputStream("F:/a/a6.jpg")); 99 v.add(new FileInputStream("F:/a/a7.jpg")); 100 v.add(new FileInputStream("F:/a/a8.jpg")); 101 v.add(new FileInputStream("F:/a/a9.jpg")); 102 Enumeration<InputStream> e = v.elements(); //枚舉類型 103 try 104 { 105 sis = new SequenceInputStream(e); 106 fos = new FileOutputStream("src/dj.jpg"); 107 int ch; 108 while((ch=sis.read())!=-1) 109 { 110 //寫入字節流 111 fos.write(ch); 112 } 113 }finally 114 { 115 try 116 { 117 if(sis!=null) 118 sis.close(); 119 } 120 finally 121 { 122 if(fos!=null) 123 fos.close(); 124 } 125 } 126 127 128 } 129 130 }
4.操作基本數據類型
d)DataInputStream 與DataOutputStream
1 package com.javami.kudyTest; 2 import java.io.DataOutputStream; 3 import java.io.DataInputStream; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.FileOutputStream; 7 import java.io.IOException; 8 public class DataStreamTest { 9 10 /** 11 * 操作基本數據類型: 12 * 格式化數據類型: int類型占了4個字節.寫在文本里面也是占了4個字節 13 * @throws IOException 14 */ 15 public static void main(String[] args) throws IOException 16 { 17 /*DataInputStream dis = 18 new DataInputStream(new FileInputStream("src.ohoh.txt")); 19 int num = 98;*?里面有98給我讀取嗎?*/ 20 21 /*DataOutputStream dos = 22 new DataOutputStream(new FileOutputStream("src/ohoh.txt")); //寫入數據 23 int num = 98; 24 //dos.writeInt(num); 是以int類型所占的字節寫入進去,4個字節 25 String str = "abc中國人"; 26 dos.writeUTF(str);//是以UTF編碼寫入進去 漢字占3個字節 27 */ 28 //讀 29 DataInputStream dis = new DataInputStream(new FileInputStream("src/ohoh.txt")); 30 /* 31 * 是與UTF編碼寫進去的,咱們就用相同的碼表去解碼 32 */ 33 String datat = dis.readUTF(); 34 System.out.println(datat); 35 dis.close(); 36 /* 37 * 將一個 int 值以 4-byte 值形式寫入基礎輸出流中,先寫入高字節。如果沒有拋出異常,則計數器 written 增加 4。 38 * 39 */ 40 41 } 42 43 }
5.操作內存緩沖數組
e)ByteArrayStream與CharArrayReader
1 package com.javami.kudyTest; 2 3 import java.io.ByteArrayInputStream; 4 import java.io.ByteArrayOutputStream; 5 import java.io.FileInputStream; 6 import java.io.FileNotFoundException; 7 import java.io.IOException; 8 9 10 public class ByteArrayStream { 11 12 /* 13 * ByteArrayInputStream 讀取字節 14 * ByteArrayOutputStream 寫入字節 15 */ 16 public static void main(String[]args) throws IOException 17 { 18 String chinese = "我是中國人.釣魚島是咱們中國的同胞的.jb帝國主義滾~~~"; 19 20 byte[] buf = chinese.getBytes(); //獲取到字節數組 21 22 //讀取字節包裝流 23 ByteArrayInputStream bais = new ByteArrayInputStream(buf); 24 int len = bais.available(); //獲取到字節里面有多少個字節 25 byte[] bufs = new byte[len]; //自定義大小做緩沖區.為什么這樣做.以為我們這樣做.可以節省內存空間. 26 bais.read(bufs); //我們把定義存儲到自定義緩沖區里面去 27 String happy = new String(bufs); 28 System.out.println(happy); 29 bais.close(); 30 31 //寫入字節包裝類 32 ByteArrayOutputStream bos = 33 new ByteArrayOutputStream(); 34 bos.write("jb滾出釣魚釣".getBytes()); 35 byte[] jbs = bos.toByteArray(); //獲取里面的數據 36 System.out.println(new String(jbs)); 37 bos.close(); 38 } 39 /* 40 * 一般的用法: 41 * DataoutputStream dos = new DataOutputStream(new ByteArrayOutputStream()); 42 */ 43 44 }
6.管道流
PipedinputStream與PipedOutputStream
1 package com.javami.kudyTest; 2 3 import java.io.IOException; 4 import java.io.PipedInputStream; 5 import java.io.PipedOutputStream; 6 7 public class PipedStreamTest { 8 public static void main(String[]args) throws IOException 9 { 10 //1.輸入流讀 11 PipedInputStream pis = new PipedInputStream(); 12 //2.輸出流寫 13 PipedOutputStream pos = new PipedOutputStream(); 14 15 //3.輸入流連接輸出流 16 pis.connect(pos); 17 18 //從服務器的角度來說:向用戶發出信息 發出的字節 19 pos.write("歡迎來到本站".getBytes()); 20 21 int len = pis.available(); 22 byte[] buf = new byte[len]; //獲取到一個自定義緩沖區大小數組 23 //自定義一個緩沖區大小.把內容讀取到這邊來 24 pis.read(buf); //把內容讀取到一個buf里面去 25 //已經被獨到了buf里面去 26 String user = new String(buf); 27 System.out.println(user); 28 pis.close(); 29 pos.close(); 30 } 31 }
7.RandomAccessFile 實現了該類的實例支持對隨機文件的讀取和寫入
1 package com.javami.kudyTest; 2 import java.io.IOException; 3 import java.io.RandomAccessFile; 4 5 public class RandomAccessFileTest { 6 7 /** 8 * 編寫一個程序,記錄該程序運行次數,運行滿足30day.就提示軟件到期 9 * @throws IOException 10 * @throws NumberFormatException 11 */ 12 public static void main(String[] args) throws IOException 13 { 14 //打開以便讀取和寫入。如果該文件尚不存在,則嘗試創建該文件。 15 //讀一次.寫一次.讀一次.寫一次. 16 RandomAccessFile raf = new RandomAccessFile("src/count.txt","rw"); 17 int count = Integer.parseInt(raf.readLine()); //轉換成int類型 18 count++; 19 if(count>10) 20 { 21 System.out.println("軟件已經到期"); 22 return ; //結束整個循環 23 } 24 System.out.println("已經使用了"+count+"次,請馬上續費~~"); 25 String str = String.valueOf(count); 26 //再寫入進去.就是一讀一些的概念啦 27 /* 28 * 注意這個偏移量的問題.如果我們不設置偏移量的時候. 29 * 他執行的順序是: 012 那么程序判斷成12就結束啦.. 30 * 設置偏移量為零: 31 * 位置是不會懂的0 32 * 1 33 * 2 34 * 3...這樣 35 */ 36 raf.seek(0); 37 raf.write(str.getBytes()); //把字節寫進去 把字節寫進去. 38 raf.close(); 39 40 } 41 42 }
這個學習的說好不好,說壞不壞.但是在休息中浪費的時間比較多..
希望以后好好努力..加油..