本文部分內容引用《JAVA基礎案例教程》-黑馬程序員
第14次-文件操作之字節流和字符流實訓-task02文件操作實訓之模擬記事本-貪吃的釗釗黑。
指導老師:範暢
一、任務描述
編寫一個模擬記事本的程序,通過在控制檯輸入指令,實現在本地新建文件、打開文件和修改文件等功能。
功能:
用戶輸入指令1代表“新建文件"
用戶輸入指令2代表“打開文件”
用戶輸入指令3代表“修改文件”
用戶輸入指令4代表“保存文件"
用戶輸入指令5代表“退出”
二、運行結果
三、任務目標
●學會分析“模擬記事本”任務的實現思路。
●能夠根據思路獨立完成“模擬記事本”程序的源代碼編寫、編譯及運行。
●掌握利用字符流操作本地文件的方法。
四、實現思路
(1)根據任務介紹和運行結果分析可知,此任務需要創建一個記事本類,在類中可以使用 while循環實現控制檯中操作指令的多次輸入,使用switch語句根據控制檯輸入的操作指令來判 斷執行什麼操作。
(2)輸入指令1時進行新建文件操作,此時需要從控制檯獲取輸入的內容並暫存到全局變量 中,以便後期進行保存和修改內容時使用。可以使用StringBuffer來保存控制檯中每次輸入的內 容,輸入內容時可能會涉及換行,這裏可以使用while循環來循環輸入,每循環一次都將控制檯 獲取的內容拼接換行符後,追加到文本內容中。當內容中輸入“stop"字符串時,輸入文本內容 的操作結束,並將新建文本的內容暫存在全局變量中。
(3)執行指令2時,可以打開指定路徑的文件,由於是模擬記事本程序,因此限定此功能只 支持打開txt文件。此操作首先要獲取輸入的路徑,判斷此路徑的文件是否是txt文件,如果是則 通過字符流讀取此文件,然後將此文件的內容打印至控制檯,並且暫存在全局變量中,將文件的 路徑也保存至全局變量中。
(4)執行指令3時,可以對暫存在全局變量中的文本內容進行修改,修改後的內容也需要暫存到全局變量中。此操作首先要判斷一下修改之 前是否先經過新建文件或者打開文件操作,當確 認經過上述操作後,可以將輸入的字符串與文本內容中目標字符串進行替換,來完成修改內容功 能。修改過程可通過while循環來進行多次的修改,當捕捉到“stop" 字符串時修改結束,並將 修改後的內容暫存到全局變量中。
(5)執行指令4時,將所有全局變量中的內容保存至本地,如果是新建的文件則保存至用戶 輸入的路徑,如果是打開後的文件則將原文件覆蓋。可以通過文件路徑的全局變量判斷是哪種保 存方式,當是打開文件的方式時,直接通過字符流寫入;當是新建的方式時,先獲取用戶輸入的 路徑,再用字符流寫入。
(6)執行指令5,直接退出系統,可以通過代碼“System.exit();" 實現。
五、實現代碼
1、創建記事本類
(1)在主函數中輸出指令說明
public class Notepad {
public static void main(String[] args) throws Exception {
System.out.println("--1:新建文件 2:打開文件 3:修改文件 4:保存 5:退出--");
}
}
(2)通過while循環實現重複輸入,在循環中使用switch語句對應相應的功能。
public class Notepad {
public static void main(String[] args) throws Exception {
System.out.println("--1:新建文件 2:打開文件 3:修改文件 4:保存 5:退出--");
Scanner sc = new Scanner(System.in);
while (true) {
System.out.print("請輸入操作指令:");
int command = sc.nextInt();
switch (command) {
case 1:
createFile();// 1:新建文件
break;
case 2:
openFile();// 2:打開文件
break;
case 3:
editFile();// 3:修改文件
break;
case 4:
saveFile();// 4:保存
break;
case 5:
exit();// 5:退出
break;
default:
System.out.println("您輸入的指令錯誤!");
break;
}
}
}
}
2、下面我們一一寫出這5個功能的實現代碼。
(1)createFile()
下面寫case 1 新建方法:createFile()
首先定義一個全局變量String message,用來存放文件中的暫存內容,初始爲null。
public class Notepad {
...
private static String message = null;//文件中的暫存內容
...
}
再通過臨時參數inputMessage將輸入的文字信息一次次地追加、拼接,直到輸入stop,最後再傳遞到message 中。
代碼及詳細註釋如下:
private static void createFile() {
message = "";// 新建文件時,暫存文件內容清空
Scanner sc = new Scanner(System.in);
System.out.println("請輸入內容,停止編寫請輸入\"stop\":");// 提示
StringBuffer stb = new StringBuffer();// 字符緩衝區,用於後期輸入內容的拼接
String inputMessage = "";//記錄每一次輸入的內容
while (!inputMessage.equals("stop")) {// 當輸入“stop”時,停止輸入
if (stb.length() > 0) {
stb.append("\r\n");// 追加換行符
}
stb.append(inputMessage);// 追加,拼接輸入信息
inputMessage = sc.nextLine();// 獲取輸入信息
}
message = stb.toString();// 將輸入內容暫存
}
可以看到,這裏我們定義了一個字符緩衝區 stb ,通過while循環我們把inputMessage中的文字內容拼接到stb中,最後再完整地將字符緩衝區 stb中的內容一次性傳遞給message。
(2)saveFile()
新建文件之後,接下來我們寫保存方法,case 4 保存方法:saveFile()
首先定義一個全局變量String filePath,用來存放文件的路徑,初始爲null。
public class Notepad {
...
private static String filePath = null;//文件路徑
...
}
private static void saveFile() throws IOException {
//待完成操練開始
Scanner sc = new Scanner(System.in);
FileWriter out = null;
if(filePath != null){//文件是由“打開”載入的
out = new FileWriter(filePath);//將原文件覆蓋
} else {//新建的文件
System.out.print("請輸入文件保存的絕對路徑:");
String path = sc.next();//獲取文件保存的路徑
filePath = path;
//將輸入路徑中大寫字母替換成小寫字母后判斷是不是文本格式
if (!filePath.toLowerCase().endsWith(".txt")) {
filePath +=".txt";
}
out = new FileWriter(filePath);//構造輸出流
}
out.write(message);//寫入暫存的內容
out.close();//關閉輸出流
message = null;//修改文件前先將寫入內容清空
filePath = null;//將文件路徑置空
//待完成操練結束
}
第5行代碼根據路徑的全局變量是否爲空,來判斷此時內容的全局變量是新建文件產生的還是打開文件產生的。
如果是打開 文件產生的,則將此文件覆蓋掉;
如果是新建文件產生的,則從獲得控制檯輸入的路徑之後,判斷其是否是.txt,如果不是則將其轉換成.txt。再將message中暫存的內容寫入文本文件。最後將文件路徑filePath 和文件內容message的全局變量置空。
補充:
.toLowerCase()方法:
語法:public String toLowerCase()
功能:返回一個字符串,該字符串中的字母被轉換成小寫字母,而且對非字母字符不會產生影響。
與之對應的方法是toUpperCase()方法。
.endsWith()
語法:public boolean endsWith(String suffix)
參數:suffix – 指定的後綴。
功能:如果參數表示的字符序列是此對象表示的字符序列的後綴,則返回 true;否則返回 false。
(3)openFile()
接下來我們寫打開方法,case 2 打開方法:openFile()
private static void openFile() throws Exception {
//待完成操練開始
message = "";//打開文件時,將暫存文件清空
Scanner sc = new Scanner(System.in);
System.out.print("請輸入打開文件的位置:");
filePath = sc.next();//獲取打開文件的路徑
//判斷打開的文件是否爲.txt文件
if (filePath != null && !filePath.endsWith(".txt")) {
System.out.print("請選擇文本!");
return;
}
FileReader in = new FileReader(filePath);//實例化一個FileReader對象
char[] charArray = new char[1024];//緩存數組
int len = 0;
StringBuffer sb = new StringBuffer();
//循環讀取,一次讀取一個字符數組
while ((len = in.read(charArray)) != -1) {
sb.append(charArray);
}
message = sb.toString();//將打開文件內容暫存到message以便輸出打印
System.out.println("打開文件內容:" + "\r\n" + message);
in.close();
//待完成操練結束
}
首先獲取控制檯傳入的文件路徑,並將其存儲到filePath 全局變量中。判斷將要打開的文件的格式是否是.txt。利用字符輸入流讀取文件的內容。將StringBuffer中的內容轉成String 類型,並存 入全局變量message中,以便修改和保存時使用。
(4)editFile()
接下來我們寫修改方法,case 3 修改文件方法:editFile()
private static void editFile() {
if (message == "" && filePath == null) {
System.out.println("請先新建文件或者打開文件");
return;
}
Scanner sc = new Scanner(System.in);
System.out.println("請輸入要修改的內容(以 \"修改的目標文字:修改之後的文字\" 格式),"
+ "停止修改請輸入\"stop\":");
String inputMessage = "";
while (!inputMessage.equals("stop")) {// 當輸入stop時,停止修改
inputMessage = sc.nextLine();
if (inputMessage != null && inputMessage.length() > 0) {
// 將輸入的文字根據“:”拆分成數組
String[] editMessage = inputMessage.split(":");
if (editMessage != null && editMessage.length > 1) {
// 根據輸入的信息將文件中內容替換
message = message.replace(editMessage[0], editMessage[1]);
}
}
}
System.out.println("修改後的內容:" + "\r\n" + message);
}
使用while 循環實現多次替換文件內容的功能,首先獲取替換的指令,再將 輸入的內容通過英文的冒號:分割出(修改的目標文字,修改之後的文字),傳遞到字符串數組editMessage中,分別對應數組元素(editMessage[0], editMessage[1])。最後將內容的全局變量message進行替換。打印。
補充:
.split
語法:stringObject.split(separator)
參數:separator 字符串或正則表達式,從該參數指定的地方分割 stringObject。
功能:把一個字符串分割成字符串數組。
.replace
語法:stringObject.replace(target,replacement)
參數:target需要被替換的字符,replacement替換後的字符。
功能:在字符串中用一些字符替換另一些字符
(5)exit()
case 5 退出方法:exit()
輸出結束語友好提示,然後調用系統退出方法。
private static void exit() {
System.out.println("您已退出系統,謝謝使用!");
System.exit(0);
}
六、完整源碼
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
/**
* 模擬記事本程序
*/
public class Notepad {
private static String filePath = null;//文件路徑
private static String message = null;
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
System.out.println("--1:新建文件 2:打開文件 3:修改文件 4:保存 5:退出--");
while (true) {
System.out.print("請輸入操作指令:");
int command = sc.nextInt();
switch (command) {
case 1:
createFile();// 1:新建文件
break;
case 2:
openFile();// 2:打開文件
break;
case 3:
editFile();// 3:修改文件
break;
case 4:
saveFile();// 4:保存
break;
case 5:
exit();// 5:退出
break;
default:
System.out.println("您輸入的指令錯誤!");
break;
}
}
}
/**
* 新建文件 從控制檯獲取內容
*/
private static void createFile() {
message = "";// 新建文件時,暫存文件內容清空
Scanner sc = new Scanner(System.in);
System.out.println("請輸入內容,停止編寫請輸入\"stop\":");// 提示
StringBuffer stb = new StringBuffer();// 用於後期輸入內容的拼接
String inputMessage = "";
while (!inputMessage.equals("stop")) {// 當輸入“stop”時,停止輸入
if (stb.length() > 0) {
stb.append("\r\n");// 追加換行符
}
stb.append(inputMessage);// 拼接輸入信息
inputMessage = sc.nextLine();// 獲取輸入信息
}
message = stb.toString();// 將輸入內容暫存
}
/**
* 打開文件
*/
private static void openFile() throws Exception {
//待完成操練開始
message = "";//打開文件時,將暫存文件清空
Scanner sc = new Scanner(System.in);
System.out.print("請輸入打開文件的位置:");
filePath = sc.next();//獲取打開文件的路徑
//判斷打開的文件是否爲.txt文件
if (filePath != null && !filePath.endsWith(".txt")) {
System.out.print("請選擇文本!");
return;
}
FileReader in = new FileReader(filePath);//實例化一個FileReader對象
char[] charArray = new char[1024];//緩存數組
int len = 0;
StringBuffer sb = new StringBuffer();
//循環讀取,一次讀取一個字符數組
while ((len = in.read(charArray)) != -1) {
sb.append(charArray);
}
message = sb.toString();//將打開文件內容暫存到message以便輸出打印
System.out.println("打開文件內容:" + "\r\n" + message);
in.close();
//待完成操練結束
}
/**
* 修改文件內容 通過字符串替換的形式
*/
private static void editFile() {
if (message == "" && filePath == null) {
System.out.println("請先新建文件或者打開文件");
return;
}
Scanner sc = new Scanner(System.in);
System.out.println("請輸入要修改的內容(以 \"修改的目標文字:修改之後的文字\" 格式),"
+ "停止修改請輸入\"stop\":");
String inputMessage = "";
while (!inputMessage.equals("stop")) {// 當輸入stop時,停止修改
inputMessage = sc.nextLine();
if (inputMessage != null && inputMessage.length() > 0) {
// 將輸入的文字根據“:”拆分成數組
String[] editMessage = inputMessage.split(":");
if (editMessage != null && editMessage.length > 1) {
// 根據輸入的信息將文件中內容替換
message = message.replace(editMessage[0], editMessage[1]);
}
}
}
System.out.println("修改後的內容:" + "\r\n" + message);
}
/**
* 保存 新建文件存在用戶輸入的路徑 打開的文件將原文件覆蓋
*/
private static void saveFile() throws IOException {
//待完成操練開始
Scanner sc = new Scanner(System.in);
FileWriter out = null;
if(filePath != null){//文件是由“打開”載入的
out = new FileWriter(filePath);//將原文件覆蓋
} else {//新建的文件
System.out.print("請輸入文件保存的絕對路徑:");
String path = sc.next();//獲取文件保存的路徑
filePath = path;
//將輸入路徑中大寫字母替換成小寫字母后判斷是不是文本格式
if (!filePath.toLowerCase().endsWith(".txt")) {
filePath +=".txt";
}
out = new FileWriter(filePath);//構造輸出流
}
out.write(message);//寫入暫存的內容
out.close();//關閉輸出流
message = "";//修改文件前先將寫入內容清空
filePath = null;//將文件路徑置空
//待完成操練結束
}
/**
* 退出
*/
private static void exit() {
System.out.println("您已退出系統,謝謝使用!");
System.exit(0);
}
}