day10_面向對象(File類、遞歸和字節流)
一.File類
1.File類的作用
File類可以用來表示文件或者文件夾
2.File類的構造
public File(String pathname);
public File(String parent, String child);
public File(File file, String child);
/**
* File類的構造方法
*/
public class FileDemo01 {
public static void main(String[] args) {
//1.根據路徑
File f1 = new File("C:\\Users\\Administrator\\Desktop\\temp\\aaa\\1.png");
System.out.println(f1);
//2.父路徑和子路徑
File f2 = new File("C:\\Users\\Administrator", "Desktop\\temp\\aaa\\1.png");
System.out.println(f2);
//3.父File對象和子路徑
File parent = new File("C:\\Users\\Administrator");
File f3 = new File(parent, "Desktop\\temp\\aaa\\1.png");
System.out.println(f3);
}
}
3.相對路徑和絕對路徑的概念*****************
絕對路徑:以盤符開頭的路徑 比如:C:\\code\\1.java
相對路徑:以當前項目的根目錄開始 比如1.txt 該文件就從當前項目的根目錄開始尋找
4.File類的獲取方法
public String getAbsolutePath(); // 獲取絕對路徑
public String getPath(); // 獲取創建時傳入路徑
public long length(); // 只能獲取文件的大小(單位字節),不能獲取文件夾的大小
public String getName(); // 獲取名字(文件名字)
/**
* File類的獲取方法
*/
public class FileDemo02 {
public static void main(String[] args) {
//1.創建File對象
File f1 = new File("E:\\mycode\\heima112\\111.txt");
// File f1 = new File("1.txt");
//2.獲取絕對路徑
String absolutePath = f1.getAbsolutePath();
System.out.println(absolutePath);
System.out.println("=====================");
//3.獲取構造時傳入的路徑
String path = f1.getPath();
System.out.println(path);
System.out.println("=====================");
//4.獲取文件的大小
long len = f1.length();
System.out.println("文件大小爲:"+len); //GBK/UTF-8 編碼下1箇中文2/3個字節
//5.獲取名字
System.out.println("=====================");
String name = f1.getName();
System.out.println(name);
}
}
5.File類的判斷方法
public boolean exists(); // 判斷File對象所表示的文件或者文件夾是否存在
public boolean isFile(); // 判斷是否是文件
public boolean isDirectory(); // 判斷是否是文件夾
/**
* File類的判斷方法
*/
public class FileDemo03 {
public static void main(String[] args) {
//1.判斷是否存在
File f1 = new File("11.txt");
boolean exists = f1.exists();
System.out.println(exists);
System.out.println("===========");
//2.判斷是文件還是文件夾
boolean isFile = f1.isFile();
System.out.println("是文件嗎?" + isFile);
boolean isDirectory = f1.isDirectory();
System.out.println("是文件夾嗎?" + isDirectory);
}
}
注意:判斷是文件還是文件時,必須要保證該File對象表示路徑存在!!!
在Windows中同一路徑下文件和文件名不允許重名(Windows中也不區分大小寫)
6.File類的創建刪除方法
public boolean createNewFile(); 創建一個文件,返回值代表是否成功
public boolean mkdir(); 創建一個單級文件夾,返回值代表是否成功
public boolean mkdirs(); 創建一個多級文件夾,返回值代表是否成功
public boolean delete(); 刪除文件或者空的文件夾,返回值代表是否成功
/**
* File類的創建和刪除方法
*/
public class FileDemo04 {
public static void main(String[] args) throws IOException {
//1.創建文件
File f1 = new File("2.txt");
boolean newFile = f1.createNewFile();
System.out.println("是否創建成功:" + newFile);
// //2.創建文件夾
File f2 = new File("aaa");
boolean mkdir = f2.mkdir();
System.out.println("是否創建成功:"+mkdir);
//3.刪除文件或者文件夾
boolean b1 = f1.delete();
boolean b2 = f2.delete();
System.out.println("文件是否刪除成功:"+b1);
System.out.println("文件夾是否刪除成功:"+b2);
//4.mkdirs
File f3 = new File("aaa\\bbb\\ccc\\ddd");
System.out.println(f3.mkdir());
System.out.println(f3.mkdirs());
//5.delete方法的限制
File f4 = new File("bbb");
System.out.println(f4.delete());
}
}
7.File類遍歷目錄的方法
public String[] list(); 列出當前文件夾下所有東西的名字
public File[] listFiles(); 列出當前文件夾下所有File對象
/**
* 遍歷目錄方法
*/
public class FileDemo05 {
public static void main(String[] args) {
//1.列出名字
File f1 = new File("C:\\Users\\Administrator\\Desktop\\temp\\aaa");
String[] names = f1.list();
for (String name : names) {
System.out.println(name);
}
//2.列出File對象
System.out.println("===================");
File[] files = f1.listFiles();
for (File file : files) {
System.out.print(file.getAbsolutePath());
if (file.isFile()) {
System.out.print("是文件");
System.out.println(",大小爲:"+file.length()+"字節");
}else{
System.out.println("是文件夾");
}
}
}
}
二.遞歸
1.什麼是遞歸
在方法內部調用自己
如果是無限遞歸(或死遞歸),程序最終會出現錯誤 StackOverflowError(棧溢出錯誤)
如果想要正確地使用遞歸,必須保證遞歸有正確的出口(結束條件),所謂的出口,是指當滿足某個條件時,直接使用return結束本次遞歸函數調用,返回上級遞歸調用
public class RecursionDemo {
public static void main(String[] args) {
method(100);
}
public static void method(int n) {
//讓遞歸有一個出口,不再繼續調用自己
if (n == 0) {
return;
}
System.out.println("method方法...");
method(n-1);
}
}
2.遞歸求和案例
需求:使用遞歸求1+2+3...+n的和
遞歸步驟:
a.定義方法
b.找規律,遞歸調用自己
c.找遞歸的出口條件
public class RecursionTestDemo01 {
public static void main(String[] args) {
//調用
int sum = getSum(10);
System.out.println(sum);
}
/**
* 遞歸步驟:
* a.定義方法
* b.找規律,遞歸調用自己
* c.找遞歸的出口條件
*/
//a.定義方法
public static int getSum(int n) {
//c.找遞歸的出口條件
if (n == 1) {
return 1;
}
//b.找規律,遞歸調用自己
// 求 1+2+3..n = (1+2+3..n-1) + n
return getSum(n-1)+n;
}
//使用for循環
public static int getSum(int n) {
int sum = 0;
for (int i = 1; i <= n; i++) {
sum+=i;
}
return sum;
}
}
3.遞歸求積案例
需求:使用遞歸求1*2*3...*n的積
遞歸步驟:
a.定義方法
b.找規律,遞歸調用自己
c.找遞歸的出口條件
public class RecursionTestDemo02 {
public static void main(String[] args) {
//調用方法
int ji = getJi(6);
System.out.println(ji);
}
//使用遞歸求1-n積
public static int getJi(int n) {
if (n == 1) {
return 1;
}
//1*2*3..n = (1*2*3..n-1)*n
return getJi(n-1)*n;
}
}
4.文件搜索案例
在目錄:C:\Users\Administrator\Desktop\temp\aaa
搜索所有的:xxx.txt文件
public class RecursionTestDemo03 {
public static void main(String[] args) {
//搜索文件案例
//目標文件夾
File objDir = new File("C:\\Users\\Administrator\\Desktop\\temp\\aaa");
//目標文件: xx.txt文件
printTxtFile(objDir);
}
//定義方法,在某個文件夾下搜索.txt文件
public static void printTxtFile(File objDir) {
//1.列出所有文件
File[] files = objDir.listFiles();
//2.遍歷
for (File file : files) {
//3.判斷
if (file.isFile() && file.getName().endsWith(".txt")) { //endsWith 判斷以xxx結尾 startsWith判斷以xx開頭
//說明是一個txt的文本文件
System.out.println(file.getAbsolutePath());
} else if (file.isDirectory()) {
//說明是文件夾
printTxtFile(file);
}
}
}
}
三.IO流的概述
1.什麼是IO流
流:數據流,一種比喻,把數據傳輸過程比喻流
I:Input 輸入流 將數據從外部設備讀取到內存中
O:Output 輸出流 將數據從內存寫到外部設備中
IO流都是相對於內存而言的!!!
2.IO流的分類
a.根據流的方向來分
輸入流
輸出流
b.根據流中數據類型來分
字節流
字符流
3.Java中IO的四大流***************
字節輸入流 OutputStream(抽象類)
字節輸出流 InputSream(抽象類)
字符輸入流 Writer(抽象類)
字符輸出流 Reader(抽象類)
Java中流的命名:功能+父類名
比如:FileInputStream 文件的字節輸入流
ObjectInputStream 對象的字節輸入流(反序列化流)(序列化時輸出流)
四.字節流********************
1.萬物皆對象和IO流一切皆字節
Java中思想:萬物皆對象
IO流中:一切皆字節
在計算機中,所有東西,最終底層都是0101二進制(8個0101稱爲一個字節)
問題:
a.既然.txt文件是字節,那麼 打開時爲什麼不是0101??
因爲我們打開文件時,是用某個軟件打開,軟件具有解析功能,同樣道理,視頻文件,音頻文件,圖片文件等,都需 要使用對應的軟件打開,這些軟件都會把數據解析成他們指定的格式。
b.能不能不要解析0101,就像看0101?
可以的,只要使用某些二進制工具打開即可
2.字節輸出流******************
字節輸出流:頂層父類:OutputStream(抽象類)
共性方法:
public void write(int b);一次寫一個字節
public void write(byte[] bs);一次寫一個字節數組
public void write(byte[] bs, int startIndex, int len);一次寫一個字節數組的一部分
public void flush();刷新緩衝區(對於字節流來說沒用)
public void close();關閉流(釋放資源)
3.FileOutputStream類的使用*****************
FileOutputStream文件的字節輸出流
a.構造方法
public FileOutputStream(String pathname);
public FileOutputStream(File file);
/**
* FileOutputStream的構造方法
*/
public class FileOutputStreamDemo01 {
public static void main(String[] args) throws Exception {
//1.構造方法
FileOutputStream fos = new FileOutputStream("1.txt");
// FileOutputStream fos = new FileOutputStream(new File("1.txt"));
/**
* 以上構造幹了三件事!!!
* a.創建對象fos
* b.判斷文件是否存在
* 不存在,自動創建!!!
* 存在,會清空文件內容
* c.讓fos對象和1.txt綁定了
*/
}
}
b.寫字節數據的三個方法*****************
public void write(int b); 一次寫一個字節
public void write(byte[] bs); 一次寫一個字節數組
public void write(byte[] bs, int startIndex, int len); 一次寫一個字節數組的一部分
/**
* FileOutputStream的構造方法
*/
public class FileOutputStreamDemo02 {
public static void main(String[] args) throws Exception {
//1.構造方法
FileOutputStream fos = new FileOutputStream("1.txt");
//2.寫字節數據三個方法
//a.一次寫單個字節
fos.write(97);//0110 0001
//問題:現在我需要打開記事本後看到97,怎麼做?
fos.write(57); //9的二進制 57
fos.write(55); //9的二進制 57
//問題:現在我需要打開記事本後看到java,怎麼做?
fos.write(106);
fos.write(97);
fos.write(118);
fos.write(97);
//b.一次寫一個字節數組
byte[] bs = {106,97,118,97};
fos.write(bs);
//問題:現在我需要打開記事本後看到ghjkvbnmtyudsagdhfwertygasdfg,怎麼做?
//使用String類中的getBytes方法,自動把字符串中的字母變成碼值
byte[] bs1 = "Java我愛你".getBytes();
fos.write(bs1);
//c.一次寫一個字節數組的一部分
byte[] bs2 = {106,97,118,97};
fos.write(bs2,1,2);
}
}
c.如何追加/續寫
想要追加文件只需要使用以下構造即可
public FileOutputStream(String pathname, boolean append);
public FileOutputStream(File file, boolean append);
/**
* FileOutputStream的追加/續寫
*/
public class FileOutputStreamDemo03 {
public static void main(String[] args) throws Exception {
//1.追加創建對象
// FileOutputStream fos = new FileOutputStream("1.txt",true);//true表示追加,默認是false
FileOutputStream fos = new FileOutputStream(new File("1.txt"),true);//true表示追加,默認是false
//2.調用寫數據方法
fos.write("你喜歡嗎?".getBytes());
}
}
d.如何換行
很簡單,只需要向文件寫一個換行符即可
window:\r\n
Linux: \n
Mac: \r(MacOS X之後換行變爲\n)
/**
* FileOutputStream的換行
*/
public class FileOutputStreamDemo04 {
public static void main(String[] args) throws Exception {
//1.創建輸出流
FileOutputStream fos = new FileOutputStream("1.txt");
//2.寫數據
for (int i = 0; i < 10; i++) {
fos.write("java".getBytes());
//寫一個換行符
fos.write("\r\n".getBytes());
}
}
}
e.flush和close
public void flush(); 刷新緩衝區(對於字節流來說沒用,是一個空方法,對字符流纔有用)
public void close(); 釋放資源
/**
* FileOutputStream的flush和close
*/
public class FileOutputStreamDemo04 {
public static void main(String[] args) throws Exception {
//1.創建輸出流
FileOutputStream fos = new FileOutputStream("1.txt");
//2.寫數據
for (int i = 0; i < 10; i++) {
fos.write("java".getBytes());
//寫一個換行符
fos.write("\r\n".getBytes());
}
//3.刷新
// fos.flush();
//4.關閉
fos.close();
}
}
總結:
-[] 能夠說出File對象的創建方式
public File(String pathname);
-[] 能夠使用File類常用方法
public File listFiles();
-[] 能夠辨別相對路徑和絕對路徑
-[] 能夠遍歷文件夾(list和listFiles)
-[] 能夠解釋遞歸的含義
-[] 能夠使用遞歸的方式計算5的階乘(1*2*3*4*5)
-[] 能夠說出使用遞歸會內存棧溢出的隱患的原因
-[] 能夠說出IO流的分類和功能
輸入流 讀
輸出流 寫
-[] 能夠使用文件的字節輸出流向文件中寫出數據到文件中***
blic void write(int b);一次寫一個字節
public void write(byte[] bs);一次寫一個字節數組
public void wirte(byte[] bs,int startIndex,int len);一次寫一個字節數組的一部分