1,概述java
Java IO是Java用來讀寫數據(輸入和輸出)的API。這裏主要介紹如下幾點內容:c++
Java流式輸入/輸出
Java流類的分類 輸入/輸出流類 常見的節點流和處理流 文件流 緩衝流 數據流 轉換流 Print流 Object流
2,Java流式輸入和輸出數組
在Java程序中,對於數據的輸入輸出操做以"流"(Stream)方式進行;J2SDK提供了各類各樣的"流"類,用以獲取不一樣種類的數據;程序中經過標準的方法輸入或輸出數據。各種用途彙總以下:緩存
3,Java流的分類網絡
java.io包中定義了多個流類型(類或抽象類)來實現輸入/輸出功能。能夠從不一樣的角度對其進行分類:app
輸入和輸出:四個抽象類(凡是Stream結尾的否是字節流)dom
字節流 | 字符流 | |
輸入流 | InputStream | Reader |
輸出流 | OutputStream | Writer |
節點流和處理流:編碼
節點流爲能夠從一個特定的數據源(節點)讀寫數據(好比:文件,內存)spa
處理流是「鏈接」在已經存在的流(節點流或處理流)之上,經過對數據的處理爲程序提供更爲強大的讀寫功能:線程
4,InputStream & OutputStream,Reader & Writer
4.1,InputStream
繼承自InputStream的流都是用於向程序中輸入數據,且數據的單位爲字節(byte,8bits),下圖中深色爲節點流,淺色爲處理流。
InputStream的基本方法:
//讀取一個字節並以整數的形式返回(0~255) //若是返回-1表示已到輸入流的末尾
int read() throws IOException //讀取一系列字節並存儲到一個數組buffer //返回實際讀取的字節數,若是讀取前已到輸入流的末尾返回-1
int read(byte[] buffer) throws IOException //讀取length個字節 //並存儲到一個字節數組buffer,從length位置開始 //返回實際讀取的字節數,若是讀取前已到輸入流的末尾返回-1
int read(byte[] buffer, int offset, int length) throws IOException //關閉流釋放內存資源
void close() throws IOException //跳過n個字節不讀,返回實際跳過的字節數
long skip(long n) throws IOException
4.2,OutputStream
繼承自OutputStream的流是用於從程序中輸出數據,切數據的單位是字節(byte,8bits),下圖中深色爲節點流,淺色爲處理流。
OutputStream的基本方法:
//向輸出流中寫入一個字節數據,該字節數據位參數b的低8位
void write(int b) throws IOException //將一個字節類型的數組中的數據寫入輸出流
void writer(byte[] b) throws IOException //將一個字節類型的數組中的數據從指定位置(off)開始len個字節寫入到輸出流
void write(byte[] b, int off, int len) throws IOException //關閉流釋放內存資源
void close() throws IOException //將輸出流中緩衝的數據所有寫出到目的地
void flush() throws IOException
4.3,Reader
繼承自Reader的流都是用於向程序中輸入數據,且數據的單位是字符(16bits,例如一箇中文是兩個字節表示);下圖中深色爲節點流,淺色爲處理流:
Reader的基本方法
//讀取一個字符並以整數的形式返回(0~255) //若是返回-1表示已到輸入流的末尾
int read() throws IOException //讀取一系列字符並存儲到一個數組buffer //返回實際讀取的字符數,若是讀取前已到輸入流的末尾返回-1表示已到輸入流的末尾
int read(char[] cbuf) throws IOException //讀取length個字符 //並存儲到一個數組buffer,從length位置開始 //返回實際讀取的字符數,若是讀取前已到輸入流的末尾返回-1表示已到輸入流的末尾
int read(char[] cbuf, int offset, int length) throws IOException //關閉流釋放內存資源
void close() throws IOException //跳過n個字符不讀,返回實際跳過的字節數
long skip(long n) throws IOException
4.4,Writer
繼承自Writer的流都是用於程序中輸出數據,且數據的單位爲字符(16bits);下圖中深色爲節點流,淺色爲處理流:
Writer基本方法:
//向輸出流中寫入一個字符數據,該字符數據爲參數c的低16位
void write(int c) throws IOException //將一個字符類型的數組中的數據寫入輸出流
void writer(char[] cbuf) throws IOException //將一個字符類型的數組中的數據從指定位置(offset)開始len個字節寫入到輸出流
void write(char[] cbuf, int offset, int len) throws IOException //將一個字符串中的字符寫入到輸出流
void write(String string) throws IOException //將一個字符串從offset開始的length個字符寫入到輸出流
void write(String string, int offset, int length) throws IOException //關閉流釋放內存資源
void close() throws IOException //將輸出流中緩衝的數據所有寫出到目的地
void flush() throws IOException
5,經常使用的節點流和處理流
5.1,節點流類型
類型 | 字符流 | 字節流 |
File(文件) | FileReader FileWriter |
FileInputStream FileOutputStream |
Memory Array | CharArrayReader CharArrayWriter |
ByteArrayInputStream ByteArrayOutputStream |
Memory String | StringReader StringWriter |
--- |
Pipe(管道,線程) | PipedReader PipedWriter |
PipedInputStream PipedOutputStream |
5.1.1,File(訪問文件)
FileInputStream和FileOutputStream分別繼承自OutputStream和OutputStream,用於向文件中輸入和輸出字節。
FileInputStream和FileOutputStream的構造方法:
FileInputStream: FileInputStream(File file) Creates a FileInputStream by opening a connection to an actual file, the file named by the File object file in the file system. FileInputStream(FileDescriptor fdObj) Creates a FileInputStream by using the file descriptor fdObj, which represents an existing connection to an actual file in the file system. FileInputStream(String name) Creates a FileInputStream by opening a connection to an actual file, the file named by the path name name in the file system. OutputStream: FileOutputStream(File file) Creates a file output stream to write to the file represented by the specified File object. FileOutputStream(File file, boolean append) Creates a file output stream to write to the file represented by the specified File object. FileOutputStream(FileDescriptor fdObj) Creates a file output stream to write to the specified file descriptor, which represents an existing connection to an actual file in the file system. FileOutputStream(String name) Creates a file output stream to write to the file with the specified name. FileOutputStream(String name, boolean append) Creates a file output stream to write to the file with the specified name.
FileInputStream和FileOutputStream類支持其父類InputStream和OutputStream所提供的數據讀寫方法。
注意:
在實例化FileInputStream和FileOutputStream時要用ty-catch語句加以處理,由於可能拋出FileNotFoundException。
在讀寫數據時也要用try-catch語句加以處理,由於可能拋出IOException。
例子:
1,FileInputStream & FileOutputStream
FileInputStream:
public static void main(String[] args) { int b = 0; FileInputStream fis = null; try { fis = new FileInputStream("d:\\share\\java\\io\\TestFileInputStream.java"); } catch (FileNotFoundException e) { System.out.println("找不到指定文件"); System.exit(-1); } try { long num = 0; while((b = fis.read()) != -1) { System.out.print((char)b); num++; } fis.close(); System.out.println("共讀取了" + num + "個字節"); } catch (IOException e) { System.out.println("文件讀取錯誤"); System.exit(-1); } }
結果:對於中文亂碼,由於是一個字節一個字節的讀取,因此只讀取了半個中文
控制檯輸出: import java.io.*; public class TestFileInputStream { public static void main(String[] args) { int b = 0; FileInputStream in = null; try { in = new FileInputStream("d:\\share\\java\\io\\TestFileInputStream.java"); } catch (FileNotFoundException e) { System.out.println("ÕÒ²»µ½Ö¸¶¨Îļþ"); System.exit(-1); } try { long num = 0; while((b=in.read())!=-1){ System.out.print((char)b); num++; } in.close(); System.out.println(); System.out.println("¹²¶ÁÈ¡ÁË "+num+" ¸ö×Ö½Ú"); } catch (IOException e1) { System.out.println("Îļþ¶ÁÈ¡´íÎó"); System.exit(-1); } } }共讀取了700個字節
FileOutputStream:
public static void main(String[] args) { int b = 0; FileInputStream fis = null; FileOutputStream fos = null; try { fis = new FileInputStream("d:/share/java/HelloWorld.java"); fos = new FileOutputStream("d:/share/java/io/HW.java");//沒有回自動新建一個文件
while ((b = fis.read()) != -1) { fos.write(b); } fis.close(); fos.close(); } catch (FileNotFoundException e) { System.out.println("找不到指定的文件"); System.exit(-1); } catch (IOException e) { System.out.println("文件複製錯誤"); System.exit(-1); } System.out.println("文件已複製"); }
輸出:能夠在d:/share/java/io中看到複製的文件HW.java
2,FileReader & FileWriter
FileReader:
public static void main(String[] args) { int c = 0; FileReader fr = null; try { fr = new FileReader("d:\\share\\java\\io\\TestFileReader.java"); while((c = fr.read()) != -1) { System.out.print((char)c); } fr.close(); } catch (FileNotFoundException e) { System.out.println("找不到指定文件"); } catch (IOException e) { System.out.println("讀取文件出錯"); } }
FileWriter:
例一:
public static void main(String[] args) { FileWriter fw = null; try { fw = new FileWriter(new File("d:\\unicode.dat")); for(int i = 0; i <= 50000; i++) {//char最大爲65535
fw.write(i); } fw.close(); } catch (IOException e) { e.printStackTrace(); System.out.println("文件寫入錯誤"); System.exit(-1); } }
結果:D盤中的unicode.dat文件中的內容。
例二:
public static void main(String[] args) throws Exception { FileReader fr = new FileReader("d:/java/io/TestFileWriter2.java"); FileWriter fw = new FileWriter("d:/java/io/TestFileWriter2.bak"); int b; while((b = fr.read()) != -1) { fw.write(b); } fr.close(); fw.close(); }
5.2,處理流
處理流須要套接在節點流和其餘處理流之上使用
處理類型 | 字符流 | 字節流 |
Buffering | BufferReader BufferWriter |
BufferedInputStream BufferedOutputStream |
Converting between bytes and character |
InputStreamReader OutputStreamWriter |
|
Object Serialization | --- | ObjectInputStream ObjectOutputstream |
Data Conversion | --- | DataInputStream DataOutputStream |
Counting | LineNumberReader | LineNumberInputStream |
Peeking ahead | PushbackReader | PushbackInputStream |
Printing | PrintWriter | PrintStream |
5.2.1,緩衝流
緩衝流要「套接」在相應的節點流之上,對讀寫的數據提供了緩衝的功能,提升了讀寫的效率,同時增長了一些新的方法。
J2SDK提供了四種緩衝流,其經常使用的構造方法:
BufferedReader BufferedReader(Reader in) Creates a buffering character-input stream that uses a default-sized input buffer. BufferedReader(Reader in, int sz) Creates a buffering character-input stream that uses an input buffer of the specified size. BufferedWriter BufferedWriter(Writer out) Creates a buffered character-output stream that uses a default-sized output buffer. BufferedWriter(Writer out, int sz) Creates a new buffered character-output stream that uses an output buffer of the given size. BufferedInputStream BufferedInputStream(InputStream in) Creates a BufferedInputStream and saves its argument, the input stream in, for later use. BufferedInputStream(InputStream in, int size) Creates a BufferedInputStream with the specified buffer size, and saves its argument, the input stream in, for later use. BufferedOutputStream BufferedOutputStream(OutputStream out) Creates a new buffered output stream to write data to the specified underlying output stream. BufferedOutputStream(OutputStream out, int size) Creates a new buffered output stream to write data to the specified underlying output stream with the specified buffer size.
緩衝輸入流支持其父類的mark和reset方法
BufferedReader提供了readLine方法用於讀取一行字符串(以\r或\n分隔)
BufferedWriter提供了newLine方法用於寫入一個行分隔符
對於輸出的緩衝流,寫出的數據會先在內存中緩存,使用flush方法將會使內存中的數據馬上寫出。
例一:
public static void main(String[] args) { try { FileInputStream fis = new FileInputStream("d:\\share\\java\\HelloWorld.java"); BufferedInputStream bis = new BufferedInputStream(fis); int c = 0; System.out.println(bis.read()); System.out.println(bis.read()); bis.mark(100); for(int i = 0; i <= 10 && (c=bis.read()) != -1; i++) { System.out.print((char)c + " "); } System.out.println(); bis.reset(); for(int i = 0; i <= 10 && (c=bis.read()) != -1; i++) { System.out.print((char)c + " "); } bis.close(); } catch (IOException e) { e.printStackTrace(); } }
輸出:
47
42 a l ; s k j d f ; a l ; s k j d f ;
例二:
public static void main(String[] args) { try { BufferedWriter bw = new BufferedWriter(new FileWriter("d:\\dat2.txt")); BufferedReader br = new BufferedReader(new FileReader("d:\\dat2.txt")); String s = null; for(int i = 1; i<=100; i++) { s = String.valueOf(Math.random()); bw.write(s); bw.newLine(); } bw.flush(); while((s = br.readLine()) != null) {//讀一行
System.out.println(s); } bw.close(); br.close(); } catch (IOException e) { e.printStackTrace(); } }
輸出:
dat2.txt文件:
控制檯輸出:
5.2.2,轉換流
InputStreamReader和OutputStreamWriter用於字節數據到字符數據之間的轉換。
InputStreamReader須要和InputStream套接(把InputStream轉換成InputStreamReader)
OutputStreamWriter須要和OutputStream套接(把OutputStreamWriter轉換成OutputStream)
轉換流在構造時能夠指定其編碼集合,例如:
InputStream is = new InputStreamReader(System.in, "IOS8859_1");
例一:
public static void main(String[] args) { try { OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d:\\bak\\char.txt")); osw.write("miscalkjsdlasjdlajslkdalksd"); System.out.println(osw.getEncoding()); osw.close(); osw = new OutputStreamWriter(new FileOutputStream("d:\\bak\\char.txt", true), "ISO8859_1");//true,追加
osw.write("sadasdasdasdasd"); System.out.println(osw.getEncoding()); osw.close(); } catch (Exception e) { e.printStackTrace(); } }
結果:
UTF8//系統默認的編碼
ISO8859_1
例二:
public static void main(String[] args) { try { InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(isr); String s = null; s = br.readLine(); while(s != null) { if("exit".equalsIgnoreCase(s)) break; System.out.println(s.toUpperCase()); s = br.readLine(); } br.close(); } catch (Exception e) { e.printStackTrace(); } }
輸出:
add111
ADD111
exit
5.2.3,數據流
DataInputStream 和DataOutputStream分別繼承自InputStream 和 OutputStream,它屬於處理流,須要分別套接在InputStream 和 OutputStream類型的節點流上。
DataInputStream 和DataOutputStream提供了能夠存取與機器無關的Java原始類型數據(如:int,double等)的方法。
DataInputStream 和DataOutputStream的構造方法:
DataInputStream(InputStream in) Creates a DataInputStream that uses the specified underlying InputStream. DataOutputStream(OutputStream out) Creates a new data output stream to write data to the specified underlying output stream.
ByteArrayInputStream 和 ByteArrayOutputStream
例子:
public static void main(String[] args) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream();//在內存中分配了一個字節數組
DataOutputStream dos = new DataOutputStream(baos); dos.writeDouble(Math.random()); dos.writeBoolean(true); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); System.out.println(bais.available()); DataInputStream dis = new DataInputStream(bais); System.out.println(dis.readDouble()); System.out.println(dis.readBoolean()); dos.close(); dis.close(); } catch (Exception e) { e.printStackTrace(); } }
結果:
9
0.5620896958440097
true
5.2.4,Print流
Print流(只有輸出流沒有輸入流)
PrintWriter和PrintStream都屬於輸出流,分別針對於字符和字節
PrintWriter和PrintStream提供了重載的print方法
Println方法用於多種數據類型的輸出
PrintWriter和PrintStream的輸出操做不會拋出異常,用戶經過檢測錯誤狀態獲取錯誤信息
PrintWriter和PrintStream有自動flush方法
構造方法:
PrintWriter(File file) Creates a new PrintWriter, without automatic line flushing, with the specified file. PrintWriter(File file, String csn) Creates a new PrintWriter, without automatic line flushing, with the specified file and charset. PrintWriter(OutputStream out) Creates a new PrintWriter, without automatic line flushing, from an existing OutputStream. PrintWriter(OutputStream out, boolean autoFlush) Creates a new PrintWriter from an existing OutputStream. PrintWriter(String fileName) Creates a new PrintWriter, without automatic line flushing, with the specified file name. PrintWriter(String fileName, String csn) Creates a new PrintWriter, without automatic line flushing, with the specified file name and charset. PrintWriter(Writer out) Creates a new PrintWriter, without automatic line flushing. PrintWriter(Writer out, boolean autoFlush) Creates a new PrintWriter. PrintStream(File file) Creates a new print stream, without automatic line flushing, with the specified file. PrintStream(File file, String csn) Creates a new print stream, without automatic line flushing, with the specified file and charset. PrintStream(OutputStream out) Creates a new print stream. PrintStream(OutputStream out, boolean autoFlush) Creates a new print stream. PrintStream(OutputStream out, boolean autoFlush, String encoding) Creates a new print stream. PrintStream(String fileName) Creates a new print stream, without automatic line flushing, with the specified file name. PrintStream(String fileName, String csn) Creates a new print stream, without automatic line flushing, with the specified file name and charset.
例一:
public static void main(String[] args) { try { PrintStream ps = null; FileOutputStream fos = new FileOutputStream("d:\\bak\\log.dat"); ps = new PrintStream(fos); if(ps != null) { System.setOut(ps);//把ps設置成System.out.println();再也不輸出在控制檯了
} int ln = 0; for(char c = 0; c <= 60000; c++) { System.out.print(c + ""); if( ln++ >= 100) { System.out.println(); ln = 0; } } } catch (Exception e) { e.printStackTrace(); } }
結果:d:\\bak\\log.dat,log.data文件
例二:
public static void main(String[] args) { try { PrintStream ps = System.out; BufferedReader br = new BufferedReader(new FileReader("d:\\bak\\log.dat")); String s = null; while((s = br.readLine()) != null) { ps.println(s); } br.close(); } catch (IOException e) { e.printStackTrace(); } }
結果:
例三:
public static void main(String[] args) { try { String s = null; BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); FileWriter fw = new FileWriter("d:\\bak\\logfile.log", true);//日誌
PrintWriter pw = new PrintWriter(fw); while ((s = br.readLine()) != null) { if("exit".equalsIgnoreCase(s)) break; System.out.println(s.toUpperCase()); pw.println("--------"); pw.println(s.toUpperCase()); pw.flush(); } pw.println("=====" + new Date() + "======"); pw.flush(); pw.close(); } catch (IOException e) { e.printStackTrace(); } }
結果:
控制檯: 12121212121 adasdasdasdasd ADASDASDASDASD exit
文件:d:\\bak\\logfile.log,logfile.log文件
5.2.5,Object流
直接將Object寫入或寫出
transient關鍵字
serializable接口
externalizable接口
例一:
public class Test { public static void main(String[] args) { try { T t = new T(); t.k = 18; FileOutputStream fos = new FileOutputStream("d:/bak/testobjectio.dat"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(t); oos.flush(); oos.close(); FileInputStream fis = new FileInputStream("d:/bak/testobjectio.dat"); ObjectInputStream ois = new ObjectInputStream(fis); T t2 = (T) ois.readObject(); System.out.println(t2.i + "//" + t2.j + "//" + t2.d + "//" + t2.k); } catch (Exception e) { e.printStackTrace(); } } } class T implements Serializable { int i = 10; int j = 9; double d = 2.3; int k = 15; }
結果:
10//9//2.3//18
例二:
用transient修飾變量k
class T implements Serializable { int i = 10; int j = 9; double d = 2.3; transient int k = 15; }
結果:
10//9//2.3//0
transient修飾的變量k不會被寫入進去,因此取出來的k爲空,爲默認值0