from http://www.cnblogs.com/hqr9313/archive/2012/04/23/2467294.html
java IO流(InputStream/OutputSteam)
什么是IO流? byte序列的讀寫,Java中的IO流是實現輸入/輸出的基礎.1)InputStream : 抽象類讀取數據的過程 包含讀取方法read(); in 模仿了讀取小說的過程
簡單說 : in是讀取文件的
OutputStream:抽象了寫出數據的過程 包含寫出方法write(); out模仿了寫筆記記錄的過程
簡單說 : out是寫入文件的
基本的byte流InputStream(抽象方法read()) |--- FileInputStream(read()在文件上讀取) 節點流 | |--- FilterInputStream 過濾器流,輸入流功能的擴展 | |--- DataInputStream(readInt()) 基本類型數據的讀取 | |--- BufferedInputStream 提供讀取緩沖區管理 | --- ObjectInputStream 過濾器流,依賴基本byte流,擴展對象的反序列化
OutputStream(抽象方法write()) |--- FileOutputStream(write()在文件上寫實現寫入) 節點流 | |--- FilterOutputStream 過濾器流,輸出流功能的擴 | |--- DataOutputStream(writerInt()) 基本類型數據的寫出 | |--- BufferedOutputStream 提供了輸出緩沖區管理 | --- ObjectOutputStream 過濾器流,依賴基本byte流,擴展對象的序列化
注意:除節點流外都是過濾器流
字符流,可以處理字符編碼,底層依賴于byte流Reader 讀取文本 | --- InputStreamReader 過濾去,依賴基本byte輸入流 | 實現文本編碼的解析 | | --- BufferedReader 過濾器, 需要依賴Reader 實例 | 提供了readLine()方法, 可以在文本文件中讀取一行 | 是常用的文本讀取方法 Writer | --- OutputStreamWriter 過濾器,,依賴基本byte輸出流 | 實現文本編碼 | --- PRintWriter 過濾器,依賴于Writer 流 | 提供了輸出文本常有方法println()
2) EOF = End of File = -1 (文件讀到末尾會返回-1)
3) 輸入流的基本方法 InputStream in = new InputStream(file) / /file是文件名 int b = in.read(); 讀取一個byte無符號填充到int底八位,-1是EOF int.read(byte[] buf) 讀取數據填充到buf中 int.read(byte[] buf,int start,int size) 讀取數據填充到buf中 in.close 關閉輸入流
4)輸出流的基本方法: OutputStream out = new OutputStream(file) / /file是文件名 out.write(int b) 寫出一個byte 到流 b 的底八位寫出 out.write(byte[] buf) 將buf的一部分寫入流中 out.write(byte[] buf, int start, int size) 將buf的一部分寫入流中 out.flush() 清理緩存 out.close
1.FileInputStream (read()在文件上讀取) 節點流方法: read() 從輸入流中讀取數據的下一個字節 read(byte[] buf) 從輸入流中讀取一定數量的字節,并將其存儲在緩沖區數組 buf中 read(byte[] b, int off, int len) 將輸入流中最多 len 個數據字節讀入 byte 數組。例
1 import java.io.FileInputStream; 2 import java.io.IOException; 3 import java.io.InputStream; 4 5 public class InputStreamDemo { 6 public static void main(String[] args) 7 throws IOException { 8 String file = "out.txt"; 9 InputStream in = new FileInputStream(file);10 int b;11 while((b=in.read())!=-1){//read()方法12 System.out.print(Integer.toHexString(b) + " ");13 }14 in.close();15 16 in = new FileInputStream(file);17 //in.available() 可以讀取的數據個數,小文件一般是文件長度18 byte[] buf = new byte[in.available()];19 in.read(buf);//read(byte[] buf)方法重載20 in.close();21 for (byte c : buf) {22 System.out.print(Integer.toHexString(c & 0xff) + " ");23 // c & 0xff --->將16進制寫成0xff的格式24 //ffffffd6---> d625 //11111111 11111111 11111111 11010110 &對應相乘26 //00000000 00000000 00000000 11111111 0xff27 //00000000 00000000 00000000 1101011028 }29 }30 }
2 FileOutputStream(write()在文件上寫實現寫入) 節點流方法 :write(int b) 將指定的字節寫入此輸出流。 write(byte[] buf) 將 b.length 個字節從指定的 byte 數組寫入此輸出流。 write(byte[] b, int off, int len) 將指定 byte 數組中從偏移量 off 開始的 len 個字節寫入此輸出流。例子
1 import java.io.*; 2 3 public class OutputStreamDemo { 4 public static void main(String[] args) 5 throws IOException{ 6 String file = "out.txt"; 7 OutputStream out = new FileOutputStream(file); 8 out.write(65);//在文件中是以16進制存儲的,對應0x41 9 out.write(66);//0x4210 byte[] buf = {(byte)0xd6,(byte)0xd0};11 out.write(buf);12 out.flush();//刷出緩存,清理緩沖區,保證可靠寫 13 out.close();14 }15 }
3.BufferedInputStream和BufferedOutputStream 的 用法
BufferedInputStream(FileInputStream in) BufferedOutputStream(FileOutputStream out)可以提高性能例子
1 import java.io.BufferedInputStream; 2 import java.io.BufferedOutputStream; 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 import java.io.InputStream; 7 8 public class BufferedStreamDemo { 9 public static void main(String[] args) throws IOException {10 //BufferedInputStream普通寫法11 String file = "out.txt";12 InputStream ins = new FileInputStream(file);13 BufferedInputStream bufin= new BufferedInputStream(ins);14 int b;15 while((b=bufin.read())!=-1){16 System.out.println(Integer.toHexString(b));17 }18 //常用寫法,只要用到FileInputStream的地方都可以套一個BufferedInputStream用來提升性能19 BufferedInputStream in = new BufferedInputStream(20 new FileInputStream("out.txt"));21 22 //BufferedOutputStream23 BufferedOutputStream out = new BufferedOutputStream(24 new FileOutputStream("out.txt"));25 out.write(65);26 }27 }
4.基本類型數據的寫出和讀入DataOutputStream 方法:readInt() readLong() readBoolean()等寫出(寫)
1 例子 2 import java.io.*; 3 public class DataOutDemo { 4 public static void main(String[] args) 5 throws IOException{ 6 String file = "data.dat";//項目文件夾 7 OutputStream out = new FileOutputStream(file); 8 //DataOutputStream 實現基本類型數據的序列化 9 //將基本類型數據拆開為byte序列,寫入到out流中10 DataOutputStream dos = new DataOutputStream(out);11 dos.write(-2);12 dos.writeInt(-2);13 dos.writeLong(-2);14 dos.writeByte(-2);15 dos.writeDouble(-2);16 dos.writeShort(-2);17 dos.writeFloat(-2);18 dos.writeBoolean(true);19 dos.writeChar('中');20 dos.close();21 22 }23 }
DataInputStream 方法: writeInt() writeChar() 等8種讀入(讀)
1 import java.io.DataInputStream; 2 import java.io.FileInputStream; 3 import java.io.IOException; 4 import java.io.InputStream; 5 6 public class DataInDemo { 7 public static void main(String[] args) 8 throws IOException{ 9 10 String file = "data.dat";11 12 InputStream in = new FileInputStream(file);13 //DataInputStream 從基本流中讀取基本類型數據,實現基本14 //類型數據的反序列化15 DataInputStream dis = new DataInputStream(in);16 int b = dis.read();17 int i = dis.readInt();18 long l= dis.readLong();19 byte bx = dis.readByte();20 double d = dis.readDouble();21 short s = dis.readShort();22 float f = dis.readFloat();23 boolean bol = dis.readBoolean();24 char c = dis.readChar();25 dis.close();26 System.out.print( b +" ");//254 fe27 System.out.print(i+" ");28 System.out.print(l+" ");29 System.out.print(bx+" ");30 System.out.print(d+" ");31 System.out.print(s+" ");32 System.out.print(f+" ");33 System.out.print(bol+" ");34 System.out.print(c+" ");35 36 }37 }
5 字符串的序列化(文字的編碼方案) 從char序列到byte序列 的轉換,叫"編碼" 1) String 字符串本質上是Char 2)utf-16be 編碼-----將16位char從中間切開為2個byte utf -16be是將 unicode char[] 序列化為byte[]的編碼方案 能夠支持65535個字符編碼,英文浪費空間
如: char[] = ['A', 'B', '中'] 對應 0041,0042,4e2d
utf-8:國際標準,是將unicode編碼為byte序列的方案,采用變長編碼 1-N方案,其中英文1個byte,中文3個byte unicoded的" 中": 4e 2d = 01001110 00101101 utf-8的"中":e4 b8 ad =11100100 10111000 10101101 1110xxxx 10xxxxxx 10xxxxxx
以0開頭的是英文(0-127) 110表示連續2字節表示一個字符 1110表示連續3字節表示一個字符 每個數據字節以10開頭
GBK: 中國標準,支持20000+中日韓文,英文編碼1byte,中文2byte 與unicode不兼容,中文windows默認gbk
ISO8859-1:只支持255個英文字符,不支持中文(Sun服務器默認編碼,如tomcat等)
例子
1 import java.io.FileOutputStream; 2 import java.io.IOException; 3 import java.io.OutputStream; 4 5 public class CharIODemo { 6 public static void main(String[] args) 7 throws IOException{ 8 String str = "ABCD中國"; 9 System.out.println(str);10 //Java 的字符是16位 Unicode值,而文件是8位Byte序列11 12 //GBK13 System.out.println("GBK編碼方案,對字符編碼");14 String file = "gbk.txt";15 OutputStream out = new FileOutputStream(file);//默認GBK編碼方案16 byte[] gbk = str.getBytes("GBK");17 out.write(gbk);18 out.close();19 IOUtils.print(file);20 //UTF-16BE,每個編碼是2個字節21 System.out.println("UTF-16BE編碼方案,對字符編碼");22 file = "utf-16be.txt";23 out = new FileOutputStream(file);24 byte[] utf16be = str.getBytes("UTF-16BE");25 out.write(utf16be);26 out.close();27 IOUtils.print(file);28 29 //UTF-8,英文是1個字節,中文是3個字節30 System.out.println("UTF-8編碼方案,對字符編碼");31 file = "utf-8.txt";32 out = new FileOutputStream(file);33 byte[] utf8 = str.getBytes("UTF-8");//編碼string -> byte[]34 out.write(utf8);35 out.close();36 IOUtils.print(file);37 38 byte[] buf = IOUtils.read("utf-8.txt");39 //new String(buf,"UTF-8"),構造器可以將 byte編碼序列40 //解碼為 char序列(字符串)41 String s = new String(buf,"UTF-8");//解碼byte-> String42 System.out.println(s);43 }44 }
6 字符流IO(Reader Writer)1) 字符的處理,一次處理一個字符(unicode編碼)2) 字符的底層仍然是基本的字節流3) 字符流的基本實現 InputStreamReader 完成byte流解析為char流,按照編碼解析 OutputStreamWriter 提供char流到byte流,按照編碼處理4) 字符流的過濾器 是字符讀寫的功能擴展,極大的方便了文本的讀寫操作 BufferedReader : readLine() 一次讀取一行 PrintWriter : println() 一次打印一行5)讀取一個文本文件 InputStream is = new FileInputStream("test.txt"); Reader in = new InputStreamReader(is); BufferedReader reader = new BufferedReader(in); 或者 BufferedReader in = new BufferedReader(new FileReader(filename));
例子:
1 import java.io.BufferedInputStream; 2 import java.io.BufferedReader; 3 import java.io.FileInputStream; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 7 public class TestReaderDemo { 8 public static void main(String[] args) 9 throws IOException{10 //Scanner BufferedReader都是流的功能擴展,是過濾器11 // 不能單獨使用,最終需要依賴于基本byte流(in)12 //Scanner 提供了nextLine()方法//Java5以后13 //BufferedReader 提供了 readLine()方法,讀取一行14 //readLine()讀取到文件末尾返回null15 16 //逐行讀取文本文件,顯示到系統控制臺17 //工作中常用18 String file = "in.txt"; //為當前工作區workspace/項目名/in.txt19 BufferedReader in = new BufferedReader(20 new InputStreamReader(21 new BufferedInputStream(22 new FileInputStream(file)),"gbk"));23 String str;24 while((str = in.readLine()) != null){25 System.out.println(str);26 }27 in.close();28 }
6)寫出一個文本文件 PrintWriter out = new PrintWriter(new FileWriter(new FileOutputStream(filename))); 或者 PrintWriter out = new PrintWriter( new OutputStreamWriter( new FileOutputStream(filename)))例子
1 import java.io.IOException; 2 import java.io.PrintWriter; 3 import java.util.Scanner; 4 5 public class SyncWriteDemo { 6 public static void main(String[] args) 7 throws IOException{ 8 Scanner in = new Scanner(System.in); 9 String file = "sync.txt";10 PrintWriter out = new PrintWriter(file,"UTF-8");11 while(true){12 String str = in.nextLine();13 out.println(str);14 if("q".equalsIgnoreCase(str)){15 break;16 }17 }18 out.close();19 }20 }
7)系統的默認編碼,中文一般是GBK如何查看默認編碼?
String encoding = System.getProperty("file.encoding");
7 對象的IO序列化和深層復制
什么是對象序列化: 將對象Object轉換為byte序列,反之叫做對象的反序列華1)序列化流,是過濾流 ObjectOutputStream 方法 writeObject() 對象的序列化 ObjectInputStream 方法readObject() 對象的反序列化2)序列化接口(Serializable)
對象必須實現"序列化接口Serializable"才能進行序列化,否則將出現不能序列化的異常 Serializable是一個空的接口,沒有任何方法 ,僅作為序列化的一個標識
3)JavaBean 規范規定,Java類必須實現Serializable接口
Java API中的類大多是符合Java Bean規范的,基本都實現了Serializable
4) 對象的序列化可以變相實現對象的深層復制例子
1 import java.io.BufferedInputStream; 2 import java.io.BufferedOutputStream; 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 import java.io.ObjectInputStream; 6 import java.io.ObjectOutputStream; 7 import java.io.Serializable; 8 9 public class ObjectIODemo {10 public static void main(String[] args) 11 throws Exception{12 String file = "obj.dat";13 ObjectOutputStream out = new ObjectOutputStream(14 new BufferedOutputStream(15 new FileOutputStream(file)));16 Foo foo =new Foo();17 out.writeObject(foo);//將foo引用的對象,序列化到文件中18 out.close();19 20 //讀出21 ObjectInputStream in = new ObjectInputStream(22 new BufferedInputStream(23 new FileInputStream(file)));24 Foo foo1 = (Foo)in.readObject();//對象反序列化25 in.close();26 System.out.println(foo1.name);27 28 System.out.println("深層復制:對象被復制,對象屬性也被復制");29 System.out.println(foo==foo1);//false 對象復制了(一層)30 System.out.println(foo.name == foo1.name);//false ,屬性被復制了(二層)31 //利用序列化 和 反序列化 可以簡潔的實現 對象的深層復制32 }33 34 }35 class Foo implements Serializable{//Serializable沒有聲明方法36 String name = "Tom";37 }
淺層復制與深層復制1)java的默認規則是淺層復制,性能好,但隔離性差,如(clone(),Arrays.copyOf) 淺層復制 : 對象的引用不同,但對象中屬性的引用相同2)利用序列化可以實現深層復制 深層復制: 對象的引用不同,但對象中的屬性的引用也不相同例
1 import java.io.ByteArrayInputStream; 2 import java.io.ByteArrayOutputStream; 3 import java.io.ObjectInputStream; 4 import java.io.ObjectOutputStream; 5 6 public class DeepcopyDemo { 7 public static Object deepCope(Object obj){ 8 try{ 9 //1. 對象序列化10 // 緩沖流: 字節數組輸出流11 ByteArrayOutputStream buf =12 new ByteArrayOutputStream();13 //對象輸出流14 ObjectOutputStream out = 15 new ObjectOutputStream(16 new ByteArrayOutputStream());17 18 out.writeObject(obj);//序列化對象到buf中19 out.close();20 21 //2 .對象的反序列化22 byte[] ary = buf.toByteArray();23 ByteArrayInputStream bais = 24 new ByteArrayInputStream(ary);25 ObjectInputStream in = 26 new ObjectInputStream(bais);27 Object o = in.readObject();//從ary反序列化28 in.close();29 return o;30 31 }catch(Exception e){32 e.printStackTrace();33 throw new RuntimeException(e);34 }35 }36 }
以上用到的ByteArrayInputStream和ByteArrayOutputStream
下面有一個ByteArrayInputStream和ByteArrayOutputStream的例子
例子
1 import java.io.ByteArrayInputStream; 2 import java.io.ByteArrayOutputStream; 3 import java.io.IOException; 4 import java.util.Arrays; 5 6 import com.tarena.day18.IOUtils; 7 8 public class ByteArrayIODemo { 9 public static void main(String[] args) 10 throws IOException{11 byte[] ary = {1,-1,127,-128};12 // {00000001, 11111111, 01111111, 10000000}13 ByteArrayInputStream in = new ByteArrayInputStream(ary);14 int b = in.read();//1 00000000 00000000 00000000 0000000115 System.out.println(b);16 b = in.read();17 System.out.println(b);//255 00000000 00000000 00000000 1111111118 b = in.read(); 19 System.out.println(b);//127 00000000 00000000 00000000 0111111120 b = in.read();21 System.out.println(b);//128 00000000 00000000 00000000 1000000022 b = in.read();23 System.out.println(b);//-1 11111111 11111111 11111111 1111111124 in.close();25 26 ByteArrayOutputStream out = new ByteArrayOutputStream();//默認開辟32byte的數組作為輸出目標27 //如果滿了就自動擴容28 //out:[0,0,0,0,0,0,0,.....]29 //30 out.write(1);//[1,0,0,0,0,0,....]31 out.write(-2);//[1,fe,0,0,0,0,0,....]32 out.write(-1);//[1,fe,ff,0,0,0,0,....]33 out.close();34 byte[] buf = out.toByteArray();//復制有效部分35 IOUtils.print(buf);//[01, fe, ff ]36 }37 38 }39 40 41
新聞熱點
疑難解答