File介紹
在整個IO包了,唯一表示與文件本身有關的類就是File類。使用File類可以進行1創建或刪除文件等常用操作。要想使用File類。則首先要觀察File類的構造方法,此類的常用構造方法如下所示:
No. 方法或常量 類型 描述
- 1 public static final String pathSeparator 常量 表示路徑的分隔符(windows是“;”)
- 2 public static final String separator 常量 表示路徑的分隔符(windows是“\”)
- 3 public File(String pathname) 構造 創建File類對象,傳入完整路徑
- 4 public boolean createNewFile()throws IOException 普通 創建新文件
- 5 public boolean delete() 普通 刪除文件
- 6 public boolean exists() 普通 判斷文件是否存在
- 7 public boolean isDirectory() 普通 判斷給定的路徑是否在一個目錄
- 8 public long length() 普通 返回文件的大小
- 9 public String[] list() 普通 列出指定目錄的全部內容,只是名稱
- 10 public File[] listFiles() 普通 列出指定目錄的全部內容,會有路徑
- 11 Public Boolean mkdir() 普通 創建一個目錄
- 12 Public Boolean renameTo(File dest) 普通 為已有的文件重命名
代碼:
public static void testFile() throws Exception {
//新建
File hello = new File("J:"+File.separator+"hello.txt");
if (!hello.exists()) {
hello.createNewFile();
}
File hello2 = new File("J:"+File.separator+"hello.txt");
System.out.println(hello2.exists());//說明如果文件存在就使用現有的文件
System.out.println(hello.getAbsolutePath());//J:\hello.txt
System.out.println(hello.getPath());//J:\hello.txt
hello.renameTo(new File("J:\\h.txt"));
//刪除
if (hello.exists()) {
// hello.delete();
}
//新建文件夾
File zhtFiles = new File("J:"+File.separator+"zhtFiles");
if (!zhtFiles.exists()) {
zhtFiles.mkdirs();
}
System.out.println(zhtFiles.getPath());//J:\zhtFiles
//If this abstract pathname is already absolute,
//then the pathname string is simply returned as if by the getPath method.
System.out.println(zhtFiles.getAbsolutePath());//J:\zhtFiles
//新建了多個文件
for (int i=1; i<11; i++) {
File fi = new File(zhtFiles.getPath() + File.separator +"zht"+i+".txt");
fi.createNewFile();
}
File[] fs = zhtFiles.listFiles();
for (File f : fs) {
System.out.println(f);//帶路徑打印文件名
}
String[] strs = zhtFiles.list();
for (String s : strs) {
System.out.println(s);//只打印文件名
}
if (zhtFiles.isDirectory()) {
zhtFiles.delete();//只能刪除空文件夾
}
deleteFile(zhtFiles.getAbsolutePath());
}
//使用遞歸進行文件刪除操作
static void deleteFile(String pathName) {
File file = new File(pathName);
if (!file.exists()) return;//文件不存在
if (!file.isDirectory()) {//是文件
file.delete();
} else {//是文件夾
//刪除文件夾下的文件
File[] fs = file.listFiles();
for (File f : fs) {
deleteFile(f.getAbsolutePath());
}
file.delete();//刪除空文件夾
}
}
IO介紹
IO就相當于程序對數據源的讀入或者寫出的操作方法API的集合。
參考:
http://www.lxweimin.com/p/0b86343232d2
http://www.cnblogs.com/liuhongfeng/p/5175109.html
http://www.lxweimin.com/p/328f4f67714b
IO是輸入和輸出的簡稱,在實際的使用時,輸入和輸出是有方向的。就像現實中兩個人之間借錢一樣,例如A借錢給B,相對于A來說是借出,而相對于B來說則是借入。所以在程序中提到輸入和輸出時,也需要區分清楚是相對的內容。
在程序中,輸入和輸出都是相對于當前程序而言的,例如從硬盤上讀取一個配置文件的內容到程序中,則相當于將文件的內容輸入到程序內部,因此輸入和“讀”對 應,而將程序中的內容保存到硬盤上,則相當于將文件的內容輸出到程序外部,因此輸出和“寫”對應。熟悉輸入和輸出的對應關系,將有助于后續內容的學習。
在Java語言中,輸入和輸出的概念要比其它語言的輸入和輸出的概念涵蓋的內容廣泛得多,不僅包含文件的讀寫,也包含網絡數據的發送,甚至內存數據的讀寫以及控制臺數據的接收等都由IO來完成。
為了使輸入和輸出的結構保持統一,從而方便程序員使用IO相關的類,在Java語言的IO類設計中引入了一個新的概念——Stream(流)。
由于在進行IO操作時,需要操作的種類很多,例如文件、內存和網絡連接等,這些都被稱作數據源(data source),對于不同的數據源處理的方式是不一樣的,如果直接交給程序員進行處理,對于程序員來說則顯得比較復雜。所以在所有的IO類設計時,在讀數據時,JDK API將數據源的數據轉換為一種固定的數據序列,在寫數據時,將需要寫的數據以一定的格式寫入到數據序列,由JDK API完成將數據序列中的數據寫入到對應的數據源中。這樣由系統完成復雜的數據轉換以及不同數據源之間的不同的變換,從而簡化程序員的編碼。
IO的 這種設計就和城市中的供水和排水系統設計是一樣的,在供水的時候,水源有江河水、湖水和地下水等不同類型,由自來水公司完成把水源轉換為對應的水流(InputStream)。而在 排水系統設計時,只需要將污水排入污水管道即可(OutputStream),至于這些污水是怎么被處理的,則不需要關心,這樣也簡化了家庭用水的處理。
IO設計中這種數據序列被形象的稱作流(Stream)。通過使用流的概念,使程序員面對不同的數據源時只需要建立不同的外殼流即可,不同的外殼流里面都是統一的內部流,程序員面對的就這個外殼流,外殼流封裝了很方便統一的操作API,而外殼流和內部流之間的復雜轉換則由系統完成,從而使程序員不必深入的了解每種數據源的讀寫方式,從而降低了IO編程的復雜度。
如圖所示:
字節流
流序列中的數據既可以是未經加工的原始二進制數據,也可以是經一定編碼處理后符合某種格式規定的特定數據。因此Java中的流分為兩種:
- 字節流:數據流中最小的數據單元是字節
- 字符流:數據流中最小的數據單元是字符, Java中的字 符是Unicode編碼,一個字符占用兩個字節。
InputStream(二進制格式操作):抽象類,基于字節的輸入操作,是所有輸入流的父類。定義了所有輸入流都具有的共同特征。
InputStream 為字節輸入流,它本身為一個抽象類,必須依靠其子類實現各種功能,此抽象類是表示字節輸入流的所有類的超類。 繼承自InputStream 的流都是向程序中輸入數據的,且數據單位為字節(8bit);
InputStream是輸入字節數據用的類,所以InputStream類提供了3種重載的read方法.Inputstream類中的常用方法:
(1) public abstract int read( ):讀取一個byte的數據,返回值是高位補0的int類型值。若返回值=-1說明沒有讀取到任何字節讀取工作結束。
(2) public int read(byte b[ ]):讀取b.length個字節的數據放到b數組中。返回值是讀取的字節數。該方法實際上是調用下一個方法實現的
(3) public int read(byte b[ ], int off, int len):從輸入流中最多讀取len個字節的數據,存放到偏移量為off的b數組中。
(4) public int available( ):返回輸入流中可以讀取的字節數。注意:若輸入阻塞,當前線程將被掛起,如果InputStream對象調用這個方法的話,它只會返回0,這個方法必須由繼承InputStream類的子類對象調用才有用,
(5) public long skip(long n):忽略輸入流中的n個字節,返回值是實際忽略的字節數, 跳過一些字節來讀取
(6) public int close( ) :我們在使用完后,必須對我們打開的流進行關閉.
主要的子類(截圖):
- 1) FileInputStream把一個文件作為InputStream,實現對文件的讀取操作
- 2) ByteArrayInputStream:把內存中的一個緩沖區作為InputStream使用
- 3) StringBufferInputStream:把一個String對象作為InputStream
- 4) PipedInputStream:實現了pipe的概念,主要在線程中使用
- 5) SequenceInputStream:把多個InputStream合并為一個InputStream
OutputStream(二進制格式操作):抽象類。基于字節的輸出操作。是所有輸出流的父類。定義了所有輸出流都具有的共同特征。 Java中字符是采用Unicode標準,一個字符是16位,即一個字符使用兩個字節來表示。為此,JAVA中引入了處理字符的流。
OutputStream提供了3個write方法來做數據的輸出,這個是和InputStream是相對應的。
- 1. public void write(byte b[ ]):將參數b中的字節寫到輸出流。
- 2. public void write(byte b[ ], int off, int len) :將參數b的從偏移量off開始的len個字節寫到輸出流。
- 3. public abstract void write(int b) :先將int轉換為byte類型,把低字節寫入到輸出流中。
- 4. public void flush( ) : 將數據緩沖區中數據全部輸出,并清空緩沖區。
- 5. public void close( ) : 關閉輸出流并釋放與流相關的系統資源。
主要的子類(截圖):
- ByteArrayOutputStream:把信息存入內存中的一個緩沖區中
- FileOutputStream:把信息存入文件中
- PipedOutputStream:實現了pipe的概念,主要在線程中使用
- SequenceOutputStream:把多個OutStream合并為一個OutStream
流結束的判斷:方法read()的返回值為-1時;readLine()的返回值為null時。
- SequenceOutputStream:把多個OutStream合并為一個OutStream
緩沖輸入輸出流 BufferedInputStream/ BufferedOutputStream
計算機訪問外部設備非常耗時。訪問外存的頻率越高,造成CPU閑置的概率就越大。為了減少訪問外存的次數,應該在一次對外設的訪問中,讀寫更多的數據。為此,除了程序和流節點間交換數據必需的讀寫機制外,還應該增加緩沖機制。緩沖流就是每一個數據流分配一個緩沖區,一個緩沖區就是一個臨時存儲數據的內存。這樣可以減少訪問硬盤的次數,提高傳輸效率。
BufferedInputStream:當向緩沖流寫入數據時候,數據先寫到緩沖區,待緩沖區寫滿后,系統一次性將數據發送給輸出設備。
BufferedOutputStream :當從向緩沖流讀取數據時候,系統先從緩沖區讀出數據,待緩沖區為空時,系統再從輸入設備讀取數據到緩沖區。
字符流
字符流主要用來處理文本文件。
Reader(文件格式操作):抽象類,基于字符的輸入操作。
Writer(文件格式操作):抽象類,基于字符的輸出操作。
程序:
static void testStream() throws Exception {
//FileInputStream
FileOutputStream fos = new FileOutputStream("J:\\stream1.txt",true);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd 'T' HH:mm:ss.SSS");
String dateStr = sdf.format(new Date()) + "你好啊 " +"\n";
fos.write(dateStr.getBytes("utf-8"));
fos.close();
FileInputStream fis = new FileInputStream("J:\\stream1.txt");
int len = fis.available();
byte[] buf = new byte[len];
fis.read(buf);
// System.out.println(new String(buf, "utf-8"));
dump(new FileInputStream("J:\\stream1.txt"), new FileOutputStream("J:\\n.txt"));
dump(new FileInputStream("J:\\stream1.txt"), new FileOutputStream("J:\\n2.txt"));
//byteArray ByteArrayInputStream 將byte數組作為數據源
//ByteArrayOutputStream 新建的bos對象內部包含了一個用來存儲數據的byte數組,初始大小32,自動增大
//Creates a ByteArrayInputStream so that it uses buf as its buffer array.
byte[] byteSoure = "hello world 你好啊".getBytes("utf-8");
ByteArrayInputStream bis = new ByteArrayInputStream(byteSoure);
//Creates a new byte array output stream.
//The buffer capacity is initially 32 bytes,
//though its size increases if necessary.
ByteArrayOutputStream bos = new ByteArrayOutputStream(1024*10);
byte[] buf2 = new byte[100];
int len2 = 0;
while ((len2 = bis.read(buf2)) != -1) {
bos.write(buf2, 0, len2);
}
System.out.println(new String(bos.toByteArray(), "utf-8"));
//data Stream 在基本的stream上做了一層封裝,可以方便對各種數據類型進行讀寫
DataOutputStream dos = new DataOutputStream(new FileOutputStream("J:\\data"));
dos.writeInt(120);
dos.writeFloat(88.45f);
dos.writeUTF("hello data");
dos.close();
DataInputStream dis = new DataInputStream(new FileInputStream("J:\\data"));
System.out.println(dis.readInt());
System.out.println(dis.readFloat());
System.out.println(dis.readUTF());
//Object Stream 對類進行讀寫,類要實現serializable接口
Person p1 = new Person("zht", 28);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("J:\\object"));
oos.writeObject(p1);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("J:\\object"));
Person p2 = (Person) ois.readObject();
System.out.println(p2.toString());
//打印類轉換成的字符串
ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
ObjectOutputStream oos2 = new ObjectOutputStream(bos2);
oos2.writeObject(p1);
System.out.println(new String(bos2.toByteArray()));
}
//文件復制
static void dump(InputStream scr, OutputStream dest) {
try (InputStream tscr = scr; OutputStream tdest = dest) {//自動關閉
byte[] buf = new byte[1024];
int len = -1;
while ((len = tscr.read(buf)) != -1) {
tdest.write(buf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
//更高效的復制
static void dumpHighSpeed(InputStream scr, OutputStream dest) {
try (BufferedInputStream tscr = new BufferedInputStream(scr);
BufferedOutputStream tdest = new BufferedOutputStream(dest)) {//自動關閉
byte[] buf = new byte[1024];
int len = -1;
while ((len = tscr.read(buf)) != -1) {
tdest.write(buf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
//編輯文檔
static void testWriterReader() throws Exception {
//Reader通過InputStreamReader轉換而來,在轉換的時候注意設置編碼格式
//Writer通過OutputStreamWriter轉換而來
InputStreamReader reader = new InputStreamReader(System.in, "gbk");//使用utf-8會有亂碼
OutputStreamWriter writer = new OutputStreamWriter(System.out, "gbk");
// writer.write("hello 你好");
writer.flush();//控制臺打印輸出
char[] buf = new char[1024];
//
// int len = reader.read(buf);//從控制臺讀取數據
// writer.write("get:"+new String(buf));
// writer.flush();
//常用 的FileReader FileWriter,因為不能設置編碼格式,建議盡量少用
FileWriter fileWriter1 = new FileWriter("J:\\fw1.txt");//使用系統默認編碼
fileWriter1.write("你好zht");
fileWriter1.close();
FileReader fReader1 = new FileReader("J:\\fw1.txt");//使用系統默認編碼
fReader1.read(buf);
System.out.println(new String(buf));
//正確的讀寫文件姿勢
BufferedWriter bufferedWriter = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream("J:\\bw1.txt"), "utf-8"));
bufferedWriter.write("你好 bufferWriter");
bufferedWriter.flush();
bufferedWriter.close();
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(new FileInputStream("J:\\bw1.txt"), "utf-8"));
System.out.println(bufferedReader.readLine());
charSetConvert("J:\\w.txt", "utf-8", "gbk");
}
//文件編碼格式轉換
static void charSetConvert(String srcFileName, String readCharSet,
String writeCharSet) throws Exception {
File wFile = new File("J:\\"+new Date().getTime());//臨時生成新的文件存放編碼轉換后的結果
char[] buf = new char[1024];
int len = 0;
//自動關閉文件
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(srcFileName), readCharSet);
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(wFile), writeCharSet)) {
while ((len = reader.read(buf)) != -1) {//編碼轉換
writer.write(buf, 0, len);
}
writer.flush();
//將臨時生成的文件覆蓋原文件
byte[] bs = new byte[1024];
FileInputStream fis = new FileInputStream(wFile);
FileOutputStream fos = new FileOutputStream(srcFileName);
while ((len = fis.read(bs)) != -1) {
fos.write(bs, 0, len);
}
fos.close();
fis.close();
}
wFile.delete();//刪除臨時文件
}
class Person implements Serializable {
String name;
int age;
public Person(String n, int a) {
name = n;
age = a;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "["+name+","+age+"]";
}
}