IO繼承關(guān)系
io.jpg
1.File類
- File表示的是文件(目錄)
- File類只用于表示文件(目錄)的信息(名稱锰镀、大小等), 不能用于文件內(nèi)容的訪問
- 在某些流方法中可以使用表示路徑的字符串代替File對象
構(gòu)造器
/**
* 在不傳入絕對路徑的情況下契沫,默認(rèn)使用相對路徑,即使用 該項目工程的路徑;
* 目錄分級使用 / 表示击吱,也就是Linux系統(tǒng)的分級符(本文代碼使用Windows系統(tǒng)環(huán)境編譯)
*/
//方式一:直接傳入路徑
File file2 = new File("D:\\logs\\文本.txt");
//方式二:第一個參數(shù)代表父路徑疏尿,第二個參數(shù)代表子路徑瘟芝,常用語表示某路徑(第一個參數(shù))下的某個文件(第二個參數(shù))
File file = new File("D:\\logs","文本.txt");
常用方法
File file = new File("");
//列出當(dāng)前目錄下的子目錄和文件名,不包含父目錄名和子孫目錄褥琐,返回字符串?dāng)?shù)組
file.list();
//返回直接子目錄(文件)的抽象锌俱,表示目錄的絕對路徑
file.listFiles();
//判斷目錄或文件是否存在
file.exists();
//判斷是否是目錄
file.isDirectory();
//創(chuàng)建新目錄,只創(chuàng)建一級
file.mkdir();
//創(chuàng)建多級目錄敌呈,
file.mkdirs();
//判斷是否是文件
file.isFile();
//創(chuàng)建新的文件
file.createNewFile();
//刪除目錄或文件
file.delete();
//獲取絕對路徑贸宏,返回String
file.getAbsolutePath();
//獲取文件名,返回String
file.getName()
//獲取父路徑磕洪,返回String
file2.getParent();
案例
//案例一:判斷目錄是否存在吭练,存在 ? 刪除 : 新建;(同理可判斷文件)
private void fileTest(File file){
if (!file.exists()){
file.mkdir();//只創(chuàng)建一級目錄;file.mkdirs()可創(chuàng)建多級目錄
}else {
file.delete(); //刪除目錄
}
}
//案例二:列出指定目錄下的以.java后綴結(jié)尾所有文件析显,包含子目錄
private void listDirectory(File dir){
if(!dir.exists()){
throw new IllegalArgumentException("目錄"+dir+"不存在");
}
if (!dir.isDirectory()){
throw new IllegalArgumentException(dir+"不是目錄");
}
File[] files = dir.listFiles(); //返回直接子目錄(文件)的抽象
if (null!= files && files.length>0){
for (File file : files){
if (file.isDirectory()){
listDirectory(file);
}else {
if (file.getName().endsWith(".java"))
System.out.println(file);
}
}
}
}
2鲫咽、字節(jié)流
① InputStream、OutputStream (抽象類)
- InputStream抽象了應(yīng)用程序讀取數(shù)據(jù)的方式
- OutputStream抽象了應(yīng)用程序?qū)懗鰯?shù)據(jù)的方式
② EOF = End 讀到-1就到結(jié)尾 - ③ 輸入流基本方法
- int b = in.read(); 讀取一個字節(jié)無符號填充到int低八位谷异,-1是EOF
- in.read(byte[] buf);
- in.read(byte[] buf,int start,int size);
- ④ 輸出流基本方法
- out.write(int b); 寫出一個字節(jié)到流浑侥,b的低八位
- out.write(byte[] buf);將buf字節(jié)數(shù)組都寫入到流
- out.write(byte[] buf,int start,int size); buf字節(jié)數(shù)組從start開始寫,寫size長度
- ⑤ FileInputStream :具體實現(xiàn)了在文件上讀取數(shù)據(jù)
一晰绎、 FileInputStream寓落、FileOutputStream
- FileInputStream:用于從文件中讀取信息
- FileOutputStream:用于將信息寫入文件
構(gòu)造器
//通過傳入File對象或直接傳表示路徑的字符串
FileInputStream in = new FileInputStream(new File(""));
FileOutputStream out = new FileOutputStream(new File(""));
//FileOutputStream構(gòu)造器有第二個參數(shù)可選,傳入boolean值荞下,true:表示在原文件內(nèi)容之后追加寫入內(nèi)容伶选,
//false:默認(rèn)值史飞,可不傳,表示清空原文件仰税,重新寫入
案例
//文件拷貝
/**
* 文件拷貝 (此方法效率最高)
*
* @param srcFile
* @param destFile
*/
public static void copyFile(File srcFile,File destFile) throws IOException {
if (!srcFile.exists()){
throw new IllegalArgumentException("文件"+srcFile+"不存在");
}
if (!srcFile.isFile()){
throw new IllegalArgumentException(srcFile+"不是文件");
}
FileInputStream in = new FileInputStream(srcFile);
FileOutputStream out = new FileOutputStream(destFile);
byte[] buf = new byte[8*1024];
int b;
while ((b=in.read(buf,0,buf.length))!=-1){
out.write(buf,0,b);
out.flush();
}
in.close();
out.close();
}
二构资、BufferedInputStream、BufferedOutputStream
- BufferedInputStream:可以防止每次讀取時都得進行實際寫操作
- BufferedOutputStream:可以米面每次發(fā)送數(shù)據(jù)時都要進行實際的寫操作陨簇,注意: 每次寫完之后調(diào)用flush()方法吐绵,以刷新緩沖區(qū)
構(gòu)造器
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));
案例
/**
* 帶緩沖的文件拷貝方式(此處僅演示用法,文件拷貝不推薦使用此方式)
*
* 緩沖操作河绽,一般打開文件進行寫入操作或讀取操作時(非拷貝)己单,都會加上緩沖,可提高IO性能
*/
public static void copyFileByBuffered(File srcFile,File destFile) throws IOException {
if (!srcFile.exists()){
throw new IllegalArgumentException("文件"+srcFile+"不存在");
}
if (!srcFile.isFile()){
throw new IllegalArgumentException(srcFile+"不是文件");
}
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));
int c;
while ((c=bis.read())!=-1){
bos.write(c);
bos.flush();
}
bis.close();
bos.close();
}
三耙饰、DataInputStream/DataOutputStream
- DataInputStream:與DataOutputStream搭配使用纹笼,我們可以按照可移植方式從流讀取到基本數(shù)據(jù)類型
- DataOutputStream:與DataInputStream搭配使用,我們可以按照可移植方式向流寫入基本數(shù)據(jù)類型
構(gòu)造器
DataInputStream dis = new DataInputStream(new FileInputStream(""));
DataOutputStream dos = new DataOutputStream(new FileOutputStream(""));
案例
- DataInputStream
public class DisDemo {
public static void main(String[] args) throws IOException {
String file = "";
DataInputStream dis = new DataInputStream(new FileInputStream(file));
int i = dis.readInt();
System.out.println(i);
i = dis.readInt();
System.out.println(i);
//讀取文件中 long型苟跪、double型廷痘、和utf編碼字符
long l = dis.readLong();
System.out.println(l);
double d = dis.readDouble();
System.out.println(d);
String s = dis.readUTF();
System.out.println(s);
dis.close();
}
}
- DataOutputStream
public class DosDemo {
public static void main(String[] args) throws IOException {
String file = "demo/dos.dat";
DataOutputStream dos = new DataOutputStream(new FileOutputStream(file));
dos.writeInt(10);
dos.writeInt(-10);
dos.writeLong(12l);
dos.writeDouble(12.3);
dos.writeUTF("中國"); //采用UTF-8編碼輸出
dos.writeChars("中國"); //采用Java默認(rèn)的 utf-16be編碼輸出
dos.close();
}
}
3、字符流
- ① 編碼問題
- ② 認(rèn)識 文本和文本文件
- Java文本:指的是char是16位無符號整數(shù)件已,是字符的Unicode編碼(雙字節(jié)編碼)
- 文本:byte byte byte...的數(shù)據(jù)序列
- 文本文件是文本(char)序列按照某種編碼方案(utf-8/gbk等)序列化為byte的存儲結(jié)果
- ③ 字符流(Reader笋额、Writer):操作文本、文本文件
- 字符處理篷扩,一次處理一個字符
- 字符的底層依然是基本的字節(jié)序列
- 字符流的基本實現(xiàn):
- InputStreamReader:完成byte流解析為char流兄猩,按照編碼處理
- OutputStreamWriter:提供char流到byte流,按照編碼處理
一瞻惋、字符編碼
分類
- ASCII(數(shù)字厦滤、英文):1個字符占一個字節(jié)(所有的編碼集都兼容ASCII)
- ISO8859-1(歐洲):1個字符占一個字節(jié)
- GB-2312/GBK:1個字符占兩個字節(jié)
- Unicode: 1個字符占兩個字節(jié)(網(wǎng)絡(luò)傳輸速度慢)
- UTF-8:變長字節(jié),對于英文一個字節(jié)歼狼,對于漢字兩個或三個字節(jié)掏导。
原則
- 保證編解碼方式的統(tǒng)一,才能不至于出現(xiàn)錯誤羽峰。
二趟咆、InputStreamReader/OutputStreamWriter
構(gòu)造器
FileInputStream in = new FileInputStream("D:\\logs\\文本.txt");
InputStreamReader isr = new InputStreamReader(in,"gbk");//不寫第二個參數(shù),默認(rèn)使用項目的編碼格式
FileOutputStream out = new FileOutputStream("D:\\logs\\文本2.txt");
OutputStreamWriter osw = new OutputStreamWriter(out,"utf-8");
案例
/**
*文件拷貝
*/
public class CharStreamDemo {
public static void main(String[] args) throws IOException {
FileInputStream in = new FileInputStream("D:\\logs\\文本.txt");
InputStreamReader isr = new InputStreamReader(in,"gbk");//不寫第二個參數(shù)梅屉,默認(rèn)使用項目的編碼格式
char[] buf = new char[8*1024];
int c;
FileOutputStream out = new FileOutputStream("D:\\logs\\文本2.txt");
OutputStreamWriter osw = new OutputStreamWriter(out,"utf-8");
while ((c=isr.read(buf,0,buf.length))!=-1){
String s = new String(buf,0,c);
System.out.println(s);
osw.write(buf,0,c);
osw.flush();
}
isr.close();
osw.close();
}
}
三值纱、BufferedReader/BufferedWriter/PrintWriter
BufferedWriter和PrintWriter作用相同,PrintWriter無須刷新坯汤,可自動識別換行
構(gòu)造器
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("D:\\logs\\文本.txt"),"gbk"));
BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream("D:\\logs\\文本2.txt"),"utf-8"));
PrintWriter pw = new PrintWriter("D:\\logs\\文本3.txt");
案例
/**
*文件拷貝
*/
public class BrAndBwDemo {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("D:\\logs\\文本.txt"), "gbk"));
PrintWriter pw = new PrintWriter("D:\\logs\\文本3.txt");
String line;
while ((line = br.readLine()) != null) {
System.out.println(line); //一次讀一行,不能識別換行
pw.println(line); //ln自動換行
pw.flush();
}
br.close();
pw.close();
}
}
四虐唠、說明
- io包的InputStreamReader:稱為從字節(jié)流到字符流的橋轉(zhuǎn)換類。這個類可以設(shè)定字符轉(zhuǎn)換方式惰聂。
- OutputStreamWriter:字符到字節(jié)
BufferedReader有readLine()使得字符輸入更加方便疆偿。 - 在I/O流中咱筛,所有輸入方法都是阻塞方法。
- BufferedWriter:給輸出字符加緩沖杆故,因為它的方法很少迅箩,所以使用父類PrintWriter,它可以使用字節(jié)流對象处铛,而且方法很多饲趋。
4、RandomAccessFile
- RandomAccessFile 是Java提供的對文件內(nèi)容的訪問撤蟆,既可以讀文件也可以寫文件
- 沒有繼承InputStream/OutputStream抽象類
- 支持隨機訪問文件奕塑,可以訪問文件的任意位置
- ①Java文件模型:在硬盤上的文件是byte byte byte存儲的,是數(shù)據(jù)的集合
- ②打開文件:有兩種模式 "rw"(讀寫) "r"(只讀)
- RandomAccessFile raf = new RandomAccessFile(file,"rw");
- 文件指針:打開文件時指針在開頭 pointer=0;
- ③寫方法:raf.write(int) 只寫一個字節(jié)(后8位)枫疆,同時指針指向下一個位置爵川,準(zhǔn)備再次寫入
- ④讀方法:int b = raf.read(); 讀一個字節(jié)
- ⑤文件讀寫完成之后一定要關(guān)閉
構(gòu)造器
RandomAccessFile raf = new RandomAccessFile(new File(""),"rw");//讀寫模式
案例
public class RandomDemo {
public static void main(String[] args) throws IOException {
File demo = new File("demo");
if (!demo.exists()) {
demo.mkdir();
}
File file = new File(demo, "raf.dat");
if (!file.exists()) {
file.createNewFile();
}
RandomAccessFile raf = new RandomAccessFile(file, "rw");
System.out.println(raf.getFilePointer());//指針的位置
raf.write('A'); //只寫了一個字節(jié)(后8位)
System.out.println(raf.getFilePointer());//指針的位置
raf.write('B');
int i = 0x7fffffff;
raf.writeInt(i);
System.out.println(raf.getFilePointer());//指針的位置
String s = "中";
byte[] gbk = s.getBytes("gbk");
raf.write(gbk);
System.out.println(raf.getFilePointer());//指針的位置
//讀文件儡湾,把指針移到頭部
raf.seek(0);
//一次性讀取溉瓶,把文件中的內(nèi)容都讀到字節(jié)數(shù)組中
byte[] buf = new byte[(int) raf.length()];
raf.read(buf);
System.out.println(Arrays.toString(buf));
for (byte b : buf) {
System.out.println(Integer.toHexString(b & 0xff) + ""); //16進制
}
raf.close();
}
}