**日常的作业呀
好久没更了,这次更记事本**
相当一部分借鉴了其他人的,若侵犯了利益,请联系作者

/*

  • read()读取整个文件,将文件内容放到一个字符串变量中。
  • readline()方法每次读取一行;返回的是一个字符串对象,保持当前行的内存
  • readlines()一次性读取整个文件;自动将文件内容分析成一个行的列表。
  • “==”比较两个变量本身的值,即两个对象在内存中的首地址。
  • “equals()”比较字符串中所包含的内容是否相同。
    */

*/

  • read()读取整个文件,将文件内容放到一个字符串变量中。
  • readline()方法每次读取一行;返回的是一个字符串对象,保持当前行的内存
  • readlines()一次性读取整个文件;自动将文件内容分析成一个行的列表。
  • “==”比较两个变量本身的值,即两个对象在内存中的首地址。
  • “equals()”比较字符串中所包含的内容是否相同。
    */

package notework;
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.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import javax.swing.ImageIcon;
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;

public class MainUI extends JFrame {


private static final long serialVersionUID = 1L;
/*serialVersionUID 用来表明类的不同版本间的兼容性。

序列化的时候,被序列化的类要有一个唯一标记。客户端和服务端必须需要同一个对象,serialVersionUID的唯一值判定其为同一个对象。
后面的号码是自动生成的,只要是唯一的就行,通常为1

 * */
private JTextArea jta;//文本域与文本框的最大区别就是文本域允许用户输入多行文本信息,JTextArea():创建一个默认的文本域。
private JScrollPane jsp;//JScrollPane是带有滚动条的面板JScrollPane的一般用法是先将一些组件添加到一个JPanel中,然后再把这个JPanel添加到JScrollPane中。这样,从界面上看,在滚动面板上,好像也有多个组件。
//JScrollPane(),先创建JScrollPane对象,然后再用方法setViewportView(Component com)为滚动面板对象放置组件对象。
private static String name;
private JFileChooser jfc = new JFileChooser();
//点击上传文件的时候都会弹出一个框让我们选择要上传的文件,这种文件导航窗口就是FileChooser,JFileChooser不是抽象类也不是接口
public static void main(String[] args) {
    new MainUI().init();//在主方法里调用类的init方法
}

// 初始化界面
public void init() {
    setSize(800, 600);
    setLocationRelativeTo(null);
    //如果组件当前未显示或者 c 为 null,则此窗口将置于屏幕的中央。
    // 设置关闭按钮动作不执行任何操作
    setDefaultCloseOperation(0);
    //setDefaultCloseOperation()是设置用户在此窗体上发起 "close" 时默认执行的操作。
    name = "豪的记事本.txt";
    // 设置标志图案
    ImageIcon ii = new ImageIcon("C:\\Users\\DELL\\Desktop\\校徽.png");
    //很自然地认为当前类文件和图片在同一路径下即可。其实所谓的相对路径起点是工程的根目录,即project。
    //imageicon 用途是根据路径找图片。或者其他,需要路径的方法
    setIconImage(ii.getImage());
    // 设置文件名
    setTitle(name);
    // 添加菜单栏
    addMenu();
    // 添加文本框
    jta = new JTextArea();
    // 添加滚动条
    jsp = new JScrollPane(jta);//把jta放置在jsp上
    jsp.setPreferredSize(new Dimension(780, 550));
    /*让容器适应内部控件的大小,即preferredsize最佳大小。
     * 例如,在窗口里显示一张照片,那么可以使窗口根据当前照片的大小来调整自己的大小。但是,当使用setSize (),那么prefersize()将失效。
     * */
    add(jsp, BorderLayout.CENTER);//布局在中间
    setVisible(true);// 设置窗口可见
    addWindowListener(new WindowAdapter() {
        @Override
        public void windowClosing(WindowEvent e) {
            if (showSaveDialog() != JOptionPane.CANCEL_OPTION)// 若不是取消按钮,关闭程序
                setDefaultCloseOperation(3);
        }
    /*这个是表示在窗口添加一个Windows事件消息,目的是我们关闭窗口的时候可以正常的退出,其实这段语句等价于
    frame.setDefaultCloseOptration(JFrame.EXIT_ON_CLOSE);
    在这段语句中new WindowAdapter表示新的创建WindowAdapter的对象
    中间是对一个函数也就是windows窗口关闭函数进行重写。
     * */
    });
}

// 添加菜单栏
private void addMenu() {
    // 添加菜单栏
    JMenuBar jmb = new JMenuBar();
    // 设置菜单栏位置在顶级窗口的顶部
    setJMenuBar(jmb);//将菜单栏对象添加到窗体的菜单栏中
    // 菜单栏菜单
    JMenu jm_file = new JMenu("文件");
    JMenu jm_edit = new JMenu("编辑");
    JMenu jm_test = new JMenu("test_没啥用");
    jmb.add(jm_file);
    jmb.add(jm_edit);
    jmb.add(jm_test);
    // 给文件菜单添加菜单项
    JMenuItem item1 = new JMenuItem("打开");//这连接文档,等下实现文件打开功能
    JMenuItem item2 = new JMenuItem("保存");
    jm_file.add(item1);
    jm_file.add(item2);

    // "打开"菜单项添加动作监听器
    /*   addActionListener(ActionListener 1)方法为TextField对象注册一个ActionListener对象,
     *当TextField对象发生Action事件时,会生成一个ActionEvent对象,
     *该对象作为参数传递给ActionListener对象的actionPerformer方法在方法中可以获取该对象的信息,并作出相应的处理。
     * */
    //这实现打开功能
    item1.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            // 是否保存对原文件修改
            if (showSaveDialog() == JOptionPane.CANCEL_OPTION)
            {// 取消按钮,则返回
                return;
            }//CANCEL_OPTION,取消按钮
            /*JFileChooser的 showSaveDialog()方法,可以打开一个保存文件的对话框
             * 打开文件-----获取文件属性[文件路径+文件名]---->使用输入流[InputStream]从磁盘上读取
               保存文件----->创建文件属性[文件路径+文件名]---->使用输出流[OutPutStream]写到磁盘上
             * */
            // 弹出一个 "Open File" 文件选择器对话框
            int select = jfc.showOpenDialog(MainUI.this);
            // 选择打开文件,则读写文件
            //APPROVE_OPTION:获得选中的文件对象,选择确认(yes、ok)后返回该值。
            if (select == JFileChooser.APPROVE_OPTION) {
                jta.setText(readFile());// 写入文本框
                jta.setCaretPosition(0);// 定位光标至行首、设置光标停留位置
                //这个方法只是一个观察文本的字段的功能显示,position参数指明观察的位置
            }
        }
    });

    // “保存”菜单项添加动作监听器
    item2.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (jfc.getSelectedFile() == null) {
                createFile();//调用创建文件方法
            } else {
                showSaveDialog();//调用文件是否保存方法
            }
        }
    });
}
// 读取文件
private String readFile() {
    // 声明缓冲字符流变量
    BufferedReader br = null;
    StringBuilder sb = null;//使用StringBuilder类可以不用“+”连接字符
    try {
        br = new BufferedReader(new FileReader(jfc.getSelectedFile()));//获取要看的文件
        sb = new StringBuilder();// 创建缓冲字符串
        String str;
        int count = 0;//控制添加换行符,与原文保持一致
        while ((str = br.readLine()) != null) {
            if (count == 0)
                sb.append(str);
            if (count++ != 0)
                sb.append("\n" + str);// 添加换行
        }
    } catch (FileNotFoundException e1) {
        // 弹出“文件未找到”对话框,返回null
        JOptionPane.showMessageDialog(null, "未找到该文件!");
        return null;
    } catch (IOException e1) {
        // 弹出“文件读取异常”对话框,返回null
        JOptionPane.showMessageDialog(null, "文件读取异常");
        return null;
    } finally {
        // 关闭字符流
        if (br != null)
            try {
                br.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
    }
    name = jfc.getSelectedFile().getName();
    setTitle(name + " - 记事本");//设置文件名
    return sb.toString();//toString() 方法可把一个 Number 对象转换为一个字符串,并返回结果。
}

// 保存对话框
private int showSaveDialog() {
    int select = 0;
        // 判断文本框是否为空
    if (!jta.getText().equals("")) {//“equals()”比较字符串中所包含的内容是否相同。
        // 判断文件是否为空
        if (jfc.getSelectedFile() == null) {
            select = JOptionPane.showConfirmDialog(MainUI.this, "是否保存修改?");
            if (select == JOptionPane.YES_OPTION) {
                createFile();//文件不存在,则创建文件
            }
        } else {
            if (!isSaved()) {// 文件未保存
                select = JOptionPane.showConfirmDialog(MainUI.this, "是否保存修改?");
                if (select == JOptionPane.YES_OPTION) {
                    saveFile(jfc.getSelectedFile());
                }
            }
        }
    }
    return select;// 返回选项
}

// 创建新文件
private void createFile() {
    // String name = null;
    File file = null;
    // 选择保存或取消
    if (jfc.showSaveDialog(MainUI.this) == JFileChooser.APPROVE_OPTION) {
        file = jfc.getSelectedFile();// 获取选中的文件
    } else {
        return;
    }
    name = jfc.getName(file);// 获取输入的文件名
    if (file.exists()) { // 若选择已有文件----询问是否要覆盖
        int i = JOptionPane.showConfirmDialog(null, "该文件已存在,是否覆盖原文件", "确认", JOptionPane.YES_NO_OPTION);
        if (i == JOptionPane.YES_OPTION) {
            saveFile(file);
        } else {
            jfc.showSaveDialog(MainUI.this);// 重新选择
        }
    } else {//文件不存在,则直接保存
        saveFile(file);
    }
}

// 判断文件是否保存
private Boolean isSaved() {
    // 比较内容
    if (jta.getText().equals(readFile())) {
        return true;
    }
    return false;
}

// 保存文件,文件不存在则创建新文件
private void saveFile(File file) {
    BufferedWriter bw = null;
    try {
        bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
        bw.write(jta.getText());//写入文件
        bw.flush();
    } catch (FileNotFoundException e1) {
        JOptionPane.showMessageDialog(MainUI.this, "文件保存出错" + e1.getMessage());
    } catch (IOException e1) {
        e1.printStackTrace();
    } finally {
        try {
            if (bw != null)
                bw.close();
        } catch (IOException e1) {
        }
    }
}

}**