从0开始的java学习实践之简单读写记事本
工具:Spring Tool Suite4
语言:Java
目标:以字节流的形式完成带界面的记事本的读写功能
完成时间:2020.02.28
STS的几个常用快捷键:
alt + / :显示匹配的方法
ctrl + shift + O : 自动导入使用的包
alt + shift + S:快速生成get&set方法
学习链接
带复杂界面的笔记本 在编写时以这篇博文为参考
Java字节流操作 这位博主有比较多的详细的java一些机制和运用解说,例如 JDBC连接数据库、Java注解、Java动态代理机制、Java API 正则表达式、字节流文件读取
ByteArrayOutputStream类-菜鸟 、ByteArrayOutputStream类-jdk 通过该方法可以在分段读取文件时进行整合
while((x = fileInputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, x-1);
}
ByteArrayInputStream和ByteArrayOutputStream详解
FilterInputStream-jdk、InputStream-jdk 字节流传输需要之后做一次集中整理
代码修改
在参考代码的基础上,发现了以下问题:
- 对打开的文件进行修改后保存时,新增内容与原本内容的编码方式不一致,第二次读入时会出现乱码
- 对保存文件时的逻辑进行优化处理,分离保存文件和创建文件判定
- 参考代码在选择关闭窗口时并未真正结束进程
修改方案:
- 在进行保存和读取的时候,分别手动确定转换的编码格式
// 保存时
bytes = jTextArea.getText().getBytes("GBK");
fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(bytes);
// 读取时
str = new String(bytes, 0, bytes.length, "gbk");
- 目前还没有完全分离,但是修改了一下判定规则 首先判断是否为第一次打开,其次判断内容是否为空。此外,元代码中未处理弹出确认窗口再取消之后的方法调用,修改后使用一个循环,来完成重复判定直到保存成功。
- 未结束进程是因为默认设置为隐藏 因此显式调整为退出
setDefaultCloseOperation(EXIT_ON_CLOSE); // 默认HIDE_ON_CLOSE 如要关闭整个程序 则改为EXIT_ON_CLOSE
代码ver4.0
对元参考代码进行了划分 分离底层数据操作部分
读写功能封装 class FileOption
package aaa;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
// javax.swing
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class FileOption extends JFrame{
// 实现文件读写相关功能
/**
* 序列化编码 默认1L
*/
private static final long serialVersionUID = 1L;
public static void main() {
}
// 保存文件
public void saveFile(File file, byte[] bytes ) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(bytes);
fileOutputStream.close();
}
// 打开文件
public byte[] readFile(File file) throws IOException{
byte[] bytes = null;
int x;
byte[] buffer = new byte[512];
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
FileInputStream fileInputStream = new FileInputStream(file);
while ((x = fileInputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, x);
}
bytes = byteArrayOutputStream.toByteArray();
fileInputStream.close();
return bytes;
}
// 弹出 是否保存 的选项框
public int showSaveDialog() {
int select = 0;
select = JOptionPane.showConfirmDialog(null, "是否保存当前文档?");
return select;
}
}
菜单ui class MyNote
package aaa;
// java.awt
import java.awt.BorderLayout; // 方位布局
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.File;
// java.io
import java.io.IOException;
// javax.swing
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.JScrollPane; // 滚动面板
import javax.swing.JTextArea; // 文本编辑区
// mine
import aaa.FileOption;
public class MyNote extends JFrame{
private static final long serialVersionUID = 1L;
private JTextArea jTextArea;
private JScrollPane jScrollPane;
private static String name;
private JFileChooser jFileChooser = new JFileChooser();
private FileOption fileOption = new FileOption(); // ??需要定义什么吗
private String tempStr = ""; //用于判断是否已修改
public static void main(String[] args) {
new MyNote().init();
}
public void init() {
setSize(800, 600);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
name = "新建文本文档.txt";
setTitle(name + " - 记事本");
// 添加菜单栏
addMenu();
// 添加文本框
jTextArea = new JTextArea();
// 添加滑动条
jScrollPane = new JScrollPane(jTextArea);
jScrollPane.setPreferredSize(new Dimension(780, 550));
add(jScrollPane, BorderLayout.CENTER); // java.awt.Container.add 将组件按位置增添到容器中
setVisible(true); // 设置窗口可见 java.awt.Window.setVisible
addWindowListener(new WindowAdapter() {
@Override // 子类重写父类方法注解
public void windowClosing(WindowEvent e) {
if (fileOption.showSaveDialog() != JOptionPane.CANCEL_OPTION) // 若不是取消按钮,关闭程序
setDefaultCloseOperation(3); // 3 = EXIT_ON_CLOSE
}
});
}
// 添加菜单栏
private void addMenu() {
// 添加菜单栏
JMenuBar jMenuBar = new JMenuBar();
// 设置菜单栏位置在顶级窗口的顶部(? 怎么体现顶部
setJMenuBar(jMenuBar); // javax.swing.JFrame.setJMenuBar
// 菜单栏菜单
JMenu jm_file = new JMenu("文件");
JMenu jm_edit = new JMenu("编辑");
jMenuBar.add(jm_file);
jMenuBar.add(jm_edit);
// 给文件栏添加选项
JMenuItem item1 = new JMenuItem("打开");
JMenuItem item2 = new JMenuItem("保存");
jm_file.add(item1);
jm_file.add(item2);
// 添加 打开 项的动作监听器
item1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (jFileChooser.getSelectedFile() == null) {
// first open
if (jTextArea.getText().equals("")) {
// nothing in it
try {
readFile();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} else {
// do write something
if (fileOption.showSaveDialog() == JOptionPane.YES_OPTION) {
// choose to save text
try {
createFile();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} // choose not, then open new file
}
} else {
// not first, have opened a text
if (!isSaved()) {
// haven't saved, then quest whether save
if (fileOption.showSaveDialog() == JOptionPane.YES_OPTION){
// choose to save text
try {
saveFile();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} // choose not, then open new file
}
try {
readFile();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
});
// 添加 保存 项的动作监听器
item2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (jFileChooser.getSelectedFile() == null) {
try {
createFile();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} // 如果是第一次打开 则调用创建方法
} else {
try {
if (!isSaved()) {
// haven't saved, then save
saveFile();
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
});
}
private void createFile() throws IOException {
int select, i;
File file = null;
while(true) {
select = jFileChooser.showOpenDialog(MyNote.this);
if (select == JFileChooser.APPROVE_OPTION) {
file = jFileChooser.getSelectedFile();
name = jFileChooser.getName(file);
if (file.exists()) {
i = JOptionPane.showConfirmDialog(null, "是否覆盖原文件?");
if (i == JOptionPane.YES_OPTION) {
saveFile();
break;
} else { // choose cancel, then go back and choose again
continue;
}
} else { // create a new one
saveFile();
break;
}
} else { // choose cancel then exit chooser
return;
}
}
}
private void saveFile() throws IOException {
File file = jFileChooser.getSelectedFile();
byte[] bytes = jTextArea.getText().getBytes("GBK");
fileOption.saveFile(file, bytes);
tempStr = jTextArea.getText();
}
private void readFile() throws IOException {
int select;
while(true) {
select = jFileChooser.showOpenDialog(MyNote.this);
if (select == JFileChooser.APPROVE_OPTION) {
break;
} else { // choose cancel or exit
return;
}
}
File file = jFileChooser.getSelectedFile();
byte[] bytes = fileOption.readFile(file);
String str = new String(bytes, 0, bytes.length,"gbk");
jTextArea.setText(str);
jTextArea.setCaretPosition(0);
name = jFileChooser.getSelectedFile().getName();
setTitle(name + " - 记事本");
tempStr = str;
}
// 判断文件是否保存
private Boolean isSaved() {
// 比较两者之间的内容(待改善
if (jTextArea.getText().equals(tempStr)) {
return true;
}
return false;
}
// here is the class end
}
这里ver4.0实际上是修改后的第四版了 前三版虽然有写在博客里,不过设置了仅自己可看 就不放出来丢人了
如有问题感谢指教!