輸入輸出的重要性:
輸入和輸出功能是Java對程序處理數據能力的提高,Java以流的形式處理數據。流是一組有序的數據序列,根據操作的類型,分為輸入流和輸出流。
程序從輸入流讀取數據,向輸出流寫入數據。Java是面向對象的程序語言,每一個數據流都是一個對象,它們提供了各種支持“讀入”與“寫入”操作的流類。
Java的輸入輸出功能來自java.io 包中的InputStream類、OutputStream類、Reader類和Writer類以及繼承它們的各種子類。
(一)解析文件處理的奧秘
1、學習使用文件類 : File類
File類用於封裝系統的文件和目錄的相關信息。在該類中定義了一些與平台無關的方法來操作文件。例如文件的大小、修改時間、文件路徑等。
創建 File 對象可以通過下面3種方式:
方法1: 方法2: 方法3:
new File(String pathName) File file = new File(“E://1.txt”) new File(String parent , String child)
parent :父抽象路徑名;child:子路徑名字符串
2、如何獲取文件信息
File 類是對文件和文件夾的抽象,包含了對文件和文件夾的多種屬性和操作方法。File類的常用方法如下表:
返回 方法 說明
String getName 獲取文件名稱
String getParent 獲取文件的父路徑字符串
String getPath 獲取文件的相對路徑字符串
String getAbsolutePath 獲取文件的絕對路徑字符串
boolean exists 判斷文件或者文件夾是否存在
boolean isFile 判斷是不是文件類型
boolean isDirectory 判斷是不是文件夾類型
boolean delete 刪除文件或文件夾,如果刪除成功返回結果為true
boolean mkdir 創建文件夾,創建成功返回true
boolean setReadOnly 設置文件或文件夾的只讀屬性
long length 獲取文件的長度
long lastModified 獲取文件的最后修改時間
String[ ] list 獲取文件夾中的文件和子文件夾的名稱,並存放到字符串數組中
下面通過實例介紹File類獲取文件信息
package com.zch.io;
import java.io.File;
import java.util.Date;
/**
* 在src根目錄下創建FileInfo類,在該類的主方法中創建文件對象,通過File類的相關方法,獲取文件的相關信息
*
* @author zch
*
*/
public class FileInfo {
public static void main(String[] args) {
String filePath = "src/com/zch/io/FileInfo.java";
// 根據指定路徑創建文件對象
File file = new File(filePath);
System.out.println("文件名稱:" + file.getName());
System.out.println("文件是否存在:" + file.exists());
System.out.println("文件的相對路徑:" + file.getPath());
System.out.println("文件的絕對路徑:" + file.getAbsolutePath());
System.out.println("是否為可執行文件:" + file.canExecute());
System.out.println("文件可以讀取:" + file.canRead());
System.out.println("文件可以寫入:" + file.canWrite());
System.out.println("文件上級路徑:" + file.getParent());
System.out.println("文件大小:" + file.length() + "B");
System.out.println("文件最后修改時間:" + new Date(file.lastModified()));
System.out.println("是否文件類型:" + file.isFile());
System.out.println("是否為文件夾:" + file.isDirectory());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
運行結果如下:
文件名稱:FileInfo.java
文件是否存在:true
文件的相對路徑:src\com\zch\io\FileInfo.java
文件的絕對路徑:D:\Java\IO\src\com\zch\io\FileInfo.java
是否為可執行文件:true
文件可以讀取:true
文件可以寫入:true
文件上級路徑:src\com\zch\io
文件大小:1195B
文件最后修改時間:Sat Sep 09 21:30:10 CST 2017
是否文件類型:true
是否為文件夾:false
1
2
3
4
5
6
7
8
9
10
11
12
在使用delete()方法刪除File對象時,如果刪除的對象是目錄,該目錄中的內容必須為空。
(二)使用字節輸入輸出流
字節流用於處理二進制數據的讀取和寫入,它以字節為單位,InputStream類和OutputStream類是字節流的抽象類,它們定義了數據流讀取和寫入的基本方法。各個子類會依其特點實現或覆蓋這些方法。
1、字節數入流抽象類InputStream
InputStream 類是字節輸入流的抽象類,定義了操作輸入流的各種方法,這些方法如表:
返回 方法 說明
int available() 返回當前輸入流的數據讀取方法可以讀取的有效字節數量
Abstract int read() 從當前數據流中讀取一個字節。若已達到流結尾,則返回-1
int read(byte[ ] bytes) 從當前輸入流讀取一定的byte數據,並存取在數組中,然后返回讀取的byte數據的數量,若已到達流結尾,則返回-1。
void reset() 將當前的輸入流重新定位到最后一次調用mark()方法時的位置
void mark(int readlimit) 在當前輸入流中做標記位置,當調用reset()方法時將返回到該位置,從標記位置開始,到再讀入readlimit個字符為止,這個標記都維持有效。
Boolean markSupported() 測試當前輸入流是否支持mark()和reset()方法,只要其中一個不支持,則返回false
long skip(long n) 跳過和丟棄當前輸入的n個字節數據
void close() 關閉當前輸入流,並釋放任何與之相關聯的系統資源
InputStream 類是抽象類,不能通過new關鍵字來創建該實例對象,需要其子類創建該實例對象。下面通過實例如何使用InputStream從控制台獲取用戶輸入的數據信息。
package com.zch.io;
import java.io.IOException;
import java.io.InputStream;
/**
* 創建InputStream實例inp,並將其賦值為System類的in屬性,定義為控制台輸入流,從inp輸入流中獲取字節信息,
* 用這些字節信息創建字符串,並將其在控制台上輸出。
* @author zch
*
*/
public class InputMessage {
public static void main(String[] args) {
InputStream inp = System.in;
byte[] bytes = new byte[1024];
try {
while(inp.read() != -1){
//根據用戶輸入的信息創建字符串
String str = new String(bytes).trim();
}
inp.close(); //關閉流
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2、字節輸出流抽象類OutputStream類
OutputStream定義了輸出流的各種方法,如下表:
返回 方法 說明
void write(byte[ ] b) 將byte[ ] 數組中的數據寫入當前輸出流
void write(byte[] b ,int off, int len) 將byte[ ]數組下標off開始的len長度的數據寫入當前輸出流
Abstract void write(int b) 寫入一個byte數據到當前輸出流
void flush() 刷新當前輸出流,並強制寫入所有緩沖的字節數據
void close() 關閉當前輸出流
和InputStream類一樣,OutputStream 類是抽象類,不能通過new關鍵字來創建該實例對象,需要其子類創建該實例對象。
package com.zch.io;
import java.io.IOException;
import java.io.OutputStream;
/**
* 創建OutputStream實例out,並將其賦值為System.out標准輸出流。通過write()方法向流寫入數據。
* @author zch
*
*/
public class OutputData {
public static void main(String[] args) {
OutputStream output = System.out; //實例化OutputStream對象
byte[] bytes = "使用OutputStream輸出流在控制台輸出字符串\n".getBytes(); //創建bytes數組
try {
output.write(bytes);
bytes = "輸出內容:\n".getBytes();
output.write(bytes); //向流中寫入數據
bytes = "Java數據交互管道——IO流 \n".getBytes();
output.write(bytes);
output.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
輸出結果如下:
使用OutputStream輸出流在控制台輸出字符串
輸出內容:
Java數據交互管道——IO流
1
2
3
4
3、文件字節輸入流類 : FileInputStream類
文件字節輸入流可以從指定路徑的文件中讀取字節數據。文件字節輸入流類繼承InputStream類,並實現了讀取輸入流的各種方法。
創建文件字節輸入流創建的構造方法語法如下:
語法1:以File對象為參數創建FileInputStream實例
new FileInputStream(File file)
1
語法2:以文件對象的絕對路徑為參數創建FIleInputStream實例
new FileInputStream(String filepath)
1
4、文件字節輸出流類:FileOutputStream
文件字節輸出流關聯指定文件路徑的文件,數據通過文件字節輸出流以字節為單位輸出並保存到文件中。文件字節輸出流繼承自OutputStream類,並實現OutputStream類的各種方法。
文件字節輸出流的構造方法語法如下:
語法1:以File對象為參數創建FileOutputStream實例
new FileOutputStream(File file)
1
語法2:以文件對象的絕對路徑為參數創建FIleOutputStream實例
new FileOutputStream(String filepath)
1
2
下面通過實例介紹文件的寫入和讀取:
package com.zch.io;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 創建OutputStream實例out,並將其賦值為System.out標准輸出流,通過write方法向流中寫入數據
*
* @author zch
*
*/
public class FileCreate {
public static void main(String[] args) {
File file = new File("D:/", "word.txt"); //創建文件對象
try {
if (!file.exists()) { //如果文件不存在則新建文件
file.createNewFile();
}
FileOutputStream output = new FileOutputStream(file);
byte[] bytes = "Java數據交流管道——IO流".getBytes();
output.write(bytes); //將數組的信息寫入文件中
output.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
FileInputStream input = new FileInputStream(file);
byte[] bytes2 = new byte[1024];
int len = input.read(bytes2);
System.out.println("文件中的信息是:" + new String(bytes2, 0, len));
input.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
(三) 使用字符輸入輸出流
字符輸入輸出流 與 字節輸入輸出流有相同的功能,但傳送數據的方式不一樣,字節流以字節為單位傳送數據,可以使任何類型的數據,例如文本、音頻、視頻、圖片等。字符流以字符為單位傳送數據,只能傳送文本類型的數據。使用字符輸入輸出流的好處是,當讀取中文時不會出現亂碼問題,而使用字節輸入輸出流時,卻不能保證這一點。
1、字符輸入流抽象類:Reader類
該類定義了操作字符輸入流的方法,如下表:
返回 方法 說明
boolean ready() 判斷此數據流是否准備好
int read() 讀入一個字符,若已讀到流結尾,則返回值為-1
int read(char[ ]) 讀取一些字符到char[ ]數組內,並返回所讀入的字符的數量,若已到達流結尾,則返回-1
Abscract int read(char[ ] chars,int off,int len) 讀取一些字符到char[ ]數組下標從off開始到off+len的位置,並返回所讀入的字符的數量,若已到達流結尾,則返回-1;
void reset() 將當前輸入流重新定位到最后一次mark()方法時的位置
void mark(int readLimit) 將當前輸入流中做標記,當調用reset方法時將返回到該位置,從標記位置開始,到再讀入readLimit個字符為止,這個標記都維持有效
boolean markSupported 測試當前輸入流是否支持mark()方法和reset()方法。只要有一個方法不支持,則返回-1
long skip(long n) 跳過參數n指定的字符數量,並返回所跳過字符的數量
Abstract void close() 關閉字符輸入流,並釋放與之關聯的所有資源
2、字符輸出流類Writer類
Writer 類主要是用於解決字符輸入流的類,其地位與Reader類在輸入流的地位和作用是相同的,也是所有字符輸出流的流類。
Writer類的主要方法如下:
返回 方法 說明
void write(char[ ] cbuf) 將字符數組的數據寫入字符輸出流
Abstract void write(char[ ] cbuf int off ,int len) 將字符數組從下標off 開始向輸入流寫入長度為len的數據
void write(int c ) 向字符輸入流中寫入一個字符數據
void write(String str ) 向輸入流中寫入一個字符串數據
void write(String str , int off ,int len) 向輸入流中寫入一個字符串從off 開始長度為len的數據
Abstract void flush() 刷新當前輸出流,並強制寫入所有緩沖區的字節數據
void close() 向輸出流中寫入緩沖區的數據,然后關閉當前輸出流,釋放所有與當前輸出流相關聯的系統資源
3、文件字符輸入流FileReader
文件字符輸入流與文件字節輸入流的功能相似,但是傳送數據的方式不一樣,字節流以字節為單位傳送數據,可以使文本、視頻、音頻、圖片等。字符流以字符為單位傳送數據,只能傳送文本類型的數據。
創建字符輸入流常用的構造方法:
語法1:
new FileReader(File file);
1
2
語法2:
new FileReader(String path);
1
2
下面通過實例介紹FileReader類讀取指定磁盤文件的內容。
package com.zch.io;
import java.io.File;
import java.io.FileReader;
public class FileInAndOut {
public static void main(String[] args) {
//定義指定磁盤的文件的File對象
File file = new File("D://word.txt");
if(! file.exists()){
System.out.println("對不起,不包含指定路徑的文件");
}else{
//根據指定路徑的File對象創建FileReader對象
try {
FileReader fr = new FileReader(file);
char[] data = new char[23]; //定義char數組
int length = 0;
while((length = fr.read(data))>0){ //循環讀取文件中的數據
String str = new String(data,0,length); //根據讀取文件的內容創建String 對象
System.out.println(str); //輸出讀取內容
}
fr.close(); //關閉流
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
運行結果如下圖:
4、文件字符輸出流FileWriter
文件字符輸出流繼承自Writer類,提供了向文件輸出的各種方法,數據通過文件字符輸出流以字符為單位輸出並保存到文件中。
package com.zch.io;
/**
* 通過給定的String類型參數的指定文件名稱與路徑,創建FileWriter類。
*
* @author zch
*/
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterDemo {
public static void main(String[] args) {
File file = new File("D://word2.txt"); //創建指定文件
try {
if(! file.exists()){
file.createNewFile(); //如果指定文件不存在,新建文件
}
FileReader fr = new FileReader("D://word.txt");
FileWriter fw = new FileWriter(file); //創建FileWriter對象
int length = 0;
while((length = fr.read()) != -1){ //如果沒有讀到文件末尾
fw.write(length); //向文件寫入數據
}
fr.close(); //關閉流
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
運行后創建了Word2.txt 文件,並向其中寫入數據
(四)IO流實戰:
1、Java IO流實現復制文件夾
通過IO不僅可以復制文件,還可以復制文件夾,但是文件夾內,可能包含其他文件夾,因此需要對他們進行分別復制。
package com.zch.io;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class CopyFile {
public static void main(String[] args) {
File sourceFile = null;
File desFile = null;
String sourceFolder = "D://簡歷2";
String copyFolder = "D://copy";
sourceFile = new File(sourceFolder);
if (!sourceFile.isDirectory() || !sourceFile.exists()) {
System.out.println("源文件夾不存在!");
} else {
desFile = new File(copyFolder);
desFile.mkdir();
copy(sourceFile.listFiles(), desFile);
System.out.println("文件夾復制成功!");
}
}
/**
* 創建copy方法,該方法接收文件數組和目標文件夾兩個參數,如果目標文件夾不存在,則調用mkdir()方法創建文件夾,然后再循環中將文件數組
* 中的每個文件對象寫到目標文件夾內。
* @param fl
* @param file
*/
public static void copy(File[] fl, File file) {
if (!file.exists()) { // 如果文件夾不存在
file.mkdir(); // 建立新的文件夾
}
for (int i = 0; i < fl.length; i++) {
if (fl[i].isFile()) { // 如果是文件類型,則復制文件
try {
FileInputStream fis = new FileInputStream(fl[i]);
FileOutputStream out = new FileOutputStream(new File(
file.getPath() + File.separator + fl[i].getName()));
int count = fis.available();
byte[] data = new byte[count];
if ((fis.read(data)) != -1) {
out.write(data);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (fl[i].isDirectory()) { // 如果是文件夾類型
File des = new File(file.getPath() + File.separator
+ fl[i].getName());
des.mkdir(); // 在目標文件夾中創建相同的文件夾
copy(fl[i].listFiles(), des); // 遞歸調用方法本身
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
運行本實例,會將D盤中的簡歷文件中的內容復制到D盤的copy文件夾中,而且包含文件夾的子文件夾
2、Java IO流實現分行向文件中寫入數據
FileWriter類可以向文件寫入字符數據,如果將FileWriter類封裝到BufferWriter類的緩沖字符流中,能夠實現緩沖字符輸出流,並且可以通過讀輸出流的newLine()方法,來實現數據的分行寫入。
package com.zch.io;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
/**
* 創建BranchWriter類,在主方法中定義文件對象,將該對象作為參數創建BufferedWriter類實例,
* 調用該實例的writer方法將數據寫入文件中,然后 調用newLine()方法寫入換行符,實現分行向文件寫入數據。
*
* @author zch
*
*/
public class BranchWriter {
public static void main(String[] args) {
String filePath = "D://BranchWriter.txt";
File file = new File(filePath);
try {
if (!file.exists()) {
file.createNewFile();
}
FileWriter fw = new FileWriter(file); // 創建文件輸出流
BufferedWriter bw = new BufferedWriter(fw); // 使用緩沖區數據流封裝輸出流
for (int i = 0; i < 100; i++) { //循環寫入100行數據
bw.write("Java交互管道——IO流".toCharArray());// 寫入數據到輸出流
bw.newLine(); // 寫入換行符
bw.flush(); // 刷新緩沖區
}
System.out.println("成功寫入數據!");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
3、刪除指定文件
File類的delete()方法可以實現刪除指定的文件,首先使用目標文件路徑創建File類的實例對象,然后再調用File類的delete()方法。
package com.zch.io;
import java.io.File;
public class FileDelete {
public static void main(String[] args) {
String filePath = "D://word.txt";
File file = new File(filePath);
delFile(file);
}
public static void delFile(File file) {
if (!file.exists()) {
System.out.println("文件不存在!");
return;
}
boolean rs = file.delete();
if (rs) {
System.out.println("文件刪除成功!");
} else {
System.out.println("文件刪除失敗!");
}
}
}