自定义记录本小程序

电脑自带的记事本不太方便,所以想自己在记事本的基础上增加些功能。

准备工作

eclipse外来包log4j

在目标文件夹内建立想要记录的某种类型的txt文本,文本内包含其绝对路径(方便保存时找到路径),新建log.txt用于日志记录。

功能如下

菜单1:包含打开和保存2个功能,如下---

 

 

打开会定位到设定的文件夹,过滤需要选择的文件类型(比如txt),然后在显示的时候自动追加日期,根据【】标记符将内容显示为红色加大字体。

保存会去除文本末尾空格,去除没有文字记录的日期。

菜单2:我是分成日记、收支、实验3类,分别设置各种打开快捷键,其实就是简化打开操作(比如ctrl+D打开日记,比选择打开-选择文件-点击确定方便),这部分单独设置个监听器即可。

菜单3:附加功能,设置了总可见文字的字数、总行数(包含换行)、换行并缩进(缩进量为txt文本2个汉字)、按日期查找记录、产生成对【】标记符、光标定位到可见文字末尾   这些功能

代码如下

 

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
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.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

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.JTextPane;
import javax.swing.KeyStroke;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;

import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.Logger;

/**
 * updated by littlebird on 2018/02/26.
 *
 *
 */
public class TextNote {
    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                TFrame frame = new TFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
            }
        });
    }
}

class TFrame extends JFrame {
    /**
     * @author littlebird
     */
    private static final long serialVersionUID = 20180226L;
    Logger log = Logger.getLogger(TextNote.class);//日志
    Pattern p;//用于正则表达式匹配日期和【】标记符
    Matcher m;
    Map<Integer, Integer> map = new TreeMap<>();//用于检测两个日期间是否有文字记录
    JTextPane area;//比JTextArea好,可以设置部分字体的格式
    SimpleAttributeSet attrSet = new SimpleAttributeSet();//文本属性配置
    StyledDocument doc;//可以设置部分文字效果
    JFileChooser chooser = new JFileChooser();//文件类型过滤器
    String name;//记录文件名
    static final int WIDTH = 1000;//窗口显示宽、高
    static final int HEIGHT = 800;
    JMenuBar menus = new JMenuBar();//菜单栏,用于放置菜单Menu
    JMenu file = new JMenu("文件");//菜单,被添加到菜单栏
    JMenu sort = new JMenu("分类");
    JMenu function = new JMenu("功能");

    JMenuItem diary = new JMenuItem("日记");//元素,被添加到菜单
    JMenuItem experiment = new JMenuItem("实验");
    JMenuItem account = new JMenuItem("账目");

    JMenuItem open = new JMenuItem("打开");
    JMenuItem save = new JMenuItem("保存");

    JMenuItem charnum = new JMenuItem("字数");
    JMenuItem linenum = new JMenuItem("行数");
    JMenuItem font = new JMenuItem("标号");
    JMenuItem shiftEnter = new JMenuItem("新段落");
    JMenuItem toTextEnd = new JMenuItem("trim效果");
    JMenuItem findByDate = new JMenuItem("查找");

    public TFrame() {
        super("notebook1.0");
        PropertyConfigurator.configure("src/log4j.properties");//加载位于src下的日志配置文件,配置见后
        file.setFont(new Font("TimesRoman", Font.BOLD, 15));//菜单字体效果
        sort.setFont(new Font("TimesRoman", Font.BOLD, 15));
        function.setFont(new Font("TimesRoman", Font.BOLD, 15));

        menus.add(file);
        menus.add(sort);
        menus.add(function);

        file.add(open);
        file.addSeparator();
        file.add(save);

        sort.add(diary);
        sort.addSeparator();
        sort.add(account);
        sort.addSeparator();
        sort.add(experiment);

        function.add(charnum);
        function.addSeparator();
        function.add(linenum);
        function.addSeparator();
        function.add(font);
        function.addSeparator();
        function.add(shiftEnter);
        function.addSeparator();
        function.add(toTextEnd);
        function.addSeparator();
        function.add(findByDate);

        // 设置快捷键,比如第一个为Ctrl+O
        open.setAccelerator(
                KeyStroke.getKeyStroke(KeyEvent.VK_O, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
        save.setAccelerator(
                KeyStroke.getKeyStroke(KeyEvent.VK_S, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
        experiment.setAccelerator(
                KeyStroke.getKeyStroke(KeyEvent.VK_E, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
        account.setAccelerator(
                KeyStroke.getKeyStroke(KeyEvent.VK_Z, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
        diary.setAccelerator(
                KeyStroke.getKeyStroke(KeyEvent.VK_D, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
        shiftEnter.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.SHIFT_MASK));
        linenum.setAccelerator(
                KeyStroke.getKeyStroke(KeyEvent.VK_L, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
        toTextEnd.setAccelerator(
                KeyStroke.getKeyStroke(KeyEvent.VK_UP, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
        findByDate.setAccelerator(
                KeyStroke.getKeyStroke(KeyEvent.VK_F, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
        font.setAccelerator(
                KeyStroke.getKeyStroke(KeyEvent.VK_T, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
        charnum.setAccelerator(
                KeyStroke.getKeyStroke(KeyEvent.VK_N, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
        area = new JTextPane();
        area.setSelectedTextColor(new Color(238, 121, 66));//设置选中文本颜色
        area.setSelectionColor(new Color(238, 238, 209));//设置选中区域颜色(不仅仅是文本,还有空白的地方)
        area.setBackground(new Color(245, 255, 250));//背景色
        area.setText("");
        area.setFont(new Font("楷体", Font.BOLD, 20));//字体
        doc = area.getStyledDocument();
        JScrollPane scrollPane = new JScrollPane(area);// 添加滚动条,应该是装饰着模式
        Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
        int width = (int) screen.getWidth();
        int height = (int) screen.getHeight();
        setLocation(width / 4, height / 20);//窗口左上顶点所处电脑屏幕位置
        setSize(WIDTH, HEIGHT);
        setJMenuBar(menus);//设置添加完后的菜单栏
        getContentPane().add(scrollPane, BorderLayout.CENTER);//将包装后的文本区域添加到窗口中
        setResizable(true);//可调节窗口大小
        FileNameExtensionFilter filter = new FileNameExtensionFilter("文本文件", "txt");//文件后缀名过滤器
        chooser.setFileFilter(filter);

        // chooser.setFileView(new FileIconView(filter, null));图标暂无

        //以下添加监听器

        open.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                chooser.setCurrentDirectory(new File("D:\\MyDiary"));//设置要打开文件所在目录
                int result = chooser.showOpenDialog(TFrame.this);//弹出对话框选择
                if (result == JFileChooser.APPROVE_OPTION) {//选择并点击确定
                    name = chooser.getSelectedFile().getPath();
                    File f = new File(name);
                    String content;

                    try {

                        //因为电脑每次保存时txt文档都会变为ANSI编码,即GB2312格式

                        InputStreamReader isr = new InputStreamReader(new FileInputStream(f), "GB2312");
                        BufferedReader br = new BufferedReader(isr);

                        area.setText("");//先清空

                        //日期格式

                        String currentTime = new SimpleDateFormat("yyyy年MM月dd日 E").format(new Date());
                        while ((content = br.readLine()) != null) {
                            try {
                                doc.insertString(doc.getLength(), content + "\n", attrSet);
                            } catch (BadLocationException e1) {
                                log.error("打开文件" + name.substring(name.lastIndexOf("\\") + 1, name.indexOf(".txt"))
                                        + "时追加文本错误");
                                e1.printStackTrace();
                            }
                        }
                        if (!area.getText().contains(currentTime)) {
                            try {
                                doc.insertString(doc.getLength(), "\n"+currentTime + "\n\n", attrSet);
                            } catch (BadLocationException e1) {
                                log.error("打开文件" + name.substring(name.lastIndexOf("\\") + 1, name.indexOf(".txt"))
                                        + "时追加文本错误");
                                e1.printStackTrace();
                            }

                        }
                        try {
                            doc.insertString(doc.getLength(), "    ", attrSet);
                        } catch (BadLocationException e1) {
                            log.error("");
                            e1.printStackTrace();
                        }
                        br.close();
                        isr.close();
                    } catch (FileNotFoundException ex) {
                        log.error("打开文件时找不到文件" + name.substring(name.lastIndexOf("\\") + 1, name.indexOf(".txt")));
                        ex.printStackTrace();
                    } catch (IOException ex) {
                        log.trace("打开文件" + name.substring(name.lastIndexOf("\\") + 1, name.indexOf(".txt")) + "时IO错误");
                        ex.printStackTrace();
                    } finally {
                        content = null;
                    }

                    p = Pattern.compile("【[^【]*】");

                    // windows中\r\n换行符到这里算一个字符,要扣掉,不然后面setCharacterAttributes方法参数不对

                    m = p.matcher(area.getText().replaceAll("\r\n", "\n"));
                    map.clear();
                    while (m.find()) {
                        map.put(m.start(), m.end() - m.start());// 收集开始index和长度
                    }
                    if (!map.isEmpty()) {//如果有【】标记符
                        Iterator<Integer> it = map.keySet().iterator();
                        StyleConstants.setForeground(attrSet, Color.red);//更改文本颜色和字体大小
                        StyleConstants.setFontSize(attrSet, 24);
                        Integer in;
                        while (it.hasNext()) {
                            in = it.next();
                            doc.setCharacterAttributes(in, map.get(in), attrSet, true);//设置部分文本以上效果
                        }
                        StyleConstants.setForeground(attrSet, Color.darkGray);//设置完后配置调回来
                        StyleConstants.setFontSize(attrSet, 20);
                    }
                }
            }
        });
       save.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                int result = JOptionPane.showConfirmDialog(TFrame.this, "确定保存?", "提示",
                        JOptionPane.YES_NO_CANCEL_OPTION);//对话框:是否保存
                if (result == JOptionPane.YES_OPTION) {
                    int first = area.getText().indexOf("D:");
                    int last = area.getText().indexOf(".txt");

                    if (first != -1 && last > first) {//如果包含路径才能保存

                        name = area.getText().substring(first, last + 4);

                        OutputStreamWriter osw;
                        BufferedWriter bw;
                        List<Integer> list = new ArrayList<>();
                        StringBuilder sb = new StringBuilder();
                        sb.append(area.getText());
                        // 去除无记录的日期
                        p = Pattern.compile("\\b[1-9]\\d{3}.((0[1-9])|(1[0-2])).((0[1-9])|([12]\\d)|(3[0-1])).\\b");
                        m = p.matcher(area.getText());
                        while (m.find()) {
                            list.add(m.start());//list添加所有日期字符串的开始index

                        }

                        //先看看最后一个日期后面有无文字记录,没有就删除

                        if(area.getText().substring(list.get(list.size()-1)+15).trim().isEmpty())

                            sb.delete(list.get(list.size()-1), list.get(list.size()-1)+15);

                        //再看看其他日期后面有无文字记录,没有删除

                        for (int i = 0; i < list.size() - 1; i++) {
                            if (area.getText().substring((list.get(i) + 15), (list.get(i + 1))).trim().isEmpty()) {
                                sb.delete(list.get(i), list.get(i + 1));
                            }
                        }
                        try {
                            osw = new OutputStreamWriter(new FileOutputStream(name), "GB2312");//同样编码问题
                            bw = new BufferedWriter(osw);
                            bw.write(sb.toString().trim());
                            bw.close();
                            osw.close();
                            log.info("保存文件" + name.substring(name.lastIndexOf("\\") + 1, name.indexOf(".txt")) + "成功");
                            JOptionPane.showMessageDialog(TFrame.this, "保存成功");
                        } catch (FileNotFoundException e1) {
                            log.error("保存文件时找不到文件" + name.substring(name.lastIndexOf("\\") + 1, name.indexOf(".txt")));
                            e1.printStackTrace();
                        } catch (IOException e1) {
                            log.trace("保存文件" + name.substring(name.lastIndexOf("\\") + 1, name.indexOf(".txt"))
                                    + "时IO错误");
                            e1.printStackTrace();
                        }
                    } else {
                        JOptionPane.showMessageDialog(TFrame.this, "缺少路径,不能保存");
                    }

                }
            }
        });
        shiftEnter.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                int caret = area.getCaretPosition();//光标位置
                try {
                    area.getDocument().insertString(caret, "\n    ", attrSet);
                } catch (BadLocationException e1) {
                    log.error("shift+enter时出错");
                    e1.printStackTrace();
                }
                area.setCaretPosition(caret + 5);// 1个enter4个空格
            }
        });
        toTextEnd.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                area.setCaretPosition(area.getText().trim().replaceAll("\r\n", "\n").length());//trim+replace
            }
        });
        // 按日期进行查找
        findByDate.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                //   \b标识开始和结尾
                p = Pattern.compile("\\b[1-9]\\d{3}.((0[1-9])|(1[0-2])).((0[1-9])|([12]\\d)|(3[0-1])).\\b");//日期匹配
                m = p.matcher(area.getText());
                List<Object> list = new ArrayList<>();
                while (m.find()) {
                    list.add(m.group());//装入匹配到的日期
                }

                if (list.size() != 0) {

                    //弹出下拉列表对话框

                    String start = (String) JOptionPane.showInputDialog(TFrame.this, "开始日期", "查找",
                            JOptionPane.INFORMATION_MESSAGE, null, list.toArray(), list.get(0));
                    if (start != null) {
                        String end = (String) JOptionPane.showInputDialog(TFrame.this, "截止日期(不包含)", "查找",
                                JOptionPane.INFORMATION_MESSAGE, null, list.toArray(), list.get(list.size() - 1));
                        if (end != null) {
                            area.setText(area.getText()
                                    .substring(area.getText().indexOf(start), area.getText().indexOf(end)).trim());
                        } else
                            area.setText(area.getText().substring(area.getText().indexOf(start)).trim());
                    }
                }
                p = Pattern.compile("【[^【]*】");
                m = p.matcher(area.getText().replaceAll("\r\n", "\n"));// windows中\r\n换行符到这里算一个字符,要扣掉
                map.clear();
                while (m.find()) {
                    map.put(m.start(), m.end() - m.start());// 收集开始index和长度
                }
                if (!map.isEmpty()) {
                    Iterator<Integer> it = map.keySet().iterator();
                    StyleConstants.setForeground(attrSet, Color.red);
                    StyleConstants.setFontSize(attrSet, 24);
                    Integer in;
                    while (it.hasNext()) {
                        in = it.next();
                        doc.setCharacterAttributes(in, map.get(in), attrSet, true);
                    }
                    StyleConstants.setForeground(attrSet, Color.darkGray);
                    StyleConstants.setFontSize(attrSet, 20);
                }
            }
        });
        //本来这个变量是修改字体的,但是对于txt没有意义,改为使用【】标记符
        font.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                int index = area.getCaretPosition();
                try {
                    area.getDocument().insertString(index, "【】", attrSet);
                } catch (BadLocationException e1) {
                    e1.printStackTrace();
                }
                area.setCaretPosition(index + 1);
            }
        });
        linenum.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                int line = area.getDocument().getDefaultRootElement().getElementCount();
                JOptionPane.showMessageDialog(TFrame.this, "行数: " + line);
            }
        });
        charnum.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                int count = area.getText().replaceAll(" ", "").replaceAll("\r\n", "").length();//去除空格和换行
                JOptionPane.showMessageDialog(TFrame.this, "总字数: " + count);

            }
        });
        diary.addActionListener(new OpenListener());
        account.addActionListener(new OpenListener());
        experiment.addActionListener(new OpenListener());
    }

    // 单独设置快捷方式
    class OpenListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            if (e.getSource() == diary) {
                name = "D:\\MyDiary\\diary.txt";
            } else if (e.getSource() == account) {
                name = "D:\\MyDiary\\account.txt";
            } else if (e.getSource() == experiment) {
                name = "D:\\MyDiary\\experiment.txt";
            }
            String content;
            try {
                File f = new File(name);
                InputStreamReader isr = new InputStreamReader(new FileInputStream(f), "GB2312");
                BufferedReader br = new BufferedReader(isr);
                area.setText("");
                String currentTime = new SimpleDateFormat("yyyy年MM月dd日 E").format(new Date());

                while ((content = br.readLine()) != null) {
                    try {
                        doc.insertString(doc.getLength(), content + "\n", attrSet);
                    } catch (BadLocationException e1) {
                        log.error(
                                "打开文件" + name.substring(name.lastIndexOf("\\") + 1, name.indexOf(".txt")) + "时追加文本错误");
                        e1.printStackTrace();
                    }
                }
                if (!area.getText().contains(currentTime)) {
                    try {
                        doc.insertString(doc.getLength(), "\n"+currentTime + "\n\n", attrSet);
                    } catch (BadLocationException e1) {
                        log.error(
                                "打开文件" + name.substring(name.lastIndexOf("\\") + 1, name.indexOf(".txt")) + "时追加文本错误");
                        e1.printStackTrace();
                    }

                }
                try {
                    doc.insertString(doc.getLength(), "    ", attrSet);
                } catch (BadLocationException e1) {
                    log.error("打开文件" + name.substring(name.lastIndexOf("\\") + 1, name.indexOf(".txt")) + "时追加文本错误");
                    e1.printStackTrace();
                }
                br.close();
                isr.close();
            } catch (FileNotFoundException ex) {
                log.error("打开文件时找不到文件" + name.substring(name.lastIndexOf("\\") + 1, name.indexOf(".txt")));
                ex.printStackTrace();
            } catch (IOException ex) {
                log.trace("打开文件" + name.substring(name.lastIndexOf("\\") + 1, name.indexOf(".txt")) + "时IO错误");
                ex.printStackTrace();
            } finally {
                content = null;
            }
            p = Pattern.compile("【[^【]*】");
            m = p.matcher(area.getText().replaceAll("\r\n", "\n"));// windows中\r\n换行符到这里算一个字符,要扣掉
            map.clear();
            while (m.find()) {
                map.put(m.start(), m.end() - m.start());// 收集开始index和长度
            }
            if (!map.isEmpty()) {
                Iterator<Integer> it = map.keySet().iterator();
                StyleConstants.setForeground(attrSet, Color.red);
                StyleConstants.setFontSize(attrSet, 24);
                Integer in;
                while (it.hasNext()) {
                    in = it.next();
                    doc.setCharacterAttributes(in, map.get(in), attrSet, true);
                }
                StyleConstants.setForeground(attrSet, Color.darkGray);
                StyleConstants.setFontSize(attrSet, 20);
            }
        }
    }
}

下面附上log配置:

log4j.rootLogger=INFO,logfile#根级别
log4j.appender.logfile=org.apache.log4j.RollingFileAppender#滚动
log4j.appender.logfile.Threshold=INFO#级别
log4j.appender.logfile.File=D:\\MyDiary\\log.txt#日志目录
log4j.appender.logfile.Append=true#在末尾追加
log4j.appender.logfile.MaxFileSize=2MB#最大文件大小
log4j.appender.logfile.MaxBackupIndex=3#最大日志数

log4j.appender.logfile.layout=org.apache.log4j.PatternLayout#格式

log4j.appender.logfile.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS}(%r)-->[%t] %l: %m %x %n

log4j.appender.logfile.encoding=GB2312#日志编码与记事本相同即可

完。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值