注意
完成实验报告及源码链接:https://download.youkuaiyun.com/download/qq_29711355/85640708
一、实验目的:
练习输入/输出流的创建、转换及数据访问设计方法。
二、实验内容:
设计一个类似Windows记事本的Application应用程序。
三、实验要求:
1、采用Java Application方式建立应用程序框架;
2、仿照Windows记事本,实现界面设计;
3、完成菜单(新建、打开、保存)设计及事件设计。完成以上内容选做选做:设定循环加解密规则如下:按照ASCII字符编码(0-255),加密时对每一字符+10,(若超过255,减去255),解密时作对应反变换。编程实现文件的“新建”、“打开”(将加密文本文件“D:\1.txt”解密后打开)和“保存”(将新建或打开并修改过的文件加密保存至“D:\1.txt”中)操作。
四、实验报告内容要求:
1、简要说明记事本图形用户界面的设计过程;
2、深入分析各功能菜单的工作流程;
3、完整介绍各功能菜单的具体设计与实现过程。
4、简要说明你在该实验中的收获与体会。
参考代码
Notepad 类
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.text.Normalizer;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class Notepad extends JFrame{
//定义文件名
private static String fileName = null;
//文件内容
private static String fileContent = null;
//定义选择栏(从上到下)
private JMenuBar jMenuBar = new JMenuBar();
//定义文件菜单
private JMenu jMenu_file= new JMenu("文件");
//定义文件菜单中的子选项
private JMenuItem jMenuItem1 = null;
private JMenuItem jMenuItem2 = null;
private JMenuItem jMenuItem3 = null;
private JMenuItem jMenuItem4 = null;
//定义格式菜单
private JMenu jMenu_eidt= new JMenu("格式");
//定义格式菜单中的子选项
private JMenuItem jMenuItem5 = null;
//定义帮助菜单
private JMenu jMenu_help= new JMenu("帮助");
//定义帮助菜单中的子选项
private JMenuItem jMenuItem6 = null;
//定义文本域
private JTextArea jTextArea = new JTextArea();
//定义监听类对象
private MyActionListener myActionListener = new MyActionListener();
//定义并实例化一个文件选择框
private JFileChooser jFileChooser = new JFileChooser("F:\\");;
//定义文件输入流
private InputStreamReader inputStreamReader = null;
//定义字符输入流缓冲区
private BufferedReader bufferedReader = null;
//定义文件输出流
private FileOutputStream fileOutputStream = null;
private OutputStreamWriter outputStreamWriter =null;
//判断自动换行是否激活
private boolean lineFeed = false;
//定义滚动条
private JScrollPane jScrollPane = null;
//构造函数
public Notepad() {
super("记事本");
this.loadNorth();
this.init();
}
//初始化函数
private void init() {
//设置整体基本布局
//添加Windows窗口关闭监听事件
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
Notepad.this.exit();
}
});
setSize(new Dimension(800,600));
setLocationRelativeTo(null);
//添加菜单栏
setJMenuBar(jMenuBar);
//实例化滚动条对象,并添加垂直,水平滚动条(在需要的时候)
jScrollPane = new JScrollPane();
jScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
jScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
//添加滚动条只能用setViewportView()
jScrollPane.setViewportView(jTextArea);
//添加文本域
add(jScrollPane);
setVisible(true);
}
//添加顶部分控件(菜单栏)
//布局设置函数
private void loadNorth() {
jMenuItem1 = new JMenuItem("新建");
jMenuItem2 = new JMenuItem("打开");
jMenuItem3 = new JMenuItem("保存");
jMenuItem4 = new JMenuItem("退出");
jMenuItem5 = new JMenuItem("自动换行");
jMenuItem6 = new JMenuItem("关于记事本");
jMenu_file.add(jMenuItem1);
jMenu_file.add(jMenuItem2);
jMenu_file.add(jMenuItem3);
jMenu_file.add(jMenuItem4);
jMenu_eidt.add(jMenuItem5);
jMenu_help.add(jMenuItem6);
jMenuBar.add(jMenu_file);
jMenuBar.add(jMenu_eidt);
jMenuBar.add(jMenu_help);
jMenuBar.setVisible(true);
//为选项添加监听事件
jMenuItem1.addActionListener(myActionListener);
jMenuItem2.addActionListener(myActionListener);
jMenuItem3.addActionListener(myActionListener);
jMenuItem4.addActionListener(myActionListener);
jMenuItem5.addActionListener(myActionListener);
jMenuItem6.addActionListener(myActionListener);
}
//设置监听事件内部类
private class MyActionListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
String strClick = e.getActionCommand();
switch (strClick) {
case "新建":{
//新建条件1:如果文本区域为空,并且名字也为空(表示是一个空白的文件)或者已经有打开的文件,文件内容和文本区域内容一致则表示文件只是打开了但没有修改无需保存,直接初始化
if (Notepad.fileName == null && Notepad.this.jTextArea.getText().equals("")
|| Notepad.this.jTextArea.getText().equals(Notepad.fileContent)) {
System.out.println("新建1");
JOptionPane.showMessageDialog(null, "已新建!");
}
//新建条件2:①:文件为新建文件,但是有内容,②:文件为打开的文件,但是修改过
else {
System.out.println("新建2");
int answer = JOptionPane.showConfirmDialog(null, "是否保存?","温馨提示",JOptionPane.YES_NO_OPTION);
switch (answer) {
case 0:{
Notepad.this.saveFileByChooser();
break;
}
case 1:
break;
default:
break;
}
}
//将所有参数初始化
Notepad.fileName = null;
Notepad.fileContent = null;
Notepad.this.jTextArea.setText("");
Notepad.this.setTitle("新建 - 记事本");
System.out.println("新建");
break;
}
case "打开":{
//打开条件1:如果文本区域为空,并且名字也为空(表示是一个空白的文件),此时直接打开文件选择框就行
if (Notepad.fileName == null && Notepad.this.jTextArea.getText().equals("")) {
System.out.println("打开1");
openFileByChooser();
}
//打开条件2:如果已经打开的文件,文件内容和文本区域内容一致则表示文件只是打开了但没有修改无需保存,次直接打开文件选择框
else if (Notepad.this.jTextArea.getText().equals(Notepad.fileContent)) {
System.out.println("打开2");
Notepad.this.openFileByChooser();
}
//打开条件3:①:文件为新建文件,但是有内容,②:文件为打开的文件,但是修改过
else {
System.out.println("打开3");
int answer = JOptionPane.showConfirmDialog(null, "是否保存?","温馨提示",JOptionPane.YES_NO_OPTION);
switch (answer) {
case 0:
Notepad.this.saveFileByChooser();
openFileByChooser();
break;
case 1:
openFileByChooser();
break;
default:
break;
}
}
System.out.println("打开");
break;
}
case "保存":{
Notepad.this.saveFileByChooser();
//更新文件内容
Notepad.this.setTitle(Notepad.fileName + " - 记事本");
System.out.println("保存");
break;
}
case "退出":{
Notepad.this.exit();
System.out.println("退出");
break;
}
case "自动换行":{
Notepad.this.autoWrap();
System.out.println("自动换行" + Notepad.this.lineFeed);
break;
}
case "关于记事本":{
System.out.println("关于记事本");
String message = "记事本主要功能:\n"
+ "1.对文件的新建、打开、保存。\n"
+ "2.能够设置文本的自动换行\n"
+ "3.自动设置水平和垂直滚动条\n"
+ "4.能够按照ASCII字符编码(0-255)加密,加密时对每一字符+10,(若超过255,减去255),解密时作对应反变换。\n"
+"创作者:计科2003班--温明祥--5120205799";
JOptionPane.showMessageDialog(null, message, "关于'记事本'", JOptionPane.PLAIN_MESSAGE);
break;
}
default:
break;
}
}
}
//文件打开方法
private String openFile(String filePath) throws IOException {
this.inputStreamReader = new InputStreamReader(new FileInputStream(filePath),"utf-8");
this.bufferedReader = new BufferedReader(inputStreamReader);
String str_line = "";
String strAll = "";
while ((str_line = bufferedReader.readLine()) != null) {
strAll += str_line + "\r\n";
}
Notepad.fileContent = Notepad.decode(strAll);
bufferedReader.close();
inputStreamReader.close();
return strAll;
}
//通过选择框打开并设置到文本域
private void openFileByChooser() {
//设置打开文件选择框的标题
jFileChooser.setDialogTitle("打开");
//设置默认打开路径
jFileChooser.showOpenDialog(null);
//获取文件的绝对路径
String address = jFileChooser.getSelectedFile().getAbsolutePath();
//获取文件名,设置标题
Notepad.fileName = address;
Notepad.this.setTitle(Notepad.fileName + " - 记事本");
try {
//打开并读取文件内容
String strFile = decode(this.openFile(address));
jTextArea.setText(strFile);
} catch (IOException e1) {
e1.printStackTrace();
}
}
//文件保存方法
private void saveFile(String filePath, String strFile) throws IOException {
this.fileOutputStream = new FileOutputStream(filePath);
this.outputStreamWriter = new OutputStreamWriter(this.fileOutputStream,"UTF-8");
strFile = Notepad.encode(strFile);
this.outputStreamWriter.write(strFile);
this.outputStreamWriter.flush();
this.outputStreamWriter.close();
this.fileOutputStream.close();
JOptionPane.showMessageDialog(null, "保存成功!");
}
//判断并通过选择框保存
private void saveFileByChooser() {
String strFile = Notepad.this.jTextArea.getText();
if (Notepad.fileName != null) {
try {
this.saveFile(Notepad.fileName, strFile);
} catch (IOException e1) {
e1.printStackTrace();
}
}else if(!Notepad.this.jTextArea.getText().equals("")){
jFileChooser.setSelectedFile(new File(".txt"));
jFileChooser.setDialogTitle("保存");
jFileChooser.showSaveDialog(null);
String address = jFileChooser.getSelectedFile().getAbsolutePath();
Notepad.fileName = address;
try {
this.saveFile(Notepad.fileName, strFile);
} catch (IOException e1) {
e1.printStackTrace();
}
}else {
JOptionPane.showMessageDialog(null, "无内容,保存失败!");
}
Notepad.fileContent = strFile;
}
//退出函数,点击‘退出’和‘关闭’时调用
private void exit() {
//退出条件1:如果文本区域为空,并且名字也为空(表示是一个空白的文件)或者已经有打开的文件,文件内容和文本区域内容一致则表示文件只是打开了但没有修改无需保存,直接初始化
if (Notepad.fileName == null && Notepad.this.jTextArea.getText().equals("")
|| Notepad.this.jTextArea.getText().equals(Notepad.fileContent)) {
System.out.println("退出1");
System.exit(0);
}
//退出条件2:①:文件为新建文件,但是有内容,②:文件为打开的文件,但是修改过
else {
System.out.println("退出2");
int answer = JOptionPane.showConfirmDialog(null, "是否保存?","温馨提示",JOptionPane.YES_NO_OPTION);
switch (answer) {
case 0:{
Notepad.this.saveFileByChooser();
System.exit(0);
break;
}
case 1:
System.exit(0);
break;
default:
break;
}
}
}
//设置自动换行功能
private void autoWrap() {
if (this.lineFeed) {
this.lineFeed = false;
}else {
this.lineFeed = true;
}
//设置换行功能
this.jTextArea.setLineWrap(this.lineFeed);
//设置断行不断字功能
this.jTextArea.setWrapStyleWord(this.lineFeed);
}
//字符串加密
public static String encode(String data) {
//把字符串转为字节数组
byte[] b = data.getBytes();
//遍历
for(int i=0;i<b.length;i++) {
if (b[i] == '\n' || b[i] == '\r' || 0 > b[i] || b[i] > 255) {
continue;
}
else if (0 <= b[i] && b[i] <= 255) {
if ( b[i] + 10 > 255) {
b[i] = (byte) (b[i] + 10 - 255);
}else {
b[i] += 10;//在原有的基础上+10
}
}
}
return new String(b);
}
/**
* 解密:把一个加密后的字符串在原有基础上-1
* @param data 加密后的字符串
* @return 返回解密后的新字符串
*/
public static String decode(String data) {
//把字符串转为字节数组
byte[] b = data.getBytes();
//遍历
for(int i=0;i<b.length;i++) {
if (b[i] == '\n' || b[i] == '\r' || 0 > b[i] || b[i] > 255) {
continue;
}
else if (0 <= b[i] && b[i] <= 255) {
if ( b[i] - 10 < 0) {
b[i] = (byte) (255 - (10 - b[i]));
}else {
b[i] -= 10;//在原有的基础上-10
}
}
}
return new String(b);
}
}
TestNoteopad 类
public class TestNotepad {
public static void main(String[] args) {
new Notepad();
}
}