原文出處http://www.cnblogs.com/rollenholt/archive/2011/09/11/2173787.html
寫在前面:本文章基本覆蓋了java IO的全部內容,java新IO沒有涉及,因爲我想和這個分開,以突出那個的重要性,新IO哪一篇文章還沒有開始寫,估計很快就能和大家見面。照舊,文章依舊以例子爲主,因爲講解內容的java書很多了,我覺的學以致用纔是真。代碼是寫出來的,不是看出來的。
最後歡迎大家提出意見和建議。
【案例1】創建一個新文件
1
2
3
4
5
6
7
8
9
10
11
|
import java.io.*;
class hello{
public static void main(String[] args) {
File f= new File( "D:\\hello.txt" );
try {
f.createNewFile();
} catch (Exception e) {
e.printStackTrace();
}
}
} |
【運行結果】:
程序運行之後,在d盤下會有一個名字爲hello.txt的文件。
【案例2】File類的兩個常量
1
2
3
4
5
6
7
|
import java.io.*;
class hello{
public static void main(String[] args) {
System.out.println(File.separator);
System.out.println(File.pathSeparator);
}
} |
【運行結果】:
\
;
此處多說幾句:有些同學可能認爲,我直接在windows下使用\進行分割不行嗎?當然是可以的。但是在linux下就不是\了。所以,要想使得我們的代碼跨平臺,更加健壯,所以,大家都採用這兩個常量吧,其實也多寫不了幾行。呵呵、
現在我們使用File類中的常量改寫上面的代碼:
1
2
3
4
5
6
7
8
9
10
11
12
|
import java.io.*;
class hello{
public static void main(String[] args) {
String fileName= "D:" +File.separator+ "hello.txt" ;
File f= new File(fileName);
try {
f.createNewFile();
} catch (Exception e) {
e.printStackTrace();
}
}
} |
你看,沒有多寫多少吧,呵呵。所以建議使用File類中的常量。
刪除一個文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/** * 刪除一個文件
* */ import java.io.*;
class hello{
public static void main(String[] args) {
String fileName= "D:" +File.separator+ "hello.txt" ;
File f= new File(fileName);
if (f.exists()){
f.delete();
} else {
System.out.println( "文件不存在" );
}
}
} |
創建一個文件夾
1
2
3
4
5
6
7
8
9
10
11
|
/** * 創建一個文件夾
* */ import java.io.*;
class hello{
public static void main(String[] args) {
String fileName= "D:" +File.separator+ "hello" ;
File f= new File(fileName);
f.mkdir();
}
} |
【運行結果】:
D盤下多了一個hello文件夾
列出指定目錄的全部文件(包括隱藏文件):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/** * 使用list列出指定目錄的全部文件
* */ import java.io.*;
class hello{
public static void main(String[] args) {
String fileName= "D:" +File.separator;
File f= new File(fileName);
String[] str=f.list();
for ( int i = 0 ; i < str.length; i++) {
System.out.println(str[i]);
}
}
} |
【運行結果】:
$RECYCLE.BIN
360
360Downloads
360Rec
360SoftMove
Config.Msi
da
Downloads
DriversBackup
eclipse
java web整合開發和項目實戰
Lenovo
MSOCache
Program
Program Files
python
RECYGLER.{8F92DA15-A229-A4D5-B5CE-5280C8B89C19}
System Volume Information
Tomcat6
var
vod_cache_data
新建文件夾
(你的運行結果應該和這個不一樣的,呵呵)
但是使用list返回的是String數組,。而且列出的不是完整路徑,如果想列出完整路徑的話,需要使用listFiles.他返回的是File的數組
列出指定目錄的全部文件(包括隱藏文件):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/** * 使用listFiles列出指定目錄的全部文件
* listFiles輸出的是完整路徑
* */ import java.io.*;
class hello{
public static void main(String[] args) {
String fileName= "D:" +File.separator;
File f= new File(fileName);
File[] str=f.listFiles();
for ( int i = 0 ; i < str.length; i++) {
System.out.println(str[i]);
}
}
} |
【運行結果】:
D:\$RECYCLE.BIN
D:\360
D:\360Downloads
D:\360Rec
D:\360SoftMove
D:\Config.Msi
D:\da
D:\Downloads
D:\DriversBackup
D:\eclipse
D:\java web整合開發和項目實戰
D:\Lenovo
D:\MSOCache
D:\Program
D:\Program Files
D:\python
D:\RECYGLER.{8F92DA15-A229-A4D5-B5CE-5280C8B89C19}
D:\System Volume Information
D:\Tomcat6
D:\var
D:\vod_cache_data
D:\新建文件夾
通過比較可以指定,使用listFiles更加方便、
判斷一個指定的路徑是否爲目錄
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/** * 使用isDirectory判斷一個指定的路徑是否爲目錄
* */ import java.io.*;
class hello{
public static void main(String[] args) {
String fileName= "D:" +File.separator;
File f= new File(fileName);
if (f.isDirectory()){
System.out.println( "YES" );
} else {
System.out.println( "NO" );
}
}
} |
【運行結果】:YES
搜索指定目錄的全部內容
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
|
/** * 列出指定目錄的全部內容
* */ import java.io.*;
class hello{
public static void main(String[] args) {
String fileName= "D:" +File.separator;
File f= new File(fileName);
print(f);
}
public static void print(File f){
if (f!= null ){
if (f.isDirectory()){
File[] fileArray=f.listFiles();
if (fileArray!= null ){
for ( int i = 0 ; i < fileArray.length; i++) {
//遞歸調用
print(fileArray[i]);
}
}
}
else {
System.out.println(f);
}
}
}
} |
【運行結果】:
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\framepages\web4welcome_jsp.java
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\help_005fhome_jsp.class
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\help_005fhome_jsp.java
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\home_jsp.class
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\home_jsp.java
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\index_jsp.class
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\index_jsp.java
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\login_jsp.class
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\login_jsp.java
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\modify_005fuser_005finfo_jsp.class
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\modify_005fuser_005finfo_jsp.java
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\register_005fnotify_jsp.class
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\register_005fnotify_jsp.java
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\sign_005fup_jsp.class
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\sign_005fup_jsp.java
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\transit_jsp.class
……
【使用RandomAccessFile寫入文件】
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/** * 使用RandomAccessFile寫入文件
* */ import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName= "D:" +File.separator+ "hello.txt" ;
File f= new File(fileName);
RandomAccessFile demo= new RandomAccessFile(f, "rw" );
demo.writeBytes( "asdsad" );
demo.writeInt( 12 );
demo.writeBoolean( true );
demo.writeChar( 'A' );
demo.writeFloat( 1 .21f);
demo.writeDouble( 12.123 );
demo.close();
}
} |
如果你此時打開hello。txt查看的話,會發現那是亂碼。
字節流
【向文件中寫入字符串】
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/** * 字節流
* 向文件中寫入字符串
* */ import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName= "D:" +File.separator+ "hello.txt" ;
File f= new File(fileName);
OutputStream out = new FileOutputStream(f);
String str= "你好" ;
byte [] b=str.getBytes();
out.write(b);
out.close();
}
} |
查看hello.txt會看到“你好”
當然也可以一個字節一個字節的寫。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/** * 字節流
* 向文件中一個字節一個字節的寫入字符串
* */ import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName= "D:" +File.separator+ "hello.txt" ;
File f= new File(fileName);
OutputStream out = new FileOutputStream(f);
String str= "你好" ;
byte [] b=str.getBytes();
for ( int i = 0 ; i < b.length; i++) {
out.write(b[i]);
}
out.close();
}
} |
結果還是:“你好”
向文件中追加新內容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
/** * 字節流
* 向文件中追加新內容:
* */ import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName= "D:" +File.separator+ "hello.txt" ;
File f= new File(fileName);
OutputStream out = new FileOutputStream(f, true );
String str= "Rollen" ;
//String str="\r\nRollen"; 可以換行
byte [] b=str.getBytes();
for ( int i = 0 ; i < b.length; i++) {
out.write(b[i]);
}
out.close();
}
} |
【運行結果】:
你好Rollen
【讀取文件內容】
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/** * 字節流
* 讀文件內容
* */ import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName= "D:" +File.separator+ "hello.txt" ;
File f= new File(fileName);
InputStream in= new FileInputStream(f);
byte [] b= new byte [ 1024 ];
in.read(b);
in.close();
System.out.println( new String(b));
}
} |
【運行結果】
你好Rollen
Rollen_
但是這個例子讀取出來會有大量的空格,我們可以利用in.read(b);的返回值來設計程序。如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/** * 字節流
* 讀文件內容
* */ import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName= "D:" +File.separator+ "hello.txt" ;
File f= new File(fileName);
InputStream in= new FileInputStream(f);
byte [] b= new byte [ 1024 ];
int len=in.read(b);
in.close();
System.out.println( "讀入長度爲:" +len);
System.out.println( new String(b, 0 ,len));
}
} |
【運行結果】:
讀入長度爲:18
你好Rollen
Rollen
讀者觀察上面的例子可以看出,我們預先申請了一個指定大小的空間,但是有時候這個空間可能太小,有時候可能太大,我們需要準確的大小,這樣節省空間,那麼我們可以這樣幹:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/** * 字節流
* 讀文件內容,節省空間
* */ import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName= "D:" +File.separator+ "hello.txt" ;
File f= new File(fileName);
InputStream in= new FileInputStream(f);
byte [] b= new byte [( int )f.length()];
in.read(b);
System.out.println( "文件長度爲:" +f.length());
in.close();
System.out.println( new String(b));
}
} |
文件長度爲:18
你好Rollen
Rollen
將上面的例子改爲一個一個讀:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/** * 字節流
* 讀文件內容,節省空間
* */ import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName= "D:" +File.separator+ "hello.txt" ;
File f= new File(fileName);
InputStream in= new FileInputStream(f);
byte [] b= new byte [( int )f.length()];
for ( int i = 0 ; i < b.length; i++) {
b[i]=( byte )in.read();
}
in.close();
System.out.println( new String(b));
}
} |
輸出的結果和上面的一樣。
細心的讀者可能會發現,上面的幾個例子都是在知道文件的內容多大,然後才展開的,有時候我們不知道文件有多大,這種情況下,我們需要判斷是否獨到文件的末尾。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/** * 字節流
*讀文件
* */ import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName= "D:" +File.separator+ "hello.txt" ;
File f= new File(fileName);
InputStream in= new FileInputStream(f);
byte [] b= new byte [ 1024 ];
int count = 0 ;
int temp= 0 ;
while ((temp=in.read())!=(- 1 )){
b[count++]=( byte )temp;
}
in.close();
System.out.println( new String(b));
}
} |
【運行結果】
你好Rollen
Rollen_
提醒一下,當獨到文件末尾的時候會返回-1.正常情況下是不會返回-1的
字符流
【向文件中寫入數據】
現在我們使用字符流
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/** * 字符流
* 寫入數據
* */ import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName= "D:" +File.separator+ "hello.txt" ;
File f= new File(fileName);
Writer out = new FileWriter(f);
String str= "hello" ;
out.write(str);
out.close();
}
} |
當你打開hello。txt的時候,會看到hello
其實這個例子上之前的例子沒什麼區別,只是你可以直接輸入字符串,而不需要你將字符串轉化爲字節數組。
當你如果想問文件中追加內容的時候,可以使用將上面的聲明out的哪一行換爲:
Writer out =new FileWriter(f,true);
這樣,當你運行程序的時候,會發現文件內容變爲:
hellohello如果想在文件中換行的話,需要使用“\r\n”
比如將str變爲String str="\r\nhello";
這樣文件追加的str的內容就會換行了。
從文件中讀內容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/** * 字符流
* 從文件中讀出內容
* */ import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName= "D:" +File.separator+ "hello.txt" ;
File f= new File(fileName);
char [] ch= new char [ 100 ];
Reader read= new FileReader(f);
int count=read.read(ch);
read.close();
System.out.println( "讀入的長度爲:" +count);
System.out.println( "內容爲" + new String(ch, 0 ,count));
}
} |
【運行結果】:
讀入的長度爲:17
內容爲hellohello
hello
當然最好採用循環讀取的方式,因爲我們有時候不知道文件到底有多大。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/** * 字符流
* 從文件中讀出內容
* */ import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName= "D:" +File.separator+ "hello.txt" ;
File f= new File(fileName);
char [] ch= new char [ 100 ];
Reader read= new FileReader(f);
int temp= 0 ;
int count= 0 ;
while ((temp=read.read())!=(- 1 )){
ch[count++]=( char )temp;
}
read.close();
System.out.println( "內容爲" + new String(ch, 0 ,count));
}
} |
運行結果:
內容爲hellohello
hello
關於字節流和字符流的區別
實際上字節流在操作的時候本身是不會用到緩衝區的,是文件本身的直接操作的,但是字符流在操作的 時候下後是會用到緩衝區的,是通過緩衝區來操作文件的。
讀者可以試着將上面的字節流和字符流的程序的最後一行關閉文件的代碼註釋掉,然後運行程序看看。你就會發現使用字節流的話,文件中已經存在內容,但是使用字符流的時候,文件中還是沒有內容的,這個時候就要刷新緩衝區。
使用字節流好還是字符流好呢?
答案是字節流。首先因爲硬盤上的所有文件都是以字節的形式進行傳輸或者保存的,包括圖片等內容。但是字符只是在內存中才會形成的,所以在開發中,字節流使用廣泛。