当前位置: 首页 > 新闻动态 > 网络资讯

在Java里如何实现简易记事本应用_Java文本存储项目实战说明

作者:P粉602998670 浏览: 发布日期:2026-01-27
[导读]:简易记事本必须用SwingUtilities.invokeLater启动EDT,JTextArea需启用换行,关闭前用DocumentListener检测修改并提示保存,读写文件须显式指定UTF-8编码,且区分currentFile与lastSavedTo管理路径。
简易记事本必须用SwingUtilities.invokeLater启动EDT,JTextArea需启用换行,关闭前用

DocumentListener检测修改并提示保存,读写文件须显式指定UTF-8编码,且区分currentFile与lastSavedTo管理路径。

JFrame + JTextArea 搭出基础界面,别碰 SwingUtilities.invokeLater 就跑不起来

Java 简易记事本的核心不是功能多全,而是能立刻打开、输入、保存、再打开——界面必须在事件分发线程(EDT)里构建。漏掉 SwingUtilities.invokeLater,窗口可能黑屏、无响应,甚至 JTextArea 不接收键盘输入。

  • 所有 Swing 组件(JFrameJTextAreaJMenuBar)必须包在 SwingUtilities.invokeLater 里初始化
  • JTextArea 要设 setLineWrap(true)setWrapStyleWord(true),否则长行直接撑破窗口
  • 别用 JFrame.pack() 后直接 setVisible(true) 就完事——先调 setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE),否则点关闭就彻底退出,来不及弹保存提示

文件读写用 Files.readAllLinesFiles.write,别手写 BufferedReader / FileWriter

Java 7+ 的 Files 工具类封装了编码、异常、资源释放细节,比手动开流安全得多。尤其 Windows 记事本默认存为 GBK,而 Java 默认用 UTF-8 读会乱码——必须显式指定字符集。

  • 读文件:Files.readAllLines(Paths.get(filePath), StandardCharsets.UTF_8),拼成字符串用 String.join("\n", lines)
  • 写文件:Files.write(Paths.get(filePath), content.getBytes(StandardCharsets.UTF_8)),别用 getOutputStream() 再套 Writer,容易漏 flush
  • 如果用户用系统记事本保存过文件,且含中文,大概率是 GBK 编码——可加试探逻辑:先按 UTF-8 读,捕获 MalformedInputException 后改用 GBK

监听关闭和菜单动作时,用 DocumentListener 判断是否修改,而不是靠布尔标记

boolean isModified 手动开关,极易不同步:粘贴、撤销、拖入文本都会漏触发。真正可靠的修改状态,得监听 JTextArea.getDocument() 的底层变更。

  • textArea.getDocument() 添加 DocumentListener,在 insertUpdateremoveUpdatechangedUpdate 里统一设 isModified = true
  • 保存后立刻调 document.removeDocumentListener(...),再 document.addDocumentListener(...),避免重复监听
  • 关闭前检查:if (isModified) { showSaveDialog(); },但注意:用户点“不保存”后,要重置 isModified = false,否则下次关窗又弹

“另存为”必须重置当前路径和文件名,否则“保存”会覆盖错误位置

很多初学者把“保存”和“另存为”共用一个 currentFile 字段,但“另存为”选新路径后没更新它,导致后续点“保存”仍写回旧文件——这会让用户以为内容丢了。

  • 声明两个字段:private File currentFile;(当前编辑的源文件)和 private File lastSavedTo;(上次实际写入位置),区分语义
  • “另存为”成功后,必须同时更新 currentFile = selectedFilelastSavedTo = selectedFile
  • “保存”逻辑优先写入 lastSavedTo;若为 null(即首次保存),则跳转到“另存为”流程
  • 菜单项禁用逻辑:saveMenuItem.setEnabled(lastSavedTo != null || currentFile != null),避免灰掉却无法操作
public class SimpleNotepad {
    private JFrame frame;
    private JTextArea textArea;
    private File currentFile;
    private File lastSavedTo;

    public SimpleNotepad() {
        SwingUtilities.invokeLater(() -> {
            frame = new JFrame("简易记事本");
            textArea = new JTextArea();
            textArea.setLineWrap(true);
            textArea.setWrapStyleWord(true);

            frame.add(new JScrollPane(textArea));
            frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
            frame.setSize(600, 400);

            setupMenu();
            setupCloseHandler();

            frame.setVisible(true);
        });
    }

    private void setupCloseHandler() {
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                if (isModified()) {
                    int result = JOptionPane.showConfirmDialog(frame,
                        "内容已修改,是否保存?", "确认", JOptionPane.YES_NO_CANCEL_OPTION);
                    if (result == JOptionPane.YES_OPTION) {
                        save();
                        frame.dispose();
                    } else if (result == JOptionPane.NO_OPTION) {
                        frame.dispose();
                    }
                } else {
                    frame.dispose();
                }
            }
        });
    }

    private boolean isModified() {
        // 实际项目中这里应结合 DocumentListener 状态判断
        return false; // 占位,真实逻辑见上文 DocumentListener 部分
    }

    private void save() {
        if (lastSavedTo != null) {
            writeToFile(lastSavedTo, textArea.getText());
        } else {
            saveAs();
        }
    }

    private void saveAs() {
        JFileChooser chooser = new JFileChooser();
        int result = chooser.showSaveDialog(frame);
        if (result == JFileChooser.APPROVE_OPTION) {
            File file = chooser.getSelectedFile();
            if (!file.getName().endsWith(".txt")) {
                file = new File(file.getParent(), file.getName() + ".txt");
            }
            writeToFile(file, textArea.getText());
            currentFile = file;
            lastSavedTo = file;
        }
    }

    private void writeToFile(File file, String content) {
        try {
            Files.write(file.toPath(), content.getBytes(StandardCharsets.UTF_8));
        } catch (IOException e) {
            JOptionPane.showMessageDialog(frame, "保存失败:" + e.getMessage());
        }
    }

    public static void main(String[] args) {
        new SimpleNotepad();
    }
}
文件编码兼容性、修改状态同步、保存路径管理——这三个点卡住绝大多数人的第一版实现。尤其是“另存为”后忘记更新 currentFile,问题会延迟暴露:用户编辑半小时,点“保存”却写进上周的文件里。
免责声明:转载请注明出处:http://shjed.com/news/728523.html

扫一扫高效沟通

多一份参考总有益处

免费领取网站策划SEO优化策划方案

请填写下方表单,我们会尽快与您联系
感谢您的咨询,我们会尽快给您回复!