0

0

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

P粉602998670

P粉602998670

发布时间:2026-01-27 12:42:10

|

458人浏览过

|

来源于php中文网

原创

简易记事本必须用SwingUtilities.invokeLater启动EDT,JTextArea需启用换行,关闭前用DocumentListener检测修改并提示保存,读写文件须显式指定UTF-8编码,且区分currentFile与lastSavedTo管理路径。

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

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() 的底层变更。

听脑AI
听脑AI

听脑AI语音,一款专注于音视频内容的工作学习助手,为用户提供便捷的音视频内容记录、整理与分析功能。

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

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

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

立即学习Java免费学习笔记(深入)”;

  • 声明两个字段: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,问题会延迟暴露:用户编辑半小时,点“保存”却写进上周的文件里。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

422

2023.08.02

java中boolean的用法
java中boolean的用法

在Java中,boolean是一种基本数据类型,它只有两个可能的值:true和false。boolean类型经常用于条件测试,比如进行比较或者检查某个条件是否满足。想了解更多java中boolean的相关内容,可以阅读本专题下面的文章。

350

2023.11.13

java boolean类型
java boolean类型

本专题整合了java中boolean类型相关教程,阅读专题下面的文章了解更多详细内容。

29

2025.11.30

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

235

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

437

2024.03.01

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

775

2023.08.22

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

298

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

212

2023.09.04

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

10

2026.01.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 2.9万人学习

C# 教程
C# 教程

共94课时 | 7.7万人学习

Java 教程
Java 教程

共578课时 | 51.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号