更新時間:2018-1-7 12:27:21
更多請查看在線文集:http://android.52fhy.com/java/index.html
java.io
包幾乎包含了所有操作輸入、輸出需要的類。所有這些流類代表了輸入源和輸出目標。
輸入輸出流
簡介
一個流被定義為一個數據序列。輸入流用於從源讀取數據,輸出流用於向目標寫數據。
下圖是一個描述輸入流和輸出流的類層次圖:
在java.io
包中操作文件內容的主要有兩大類:字節流、字符流,兩類都分為輸入和輸出操作。
在字節流中輸出數據主要是使用OutputStream
完成,輸入使的是InputStream
;在字符流中輸出主要是使用Writer
類完成,輸入流主要使用Reader
類完成。這四個都是抽象類。
java中提供了專用於輸入輸出功能的包java.io
, 其中包括:
InputStream
,OutputStream
,Reader
,Writer
。InputStream
和OutputStream
, 兩個是為字節流設計的,主要用來處理字節或二進制對象。Reader
和Writer
, 兩個是為字符流(1個字符占2個字節)設計的,主要用來處理字符或字符串。
常見的System.in
其實就是InputStream對象。
字節流轉換為字符流
為了方便處理字節流,我們經常會把字節流轉換為字符流。例如:
Java 的控制台輸入由 System.in
完成。為了獲得一個綁定到控制台的字符流,我們可以把 System.in
包裝在一個 BufferedReader
對象中來創建一個字符流。
下面是創建 BufferedReader
的基本語法:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
同理,從文件讀取:
InputStream f = new FileInputStream("C:/java/hello");
BufferedReader br = new BufferedReader(new InputStreamReader(f));
使用BufferedReader是為了使用緩沖功能。
java.io.BufferedReader
和java.io.BufferedWriter
類各擁有8192字符的緩沖區。當BufferedReader
在讀取文本文件時,會先盡量從文件中讀入字符數據並置入緩沖區,而之后若使用read()
方法,會先從緩沖區中進行讀取。如果緩沖區數據不足,才會再從文件中讀取,使用BufferedWriter
時,寫入的數據並不會先輸出到目的地,而是先存儲至緩沖區中。如果緩沖區中的數據滿了,才會一次對目的地進行寫出。
針對上面示例的三個類進行簡單說明:
InputStream
:是所有字節輸入流的超類,一般使用它的子類:FileInputStream
等,它能輸出字節流;InputStreamReader
:是字節流與字符流之間的橋梁,能將字節流輸出為字符流,並且能為字節流指定字符集,可輸出一個個的字符;BufferedReader
:提供通用的緩沖方式文本讀取,readLine()
讀取一個文本行,從字符輸入流中讀取文本,緩沖各個字符,從而提供字符、數組和行的高效讀取。
InputStream
提供的read()
方法支持從輸入流中讀取一個數據字節。常用原型:
public int read() throws IOException {}
從此輸入流中讀取一個數據字節。如果沒有輸入可用,則此方法將阻塞。
指定者:類 InputStream 中的 read
返回:下一個數據字節;如果已到達文件末尾,則返回 -1。
public int read(byte[] b) throws IOException{}
從此輸入流中將最多 b.length 個字節的數據讀入一個 byte 數組中。在某些輸入可用之前,此方法將阻塞。
覆蓋:類 InputStream 中的 read
參數:存儲讀取數據的緩沖區。
返回:讀入緩沖區的字節總數,如果因為已經到達文件末尾而沒有更多的數據,則返回 -1。
示例
示例1:從控制台讀取單字符輸入
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
char c;
System.out.println("輸入字符,按下 'q' 鍵退出:");
do {
c = (char) br.read();
System.out.println(c);
}while(c != 'q');
}
示例2:從控制台讀取多字符輸入
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String s;
System.out.println("輸入字符串,按下 'quit' 鍵退出:");
do {
s = br.readLine();
System.out.println(s);
}while(!s.equals("quit"));
}
示例3:使用 InputStream 中的 read讀取字節流
public static void main(String[] args) throws IOException{
InputStream input = System.in;
byte[] b = new byte[1024];
int len = 0;
StringBuffer sb = new StringBuffer("");
while ((len = input.read(b)) != 2) {
System.out.println(len);
sb.append(new String(b, 0, len));
}
input.close();
System.out.println(sb.toString());
}
其實該例子改成文件讀取會更好:
public static void main(String[] args) throws IOException{
InputStream input = new FileInputStream("src/test.txt");
byte[] b = new byte[1024];
int len = 0;
StringBuffer sb = new StringBuffer("");
while ((len = input.read(b)) > 0) {
System.out.println(len);
sb.append(new String(b, 0, len));
}
input.close();
System.out.println(sb.toString());
}
也可以使用一個文件對象來創建一個輸入流對象來讀取文件。我們首先得使用 File()
方法來創建一個文件對象:
File f = new File("src/test.txt");
InputStream input = new FileInputStream(f);
必須先在src目錄下建立文件test.txt
,內容: hello world
運行結果:
11
hello world
示例4:控制台輸出:
我們知道,控制台的輸出由 print()
和 println()
完成。這些方法都由類 PrintStream
定義,System.out
是該類對象的一個引用。
PrintStream
繼承了 OutputStream
類,並且實現了方法 write()
。這樣,write()
也可以用來往控制台寫操作。
但是write()
方法不經常使用,因為 print()
和 println()
方法用起來更為方便。
PrintStream
定義 write()
的最簡單格式如下所示:
void write(int byteval){}
該方法將 byteval
的低八位字節寫到流中。
public static void main(String[] args) {
System.out.write('h');
System.out.write('\n');
}
示例5:輸出內容到文件
public static void main(String[] args) throws IOException{
String str = "hello world";
// 構建FileOutputStream對象,文件不存在會自動新建
OutputStream out = new FileOutputStream("src/test2.txt");
out.write(str.getBytes());
out.close();
}
也可以使用一個文件對象來創建一個輸出流來寫文件。我們首先得使用File()
方法來創建一個文件對象:
File f = new File("src/test2.txt");
OutputStream out = new FileOutputStream(f);
運行后,打開src
目,就能看到test2.txt。
getBytes()
用於把字符串轉化為字節流(byte型)。方法原型:
public byte[] getBytes() {
return StringCoding.encode(value, 0, value.length);
}
public byte[] getBytes(Charset charset) {
if (charset == null) throw new NullPointerException();
return StringCoding.encode(charset, value, 0, value.length);
}
示例6:借助BufferedWriter輸出內容到文件
public static void main(String[] args) throws IOException{
String str = "hello";
// 構建FileOutputStream對象,文件不存在會自動新建
OutputStream out = new FileOutputStream("src/test3.txt");
BufferedWriter bWriter = new BufferedWriter(new OutputStreamWriter(out));
bWriter.write(str);
bWriter.close();//關閉緩沖區
}
我們還可以結合上述的BufferedReader進行從鍵盤輸入,保存到文件:
public static void main(String[] args) throws IOException{
String str = "";
// 構建FileOutputStream對象,文件不存在會自動新建
OutputStream out = new FileOutputStream("src/test3.txt");
BufferedWriter bWriter = new BufferedWriter(new OutputStreamWriter(out, "utf-8"));//構建OutputStreamWriter對象,參數可以指定編碼,默認為操作系統默認編碼,windows上是gbk
// bWriter.write(str);
//讀緩存區
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
do {
str = br.readLine();
bWriter.write(str);
System.out.println(str);
}while(!str.equals("quit"));
bWriter.close();//關閉緩沖區,同時會把緩沖區內容寫入文件
out.close();// 關閉輸出流,釋放系統資源
}
文件和I/O
主要有這些類:
- File 文件類。
- FileReader FileReader類從
InputStreamReader
類繼承而來。該類按字符讀取流中數據。 - FileWriter FileWriter 類從
OutputStreamWriter
類繼承而來。該類按字符向流中寫入數據。
File
類至少有一個參數。File
類方法:
mkdir()
方法創建一個文件夾,成功則返回true,失敗則返回false。
失敗表明File對象指定的路徑已經存在,或者由於整個路徑還不存在,該文件夾不能被創建。mkdirs()
創建指定的目錄,包括創建必需但不存在的父目錄。創建多級目錄使用該方法。isDirectory()
判斷是否是一個目錄。isFile()
判斷是否是一個標准文件。list()
提取包含的文件和文件夾的列表。delete()
方法同於刪除文件或空目錄。createNewFile() throws IOException
當且僅當不存在具有此抽象路徑名指定的名稱的文件時,原子地創建由此抽象路徑名指定的一個新的空文件。
示例1:目錄操作
public static void main(String[] args) throws IOException {
String dirname = "src/tmp";
File file = new File(dirname);
//創建目錄
if(!file.isDirectory()) {
if(file.mkdirs()) {
System.out.println("succ mkdirs");
}
}
//創建文件
File file2 = new File(dirname + "/test.txt");
file2.createNewFile();//目錄必須存在
File file3 = new File(dirname + "/test/");
file3.mkdir();
//列出目錄
if(file.isDirectory()) {
String[] lists = file.list();
for (int i = 0; i < lists.length; i++) {
File f = new File(dirname + "/" + lists[i]);
if(f.isDirectory()) {
System.out.println("[d]"+ lists[i]);
}else {
System.out.println("[f]"+ lists[i]);
}
}
}else {
System.out.println(dirname + " 不是一個目錄");
}
//刪除文件或目錄
if(file3.delete()) {
System.out.println("刪除成功");
}
}
運行結果:
[d]test
[f]test.txt
刪除成功
示例2:
public static void main(String[] args) throws IOException {
String filename = "src/tmp/test.txt";
File file = new File(filename);
file.createNewFile();// 創建文件
FileWriter fWriter = new FileWriter(file);//創建FileWriter對象
fWriter.write('i');
fWriter.write(' ');
char[] cs = {'l', 'o', 'v', 'e', ' '};
fWriter.write(cs);
fWriter.write("java");
fWriter.flush();//將輸入流和輸出流中的緩沖進行刷新,使緩沖區中的元素即時做輸入和輸出,而不必等緩沖區滿
fWriter.close();//關閉FileWriter對象
//讀取文件
FileReader fReader = new FileReader(file);
char[] cs2 = new char[15];
fReader.read(cs2);//這里因為知道長度不會大於15,所以沒有用while循環讀取
for(char c : cs2) {//遍歷輸出
System.out.print(c);
}
fReader.close();
運行結果:
i love java
參考
1、Java 流(Stream)、文件(File)和IO | 菜鳥教程
http://www.runoob.com/java/java-files-io.html
2、java中char和byte的轉換 - CSDN博客
http://blog.csdn.net/feixiazhitian/article/details/49511963
3、字節流與字符流的區別及相互轉換 - 傑-維斯布魯克 - 博客園
https://www.cnblogs.com/sjjsh/p/5269781.html
4、Java中,BufferedReader類的介紹及作用 - CSDN博客
http://blog.csdn.net/wiebin36/article/details/51912794