用Java实现文本编辑器:创建、浏览、编辑文件;剪贴、复制、粘贴;保存、另存为;字符统计;自动换行

2023-11-10

Java做文本编辑器的项目,搜了下看到网上有各种版本的Java文本编辑器有很多种,但有的实现很麻烦,最近刚好在做这个实现就也发一个,代码写得很朴素,注释无比详细。

测试过没有Bug,如果有什么问题,欢迎探讨。代码供大家借鉴参考,欢迎交流。

用Java实现文本编辑器:创建,浏览、编辑文件;剪贴、复制、粘贴;保存以及另存为;统计字符

一、开发环境

二、程序模块功能描述

(一)文件

(二)编辑

(三)统计

(三)格式:

(四)帮助

三、关键Java API列表

四、运行结果


一、开发环境

开发环境:Windows 10操作系统;JDK 13.0.2

运行环境:JRE 13.0.2 

开发工具:Notepad++文本编辑器


二、程序模块功能描述

本项目完成的文本编译器菜单栏有四个选项:文件编辑格式帮助

(一)文件

文件下拉菜单包括“新建、打开、保存、另存为、退出”5个功能。

  1. 新建:创建一个新的文本。
  2. 打开:打开一个指定的文本文件。
  3. 保存:存储文本内容修改。
  4. 另存为:把文件存储在其他位置。
  5. 退出:关闭程序。

(二)编辑

编辑下拉菜单包括“剪切、复制、粘贴”3个功能。

  1. 剪切(可以使用快捷键Ctrl + X)
  2. 复制(可以使用快捷键Ctrl + C)
  3. 粘贴(可以使用快捷键Ctrl + V)

(三)统计

  统计下拉菜单中有“统计”选项。

  1. 统计:自动统计已输入字符中汉字、大小写字母等个数。

(三)格式:

格式下拉菜单有“自动换行”功能。

  1. 自动换行:勾选上会自动换行。

(四)帮助

帮助菜单下包括“帮助、关于”两个功能。

  1. 帮助:介绍了文本编辑器如何使用。
  2. 关于:编辑器开发相关信息。

三、关键Java API列表

java.awt.*;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
java.io.BufferedReader;
java.io.BufferedWriter;
java.io.File;
java.io.FileReader;
java.io.FileWriter;
java.io.IOException;
javax.swing.*;

主框架:

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import javax.swing.*;
 
public class TextFrame extends JFrame{
	
	public TextFrame()
	{
		super("简易文本编辑器");    //调用父类的构造方法
		//创建菜单栏(JMenuBar)对象
		JMenuBar mBar = new JMenuBar();
		//在JFrame等容器中设置菜单栏对象,即将菜单栏添加到框架容器中
		this.setJMenuBar(mBar);
		
		//创建菜单
		JMenu file = new JMenu("文件");
		JMenu edit = new JMenu("编辑");
            JMenu count = new JMenu("统计");
		JMenu form = new JMenu("格式");
		JMenu help = new JMenu("帮助");
		
		//将菜单添加到菜单栏中
		mBar.add(file);
		mBar.add(edit);
        mBar.add(count);
		mBar.add(form);
		mBar.add(help);
	    
		JTextArea workArea = new JTextArea();  //创建多行文本框
	    JScrollPane imgScrollPane = new JScrollPane(workArea);  //创建一个空视图,只要组件内容超过视图大小就会显示水平和垂直滚动条
	    add(imgScrollPane,BorderLayout.CENTER);  //将当前类的对象实例加到frame的中间位置
	    
	    //定义打开和保存对话框  
	    FileDialog openDia;
		FileDialog saveDia;  
		//默认模式为 FileDialog.LOAD  
        openDia = new FileDialog(this,"打开",FileDialog.LOAD);      
        saveDia = new FileDialog(this,"另存为",FileDialog.SAVE);  
	    
	    JMenuItem item1_1 = new JMenuItem("新建");  //生成一个对象
	    item1_1.addActionListener(new ActionListener(){ 
	    	public void actionPerformed(ActionEvent e){  //对当前的控件添加监听器,点击控件时就会触发监听函数里面的内容
	    	workArea.setText("");  //清空文本 
	    	}
	    });
	    JMenuItem item1_2 = new JMenuItem("打开");
	    item1_2.addActionListener(new ActionListener(){
	    	public void actionPerformed(ActionEvent e){  //对当前的控件添加监听器,点击控件时就会触发监听函数里面的内容
	    		openDia.setVisible(true);  //打开文件对话框
	    		String dirPath = openDia.getDirectory();  //获取打开文件路径并保存 
               String fileName = openDia.getFile();  //获取文件名称并保存 
              //判断打开路径或目录是否为空,则返回空  
                if(dirPath == null || fileName == null){
                	return ;
                }  
                workArea.setText("");//清空文本
                File fileO = new File(dirPath,fileName); 
                try{
                	BufferedReader bufr = new BufferedReader(new FileReader(fileO));      //尝试从文件中读取内容
                	String line = null;  //变量字符串初始化为空  
                	while((line = bufr.readLine()) != null){
                		workArea.append(line + "\r\n");  //显示每行内容
                	}
                	bufr.close();   //关闭文本
                }
catch(IOException er1){
                	throw new RuntimeException("文件读取失败!"); 
                }
	    	}
	    });

	    JMenuItem item1_3 = new JMenuItem("保存");
	    item1_3.addActionListener(new ActionListener(){
	    	public void actionPerformed(ActionEvent e){  //对当前的控件添加一个监听器,点击控件时就会触发监听函数里面的内容
	    		File fileS = null;
	    		if(fileS == null){
	    			saveDia.setVisible(true);  //显示保存文件对话框
                    String dirPath = saveDia.getDirectory();  //获取保存文件路径并保存到字符串中
                    String fileName = saveDia.getFile();  //获取保存文件名称并保存到字符串中
                    
                    if(dirPath == null || fileName == null)  //判断路径和文件是否为空
                    	return;  //返回空值
                    
                    fileS = new File(dirPath,fileName);  //文件不为空,新建一个路径和名称
	    		}
	    		try{
	    			BufferedWriter bufw = new BufferedWriter(new FileWriter(fileS));                           //尝试从文件中读取内容
	    			String text = workArea.getText();  //获取文本内容
	    			bufw.write(text);  //将获取文本内容写入到字符输出流
	    			bufw.close();  //关闭文件
	    		}catch(IOException er){
	    			throw new RuntimeException("文件保存失败!"); 
	    		}
	    	}
	    });

	    JMenuItem item1_4 = new JMenuItem("另存为");
	    item1_4.addActionListener(new ActionListener(){
	    	public void actionPerformed(ActionEvent e){   //对当前的控件添加一个监听器,点击控件时就会触发监听函数里面的内容
	    		File fileS = null;
	    		if(fileS == null){
	    			saveDia.setVisible(true);  //显示另存为文件对话框
	    			String dirPath = saveDia.getDirectory();  //获取保存文件路径并保存到字符串中
	                String fileName = saveDia.getFile();  //获取保存文件名称并保存到字符串中 
                    
	                if(dirPath == null || fileName == null) //判断路径和文件是否为空
	                return ;   //返回空值
	                fileS = new File(dirPath,fileName);  //文件不为空,新建一个路径和名称
	    		}
	    		try{
	    			BufferedWriter bufw = new BufferedWriter(new FileWriter(fileS));                          //尝试从文件中读取内容
	    			String text = workArea.getText();  //获取文本内容
	    			bufw.write(text);   //将获取文本内容写入到字符输出流
	    			bufw.close();  //关闭文件
	    		}
catch(IOException er){
	    			throw new RuntimeException("文件保存失败!"); 
	    		}
	    	}
	    });

	    JMenuItem item1_5 = new JMenuItem("退出");
	    item1_5.addActionListener(new ActionListener(){
	    	public void actionPerformed(ActionEvent e){  //对当前的控件添加一个监听器,点击控件时就会触发监听函数里面的内容
	    		System.exit(0);
	    	}
	    });
	    
	    //创建菜单项
	    JMenuItem item2_1 = new JMenuItem("剪切");
	    item2_1.addActionListener(new ActionListener(){
	    	public void actionPerformed(ActionEvent e){
	    		workArea.cut();
	    	}
	    });
	    
	    JMenuItem item2_2 = new JMenuItem("复制");
	    item2_2.addActionListener(new ActionListener(){
	    	public void actionPerformed(ActionEvent e){
	    		workArea.copy();
	    	}
	    });
	    
	    JMenuItem item2_3 = new JMenuItem("粘贴");
	    item2_3.addActionListener(new ActionListener(){
	    	public void actionPerformed(ActionEvent e){
	    		workArea.paste();
	    	}
	    });	    

        JMenuItem item2_4 = new JMenuItem("统计");
	    item2_4.addActionListener(new ActionListener(){
	    	public void actionPerformed(ActionEvent event){  //对当前的控件添加一个监听器,点击控件时就会触发监听函数里面的内容
	    		//try代码块,当发生异常时会转到catch代码块中
					String a = workArea.getText();//定义字符串变量,并赋值为用户输入的信息
					//创建类进行文件的读取,并指定编码格式为utf-8
					//char[] ch = a.toCharArray();//把字符串变成char数组
					int c = 0,h = 0,ll = 0,l = 0,n = 0,o = 0,sum = 0;//定义整型变量,用于统计字符数
					for(int i = 0;i<a.length();i++){
						String s = a.substring(i,i+1);
						if (s.matches("[\\u4e00-\\u9fa5]")) {//if语句的条件,判断是否为汉字
								h++;//若为汉字则c1自增
							} else if(s.matches("[A-Z]")){//if语句的条件,判断是否为大写字母
								ll++;//若为大写字母则c2自增
							} else if(s.matches("[a-z]")){//if语句的条件,判断是否为小写字母
								l++;//若为小写字母则c3自增
							} else if(s.matches("[0-9]")){//if语句的条件,判断是否为数字
								n++;//若为数字则c4自增
							} else {//否则可判断为其他字符
								o++;//若为其他字符则c5自增
							}
					}
						sum = h + ll + l + n + o ;//统计总字符数
						JOptionPane.showMessageDialog(TextFrame.this, "字数统计:\n汉字:"+h+"\n大写字母:"+ll+"\n小写字母:"+l+"\n数字:"+n+"\n其他字符:"+o+"\n共计"+sum);
			}
		});


	    JRadioButtonMenuItem item3_1 = new JRadioButtonMenuItem("自动换行",false);
	    item3_1.addActionListener(new ActionListener(){
	    	public void actionPerformed(ActionEvent e){  //对当前的控件添加一个监听器,点击控件时就会触发监听函数里面的内容
	    		Object source = e.getSource();
	    		if(source == item3_1)
	    			workArea.setLineWrap(true);  //自动换行
	    		else if(source != item3_1)
	    			workArea.setLineWrap(false);
	    	}
	    });
	    
	    JMenuItem item4_1 = new JMenuItem("帮助");
	    item4_1.addActionListener(new ActionListener(){
	    	public void actionPerformed(ActionEvent event){  //对当前的控件添加一个监听器,点击控件时就会触发监听函数里面的内容
	    		new Help();
	    	}
	    });
	    JMenuItem item4_2 = new JMenuItem("关于");
	    item4_2.addActionListener(new ActionListener(){
	    	public void actionPerformed(ActionEvent event){  //对当前的控件添加一个监听器,点击控件时就会触发监听函数里面的内容
	    		new About ();
	    	}
	    });
	    
	    //在菜单中添加菜单项
	    file.add(item1_1);file.add(item1_2);file.add(item1_3);file.add(item1_4);file.add(item1_5);
	    edit.add(item2_1);edit.add(item2_2);edit.add(item2_3);
	    form.add(item3_1);
	    help.add(item4_1);help.add(item4_2);
	    
	    
	}//构造方法结束	
	
	public static void main(String args[])
	{
		TextFrame app = new TextFrame();
		
		app.setSize(600, 400);  //设置窗口大小,宽度600,高度400
		app.setLocation(200,200);  //设置窗口位置为距离屏幕左边水平方向200,上方垂直方向200
		app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);   //点击关闭按钮是直接退出
		app.setVisible(true);  //设置窗体可见
	}
}

帮助:

import javax.swing.*;
import java.awt.*;
 
public class Help extends JFrame{
	
	public Help(){
		super("帮助");  //调用父类的构造方法
		this.setSize(500, 150);  //设置窗口大小,宽度500,高度150
		this.setLocation(250,300);  //设置窗口位置为距离屏幕左边水平方向250,上方垂直方向300
		this.setResizable(false);  //设置窗体大小不可改变
		this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);  //点击关闭按钮是直接退出
		this.setVisible(true);  //设置窗体可见
		
		Container c = this.getContentPane();  //初始化一个容器
		c.setLayout(new GridLayout(3,0));   //将窗口布局设置为网格式布局,网格的行数和列数分别是3和0
		
		//创建标签文字
		JLabel label1 = new JLabel("1、“菜单”中的功能“新建”、“打开”、“保存”、“另存为”、“退出”通过点击对应使用。");
		JLabel label2 = new JLabel("2、“编辑”中的“剪切”“复制”“粘贴”可对应使用快捷键Ctrl + X、Ctrl + C、Ctrl +V。");
		JLabel label3 = new JLabel("3、“格式”里的“自动换行”勾选后到窗口边缘自动换行;不勾选则向后继续写入。");
		c.add(label1);c.add(label2);c.add(label3);  //添加标签到容器中
	}
}

关于:

import javax.swing.*;
 
public class About extends JFrame{
	public About(){
		super("关于"); //调用父类的构造方法
		this.setSize(280, 100);  //设置窗口大小,宽度280,高度100
		this.setLocation(250,300);  //设置窗口位置为距离屏幕左边水平方向250,上方垂直方向300
		this.setResizable(false);  //设置窗体大小不可改变
		this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);  //点击关闭按钮直接退出
		this.setVisible(true);  //设置窗体可见
		JPanel panel = new JPanel();  //使用默认的浮动布局
		JLabel label1 = new JLabel("这是一个用Java开发的简易文本编译器。"); 
		JLabel label2 = new JLabel("Copyright ©2020 马桂雨");
		
		panel.add(label1);
		panel.add(label2);
		this.add(panel);
	}
}

四、运行结果

  • 编辑器界面

  • 打开文件

  • 保存文件

  • 自动换行

  • 统计

  • 帮助

  • 关于

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用Java实现文本编辑器:创建、浏览、编辑文件;剪贴、复制、粘贴;保存、另存为;字符统计;自动换行 的相关文章

  • 获取文件的锁

    我想在对特定文件开始 threo read 时获取文件上的锁定 以便其他应用程序无法读取已锁定的文件并希望在线程终止时释放锁定文件 您可以获得一个FileLock https docs oracle com javase 8 docs ap
  • Reactive Spring 不支持 HttpServletRequest 作为 REST 端点中的参数?

    我创建了一个 RestController 如下所示 RestController public class GreetingController RequestMapping value greetings method RequestM
  • 删除优先级队列的尾部元素

    如何删除优先级队列的尾部元素 我正在尝试使用优先级队列实现波束搜索 一旦优先级队列已满 我想删除最后一个元素 优先级最低的元素 Thanks 没有简单的方法 将元素从原始元素复制到新元素 最后一个除外 PriorityQueue remov
  • Logback:SizeAndTimeBasedRollingPolicy 不遵守totalSizeCap

    我正在尝试以一种方式管理我的日志记录 一旦达到总累积大小限制或达到最大历史记录限制 我最旧的存档日志文件就会被删除 当使用SizeAndTimeBasedRollingPolicy在 Logback 1 1 7 中 滚动文件追加器将继续创建
  • Android 中 localTime 和 localDate 的替代类有哪些? [复制]

    这个问题在这里已经有答案了 我想使用从 android API 获得的长值 该值将日期返回为长值 表示为自纪元以来的毫秒数 我需要使用像 isBefore plusDays isAfter 这样的方法 Cursor managedCurso
  • 为自定义驱动程序创建 GraphicsDevice

    我正在开发一个在嵌入式系统中使用 Java 的项目 我有用于屏幕和触摸输入的驱动程序 以及用于文本输入的虚拟键盘 我的屏幕驱动程序有一个Graphics2D您可以绘制的对象和repaint Rectangle 更新方法 类似地 触摸驱动器能
  • 为什么Iterator接口没有add方法

    In IteratorSun 添加了remove 方法来删 除集合中最后访问的元素 为什么没有add方法来向集合中添加新元素 它可能对集合或迭代器产生什么样的副作用 好的 我们开始吧 设计常见问题解答中明确给出了答案 为什么不提供 Iter
  • 是否可以从 servlet 内部以编程方式设置请求上下文路径?

    这是一个特殊情况 我陷入了处理 企业 网络应用程序的困境 企业应用程序正在调用request getContext 并将其与另一个字符串进行比较 我发现我可以使用 getServletContext getContextPath 获取 se
  • 如何通过注解用try-catch包装方法?

    如果应该在方法调用中忽略异常 则可以编写以下内容 public void addEntryIfPresent String key Dto dto try Map
  • 添加到列表时有没有办法避免循环?

    我想知道这样的代码 List
  • 在 Java 中通过 XSLT 分解 XML

    我需要转换具有嵌套 分层 表单结构的大型 XML 文件
  • 如何删除日期对象的亚秒部分

    当 SQL 数据类型为时间戳时 java util Date 存储为 2010 09 03 15 33 22 246 如何在存储记录之前将亚秒设置为零 例如 在本例中为 246 最简单的方法是这样的 long time date getTi
  • Spring Data JPA:查询如何返回非实体对象或对象列表?

    我在我的项目中使用 Spring Data JPA 我正在演奏数百万张唱片 我有一个要求 我必须获取各种表的数据并构建一个对象 然后将其绘制在 UI 上 现在如何实现我的 Spring 数据存储库 我读到它可以通过命名本机查询来实现 如果指
  • 寻找局部最小值

    下面的代码正确地找到了数组的局部最大值 但未能找到局部最小值 我已经进行了网络搜索 以找到找到最小值的最佳方法 并且根据这些搜索 我认为我正在使用下面的正确方法 但是 在几天的时间里多次检查每一行之后 下面的代码中有一些我仍然没有看到的错误
  • IntelliJ 组织导入

    IntelliJ 是否具有类似于 Eclipse 中的组织导入功能 我拥有的是一个 Java 文件 其中多个类缺少导入 例子 package com test public class Foo public Map map public J
  • 如何让 Emma 或 Cobertura 与 Maven 一起报告其他模块中源代码的覆盖率?

    我有一个带有 Java 代码的多模块 Maven 设置 我的单元测试在其中一个模块中测试多个模块中的代码 当然 这些模块具有相互依赖性 并且在测试执行之前根据需要编译所有相关模块中的代码 那么 如何获得整个代码库覆盖率的报告 注意 我不是问
  • 使用 Java https 上传到 Imgur v3 错误

    我目前正在尝试使用他们当前的 API v3 上传到 imgur 但是我不断收到错误 错误 javax net ssl SSLException 证书中的主机名不匹配 api imgur com imgur com OR imgur com
  • 记录类名、方法名和行号的性能影响

    我正在我的 java 应用程序中实现日志记录 以便我可以调试应用程序投入生产后可能出现的潜在问题 考虑到在这种情况下 人们不会奢侈地使用 IDE 开发工具 以调试模式运行事物或单步执行完整代码 因此在每条消息中记录类名 方法名和行号将非常有
  • 检查应用程序是否在 Android Market 上可用

    给定 Android 应用程序 ID 包名称 如何以编程方式检查该应用程序是否在 Android Market 上可用 例如 com rovio angrybirds 可用 而 com random app ibuilt 不可用 我计划从
  • ArrayList.clear() 和 ArrayList.removeAll() 有什么区别?

    假如说arraylist定义为ArrayList

随机推荐