File類雖然可以操作文件,但是并不是操作文件的內(nèi)容,如果要進(jìn)行內(nèi)容的操作只能通過(guò)兩種途徑:字節(jié)流、字符流
如果要進(jìn)行輸入,輸出操作一般都會(huì)按照如下的步驟(以文件操作為例):
- 通過(guò)File類定義一個(gè)要操作文件的路徑;
- 通過(guò)字節(jié)流或字符流的子類對(duì)象為父類對(duì)象實(shí)例化;
- 進(jìn)行數(shù)據(jù)的讀(輸入)、寫(輸出)操作;
- 數(shù)據(jù)流屬于資源操作,資源操作必須關(guān)閉。
java.io包定義了兩類流:
- 字節(jié)流(JDK 1.0) : InputStream、OutputStream;
- 字符流(JDK 1.1) : Reader、Writer。
1 字節(jié)輸出流:OutputStream(重點(diǎn))
OutputStream類是一個(gè)專門進(jìn)行字節(jié)數(shù)據(jù)輸出的一個(gè)類,定義如下:
public abstract class OutputStream
extends Object
implements Closeable, Flushable
可以發(fā)先OutputStream類實(shí)現(xiàn)了個(gè)兩個(gè)接口:Closeable, Flushable;這兩個(gè)接口定義如下:
Closeable接口(JDK 1.5) | Flushable接口(JDK 1.5) |
---|---|
public interface Closeable extends AutoCloseable | public interface Flushable |
在JDK 1.7 中引入了自動(dòng)關(guān)閉機(jī)制,所以Closeable又繼承AutoCloseable接口,定義如下:
public interface AutoCloseable {
public void close() throws Exception;
}
但是OutputStream類在JDK 1.0的時(shí)候就提供了,這個(gè)類原本就定義了close()和flush()兩個(gè)方法,所以現(xiàn)在以上的兩個(gè)接口就幾乎可以忽略。
在OutputStream類里面提供有三個(gè)輸出的方法:
- 輸出單個(gè)字節(jié):
public abstract void write(int b) throws IOException
- 輸出全部字節(jié)數(shù)組:
public void write(byte[] b) throws IOException
-
輸出部分字節(jié)數(shù)據(jù):
public void write(byte[] b, int off, int len) throws IOException
OutputStream是抽象類,如果為抽象類進(jìn)行實(shí)例化操作,那么必須使用抽象類的子類,由于要使用文件操作,可以使用FileOutputStream子類,這個(gè)子類里面定義如下的構(gòu)造方法: - 創(chuàng)建或覆蓋已有文件:
public FileOutputStream(File file) throws FileNotFoundException
- 文件內(nèi)容追加:
public FileOutputStream(File file, boolean append) throws FileNotFoundException
范例:文件內(nèi)容的輸出
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class IntOrOutPutStream {
public static void main(String[] args) throws Exception {
File file = new File("D:" + File.separator + "Document" + File.separator + "test.txt");
if (!file.getParentFile().exists()) {
file.mkdirs();
}
OutputStream output = new FileOutputStream(file);
String str = "好好學(xué)習(xí),天天向上!";
byte[] data = str.getBytes();
output.write(data);
output.close();
}
}
以上是整個(gè)字節(jié)數(shù)組的內(nèi)容進(jìn)行了輸出,如果此時(shí)要輸出的文件不存在,就會(huì)自動(dòng)創(chuàng)建文件。
范例:單個(gè)字節(jié)的方式輸出
for (int x = 0 ; x < data.length ; x++) {
output.write(data[x]);
}
范例:輸出部分字節(jié)數(shù)組內(nèi)容
output.write(data, 6, 4);
以上都是直接覆蓋原有文件內(nèi)容,也可以實(shí)現(xiàn)內(nèi)容的追加,只需要更換FileOutputStream類的構(gòu)造方法即可:
OutputStream output = new FileOutputStream(file , true);
// \r\n 可以實(shí)現(xiàn)換行
String str = "好好學(xué)習(xí),天天向上!\r\n";
2 字節(jié)輸入流:InputStream
如果需要進(jìn)行數(shù)據(jù)的讀取操作,可以利用InputStream類實(shí)現(xiàn)功能,此類定義:public abstract class InputStream extends Object implements Closeable
雖然此類實(shí)現(xiàn)了Closeable接口,但是與OutputStream類一樣,可以不用考慮接口的存在,在InputStream類里面也定義又?jǐn)?shù)據(jù)讀取的方法:
- 讀取單個(gè)字節(jié):
public abstract int read() throws IOException
· 返回值:返回讀取的字節(jié)內(nèi)容,如果結(jié)尾沒(méi)有數(shù)據(jù)了,返回 -1 - 將讀取的數(shù)據(jù)保存在里字節(jié)數(shù)組里:
public int read(byte[] b) throws IOException
· 返回值:返回讀取的數(shù)據(jù)長(zhǎng)度,如果已經(jīng)讀取到結(jié)尾,返回 -1 - 將讀取的數(shù)據(jù)保存在部分字節(jié)數(shù)據(jù)里:
public int read(byte[] b, int off, int len) throws IOException
· 返回值:讀取的部分?jǐn)?shù)據(jù)的長(zhǎng)度,如果已經(jīng)讀取到結(jié)尾,返回 -1
InputStream是一個(gè)抽象類,如果要進(jìn)行文件讀取使用子類FileInputStream,此子類的構(gòu)造方法:public FileInputStream(File file) throws FileNotFoundException
范例:向數(shù)組里面讀取數(shù)據(jù)
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
public class InputStreamTest {
public static void main(String[] args) throws Exception{
//1.定義要輸入的文件路徑
File file = new File("D:" + File.separator + "Document" + File.separator + "test.txt");
if (file.getParentFile().exists()) {
//2. 使用InputStream進(jìn)行讀取
InputStream input = new FileInputStream(file);
//3. 讀取數(shù)據(jù)
byte[] data = new byte[1024]; //準(zhǔn)備長(zhǎng)度為1024的數(shù)組
int len = input.read(data); //將內(nèi)容保存到字節(jié)數(shù)組中
//4. 關(guān)閉輸入流
input.close();
System.out.println("{" + new String(data , 0 ,len) + "}");
}
}
}
范例:單個(gè)字節(jié)數(shù)據(jù)讀取
- 文件有很多字節(jié)數(shù)據(jù),所以讀取數(shù)據(jù)應(yīng)采用循環(huán)的方式,但由于不確定循環(huán)次數(shù),所以使用while循環(huán)。
import java.io.File;
import java.io.InputStream;
import java.io.FileInputStream;
public class InputStreamWhileTest {
public static void main(String[] args) throws Exception {
File file = new File("D:" + File.separator + "Document" + File.separator + "test.txt");
if (file.getParentFile().exists()) {
InputStream input = new FileInputStream(file);
byte[] data = new byte[1024];
int temp = 0;
int foot = 0;
//temp = input.read() , 表示將read() 方法讀取的字節(jié)內(nèi)容賦值給temp變量
//(temp = input.read()) != -1 , 判斷讀取temp的內(nèi)容是否是-1
while ((temp = input.read()) != -1) {
data[foot++] = (byte) temp; //有內(nèi)容進(jìn)行保存
}
input.close();
System.out.println("{" +new String(data , 0 , foot)+ "}");
}
}
}
3 字符輸出流:Writer
Writer類是在JDK1.1之后增加的,其類的定義如下:
public abstract class Writer extends Object implements Appendable, Closeable, Flushable
這個(gè)類除了實(shí)現(xiàn)了Closeable與Flushable接口外,又多實(shí)現(xiàn)了一個(gè)Appendable,這個(gè)接口的定義如下:
public interface Appendable {
public Appendable append(char c) throws IOException {}
public Appendable append(CharSequence csq) throws IOException {}
public Appendable append(CharSequence csq, int start, int end) throws IOException {}
}
在Appendable接口里面定義了追加類的操作,而且追加的數(shù)據(jù)都是字符或者字符串。
在Writer類里面定義有一下的輸出方法(部分):
- 輸出全部字符數(shù)組:
public void write(char[] cbuf) throws IOException
- 輸出字符串:
public void write(String str) throws IOException
Writer是一個(gè)抽象類,如果想要為這個(gè)類的對(duì)象實(shí)例化,應(yīng)該使用FileWriter子類:
范例:使用Writer類實(shí)現(xiàn)內(nèi)容輸出
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
public class WriterTest {
public static void main(String[] args) throws Exception {
File file = new File("D:" + File.separator + "Document"
+ File.separator + "Document" + File.separator + "test.txt");
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
Writer writerfile = new FileWriter(file);
String str = "Hello world!";
writerfile.write(str);
writerfile.close();
}
}
4 字符輸入流:Reader
Reader 是進(jìn)行字符數(shù)據(jù)讀取的輸入流,其本身也是一個(gè)抽象類:
public abstract class Reader extends Object implements Readable, Closeable
在Reader類里面也提供有一系列的read()方法:
- 讀取內(nèi)容到字符數(shù)組:
public int read(char[] cbuf) throws IOException
· 返回值:表示讀取的數(shù)據(jù)長(zhǎng)度,如果已經(jīng)讀取到結(jié)尾了,返回 -1;
為Reader類實(shí)例化的可以使用FileReader子類完成。
范例:使用Reader讀取數(shù)據(jù)
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
public class ReaderTest {
public static void main(String[] args) throws Exception {
File file = new File(
"D:" + File.separator + "Document" + File.separator + "Document" + File.separator + "test.txt");
if (file.getParentFile().exists()) {
Reader readerfile = new FileReader(file);
char[] data = new char[1024];
int len = readerfile.read(data);
readerfile.close();
System.out.println(new String(data, 0, len));
}
}
}
5 字節(jié)流與字符流的區(qū)別?
- 字節(jié)流直接與終端進(jìn)行數(shù)據(jù)交互,字符流需要將數(shù)據(jù)經(jīng)過(guò)緩沖去處理后才可以輸出。
- 在使用OutputStream輸出數(shù)據(jù)的時(shí)候,即使最后沒(méi)有關(guān)閉輸出流,內(nèi)容也可以正常輸出,但是不關(guān)閉字符輸出流,就表示在緩沖區(qū)中處理的內(nèi)容不會(huì)被強(qiáng)制性清空,所以就不會(huì)輸出數(shù)據(jù);如果有特殊情況不能夠關(guān)閉字符輸出流,可以使用flush()方法強(qiáng)制清空緩沖區(qū)。
范例:強(qiáng)制清空緩沖區(qū)
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
public class FlushTest {
public static void main(String[] args) throws Exception{
File file = new File("D:" + File.separator + "Document" + File.separator + "Document" + File.separator + "test.txt");
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
Writer out = new FileWriter(file);
String str = "Hello world @!";
out.write(str);
out.flush();
}
}
在開發(fā)之中,對(duì)字節(jié)數(shù)據(jù)處理是比較多的,例如:圖片、音樂(lè)、電影;而對(duì)字符流最大的好處就是可以處理中文,所以在日后的開發(fā)之中,如果要處理中文, 優(yōu)先考慮字符流,沒(méi)有中文時(shí),建議使用字節(jié)流。