本文部分内容引用《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;
}
}
}
}
程序框架structure
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";
}//D: \JAVA \src\task02\文件1.txt
out = new FileWriter(filePath);//构造输出流
}
out.write(message);//写入暂存的内容
out.close();//关闭输出流
message = null;//修改文件前先将写入内容清空
filePath = null;//将文件路径置空
//待完成操练结束
}
第5行代码根据路径的全局变量是否为空,来判断此时内容的全局变量是新建文件产生的还是打开文件产生的。
如果是打开 文件产生的,则将此文件覆盖掉;
如果是新建文件产生的,则从获得控制台输入的路径之后,判断其是否是.txt,如果不是则将其转换成.txt。再将message中暂存的内容写入文本文件。最后将文件路径filePath 和文件内容message的全局变量置空。
D: \JAVA \src\task02\文件1.txt
补充:
.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);
}
六、核心知识(技术心得)
读取文件
1.建立一个流对象,将已存在的一个文件加载进流。
FileReader fr = new FileReader(new File(“Test.txt”));
2.创建一个临时存放数据的数组。
char[] ch = new char[1024];
3.调用流对象的读取方法将流中的数据读入到数组中。
fr.read(ch);
4. 关闭资源。
fr.close();
写入文件
1.创建流对象,建立数据存放文件
FileWriter fw = new FileWriter(new File(“Test.txt”));
2.调用流对象的写入方法,将数据写入流
fw.write(“fanyouzhaoshuaidaile”);
3.关闭流资源,并将流中的数据清空到文件中。
fw.close();
注意
字符流操作字符,只能操作普通文本文件。
最常见的文本文件:.txt,.java,.c,.cpp 等语言的源代码。
尤其注意.doc,excel,ppt这些不是文本文件。
七、完整源码
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);
}
}