使用 Jfilechooser 编辑仍然打开的文件副本,并在行尾附加总和

Using Jfilechooser edit a file copy that is still open with appending sum at the end of the line

作业:

我需要使用 GUI 界面打开一个文件,对每一行求和,然后将每行的内容后跟一系列空格和每行的总和输出到一个新文件中。如果您愿意,新文件必须标记为 "Previousfilename"_out.txt 又名 *_out.txt。

我所在的位置:

我有运行和复制文件的 GUI。

正在对文件中的行进行编辑和汇总,这似乎是个问题。

我当前只有 GUI 工作的程序无法识别换行符,并且显示每个 int 求和在一个新行上,例如,

输入:

1, 2, 3, 4, 5
5, 6
4, 3, 9

输出:

1
3
6
10
15
20
26
30
33
42

由于不需要','分隔我的 testfile.txt 中的整数,我删除了定界符,并且在我点击复制并出现错误后整个程序失败:

Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: For input string: "1 2 3 4 5"
        at java.lang.NumberFormatException.forInputString(Unknown Source)
        at java.lang.Integer.parseInt(Unknown Source)
        at java.lang.Integer.parseInt(Unknown Source)
        at fileSumCompute.computeF(fileSumCompute.java:210)
        at fileSumCompute$myHandler.actionPerformed(fileSumCompute.java:105)
        at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
        at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
        at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
        at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
        at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
        at java.awt.Component.processMouseEvent(Unknown Source)
        at javax.swing.JComponent.processMouseEvent(Unknown Source)
        at java.awt.Component.processEvent(Unknown Source)
        at java.awt.Container.processEvent(Unknown Source)
        at java.awt.Component.dispatchEventImpl(Unknown Source)
        at java.awt.Container.dispatchEventImpl(Unknown Source)
        at java.awt.Component.dispatchEvent(Unknown Source)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
        at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
        at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
        at java.awt.Container.dispatchEventImpl(Unknown Source)
        at java.awt.Window.dispatchEventImpl(Unknown Source)
        at java.awt.Component.dispatchEvent(Unknown Source)
        at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
        at java.awt.EventQueue.access0(Unknown Source)
        at java.awt.EventQueue.run(Unknown Source)
        at java.awt.EventQueue.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
        at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
        at java.awt.EventQueue.run(Unknown Source)
        at java.awt.EventQueue.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
        at java.awt.EventQueue.dispatchEvent(Unknown Source)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
        at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.run(Unknown Source)

即使 Jfilechooser 在使用副本,我该如何编辑副本?我怎样才能让它识别换行符,但仍然打印出带有 EOF 的最后总和(以前的构建有问题,在那里出错了。)?

旧代码: https://drive.google.com/open?id=1OOB5-21sJXQSl8XLlFPASaAPoIsXWnPu

新代码:

import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.nio.file.*;
import java.util.*;

public class fileSumCompute extends JFrame{
//my first gui
private JFileChooser fc;
private JButton copyButton;
private JButton chooseFileButton;
private JButton destinationButton;
private File workingDirectory;
private JLabel sourceLabel;
private JLabel destinationLabel;
private JTextField sourceText;
private JTextField sourceFileText;
private JTextField destinationText;

    public static void main(String [] args)  
    {
        fileSumCompute cpy1 = new fileSumCompute();
        cpy1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        cpy1.setSize(600, 150);
        cpy1.setVisible(true);
    }
    //my first time creating and opening files without direct command line input. 

    public fileSumCompute() {  @Override
        //peiced together a couple JfileChooser examples and customized... I cant seem to get it to work without the other path selection and preprograming it into the same directory as source file. 
        //It works though.
        super("Compute sum of row. New file = \" *_out.txt\" ");
        setLayout(new GridLayout(3, 3, 5, 5));
        fc = new JFileChooser();

        //Open dialog box to make easier to find files
        workingDirectory = new File(System.getProperty("user.dir"));
        fc.setCurrentDirectory(workingDirectory);

     //create labels and buttons
        chooseFileButton = new JButton("CHOOSE SOURCE FILE");
        destinationButton = new JButton("DESTINATION FOLDER");
        copyButton = new JButton("COMPUTE & SAVE FILE");      //copies file so origonal is preserved
        sourceLabel = new JLabel("SOURCE: ");
        sourceText = new JTextField(10);
        sourceText.setEditable(false);
        destinationLabel = new JLabel("DESTINATION: ");
        destinationText = new JTextField(10);
        destinationText.setEditable(false);

        //JFrame tools   
        add(sourceLabel);
        add(sourceText);
        add(chooseFileButton);  
        add(destinationLabel);
        add(destinationText);
        add(destinationButton);
        add(copyButton);

        //Create myHandler object to add action listeners for the buttons.
        myHandler handler = new myHandler(); //handles the files and copies them 
        chooseFileButton.addActionListener(handler);
        destinationButton.addActionListener(handler);
        copyButton.addActionListener(handler);
        //computeF(name);
    }

    //Inner class to create action listeners    
    private class myHandler implements ActionListener {
        private File selectedSourceFile;
        private File selectedDestinationFile;

        public void actionPerformed(ActionEvent event) 
        {
            int returnVal;
            String selectedFilePath;
            File selectedFile;


            if (event.getSource() == chooseFileButton) 
            {
                returnVal = fc.showOpenDialog(null);
                if (returnVal == JFileChooser.APPROVE_OPTION) 
                {
                    selectedSourceFile = fc.getSelectedFile();
                    sourceText.setText(selectedSourceFile.getName());
                }
            }


            if (event.getSource() == destinationButton) 
            {
                returnVal = fc.showSaveDialog(null);
                if (returnVal == JFileChooser.APPROVE_OPTION) 
                {
                    selectedDestinationFile = fc.getSelectedFile();
                    destinationText.setText(selectedDestinationFile.getName());

                    //where we implement the second file... here is where we'll call to compute the sum of the lines 
                    String name = selectedSourceFile.getName();
                    name = selectedSourceFile.getName().substring(0, name.lastIndexOf(".")) + "_out.txt"; //changed the output file to read ("Orig name here"_out.txt)
                    File destinationFile = new File(selectedDestinationFile.getParentFile(), name); 
                    //destinationFile.deleteOnExit();

                    try {
                        Files.copy(selectedSourceFile.toPath(), destinationFile.toPath()); //copying and computing
                        computeF(destinationFile); //if we can get this to edit the _out.txt file we can do with out creating two seperate files- the previous *_.tmp can just be the *_out.txt
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }

                }
            }


            if (event.getSource() == copyButton) 
            {
                Path sourcePath = selectedSourceFile.toPath();
                Path destinationPath = selectedDestinationFile.toPath();
                try 
                {
                    Files.copy(sourcePath, destinationPath); 

                } 
                catch (IOException e) 
                {
                    e.printStackTrace();
                }


            }

        }
    }

以上是GUI 那么我下面的流程处理方法

public static void computeF(File selectedDestinationFile) throws IOException{
        //int i=0;
        if (!selectedDestinationFile.isFile()) // IF CANNOT FIND FILE
        {
            System.out.println("File.txt - Parameter is not an existing file");
            return;
        }

        Scanner fileReader = null; //using the namespace for readability.
        int lineSum=0;
        try
        {
            fileReader = new Scanner(selectedDestinationFile);
        }
        catch (IOException a) //it insists on a try catch
        {
            a.printStackTrace();
        }

        String name = selectedDestinationFile.getName();
        System.setOut(new PrintStream(new FileOutputStream(name)));
        while(fileReader.hasNext()) { 
                    String number = fileReader.next();
                    sum += Integer.parseInt(number);
                    System.out.println(sum);

                    if(fileReader.hasNextLine()) {
                        System.out.println(sum);
                        sum = 0;
                    }
                }


    }
}


/*_______________________________________________________________________________________________________________________*/
                          /*implement after Working script*/
//is there a way to append instead of doing the System.setout? like with this similarly found code.
/* appending how can I implement this??
try(FileWriter fw = new FileWriter("myfile.txt", true);
    BufferedWriter bw = new BufferedWriter(fw);
    PrintWriter out = new PrintWriter(bw))
{
    out.println("the text");
    //more code
    out.println("more text");
    //more code
} catch (IOException e) {
    //exception handling left as an exercise for the reader
}

// or this one? I need to keep the copy but just add to the end so that makes the most sense.  

fout = new FileWriter("filename.txt", true);

*/
/*______________________________________________________________________________________________________________________*/

_________________edit________________ //OP

后约 2 小时

忽略 Jfilechooser 中的 override 命令,它本不应存在。 同样对于新代码,基本上我如何得到它做我想做的事情,从我知道的工作开始?也就是我怎样才能让它做我需要它做的事情:

public static void computeF(FILE in)
    {   

        if (!selectedDestinationFile.isFile()) // IF CANNOT FIND FILE
        {
            System.out.println("File.txt - Parameter is not an existing file");
            return;
        }
        Scanner fileReader = null; //using the namespace for readability.
        try
        {
            fileReader = new Scanner(in);
        }
        catch (IOException a) //it insists on a try catch
        {
            a.printStackTrace();
        }
        String name = in.getName();
        fout = new FileWriter(name, true);// to try to append to the copy instead of rewriting the whole file 

    }

我写了一个很长的答案然后我的电脑死机了..让我们看看我们是否可以再做一次。

这些概念中的任何一个对于初学者来说都很难理解(GUI、文件等)。因此,根据我对您的说明的理解,这是一个可行的解决方案。我尽量不对你的整体结构做太多改动,这样对你来说会更易读。

import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class fileSumCompute extends JFrame implements ActionListener {

    private JFileChooser fc;
    private JButton copyButton;
    private JButton chooseFileButton;
    private JButton destinationButton;
    private File workingDirectory;
    private JLabel sourceLabel;
    private JLabel destinationLabel;
    private JTextField sourceText;
    private JTextField sourceFileText;
    private JTextField destinationText;
    private File selectedSourceFile = null;
    private File selectedDestinationFolder;
    private static String textToWrite;
    // my first time creating and opening files without direct command line input.

    public fileSumCompute() {
        // peiced together a couple JfileChooser examples and customized... I cant seem
        // to get it to work without the other path selection and preprograming it into
        // the same directory as source file.
        // It works though.
        super("Compute sum of row. New file = \" *_out.txt\" ");
        setLayout(new GridLayout(3, 3, 5, 5));
        fc = new JFileChooser();

        // Open dialog box to make easier to find files
        workingDirectory = new File(System.getProperty("user.dir"));
        fc.setCurrentDirectory(workingDirectory);

        // create labels and buttons
        chooseFileButton = new JButton("CHOOSE SOURCE FILE");
        destinationButton = new JButton("DESTINATION FOLDER");
        copyButton = new JButton("COMPUTE & SAVE FILE"); // copies file so origonal is preserved
        sourceLabel = new JLabel("SOURCE: ");
        sourceText = new JTextField(10);
        sourceText.setEditable(false);
        destinationLabel = new JLabel("DESTINATION: ");
        destinationText = new JTextField(10);
        destinationText.setEditable(false);

        // JFrame tools
        add(sourceLabel);
        add(sourceText);
        add(chooseFileButton);
        add(destinationLabel);
        add(destinationText);
        add(destinationButton);
        add(copyButton);

        // Add this as action listener.
        chooseFileButton.addActionListener(this);
        destinationButton.addActionListener(this);
        copyButton.addActionListener(this);
        // computeF(name);
    }

    @Override
    public void actionPerformed(ActionEvent arg0) {
        Object event = arg0.getSource();
        int returnVal;

        if (event == chooseFileButton) {
            returnVal = fc.showOpenDialog(null);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                selectedSourceFile = fc.getSelectedFile();
                sourceText.setText(selectedSourceFile.getName());
            }
        } else if (event == destinationButton) {
            fc.setCurrentDirectory(new java.io.File("."));
            fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
            if (fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
                selectedDestinationFolder = fc.getSelectedFile();
                destinationText.setText(selectedDestinationFolder.getName());
            }
        } else if (event == copyButton) {
            // where we implement the second file... here is where we'll call to compute the
            // sum of the lines
            String name = selectedSourceFile.getName();
            // changed the output file to read ("Orig name here"_out.txt)
            name = selectedSourceFile.getName().substring(0, name.lastIndexOf(".")) + "_out.txt";
            File destinationFile = new File(selectedDestinationFolder, name);

            try {
                //Files.copy(selectedSourceFile.toPath(), destinationFileFolder.toPath()); // copying and computing
                computeF(selectedSourceFile); // if we can get this to edit the _out.txt file we
                // can do with out creating two seperate files- the previous *_.tmp can just be
                // the *_out.txt
                PrintWriter writer = new PrintWriter(destinationFile, "UTF-8");
                writer.println(textToWrite);
                writer.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    public static void computeF(File selectedDestinationFile) throws IOException {
        textToWrite = ""; 
        int sum;
        if (!selectedDestinationFile.isFile()) // IF CANNOT FIND FILE
        {
            System.out.println(selectedDestinationFile.getAbsolutePath() + " - Parameter is not an existing file");
            return;
        }

        try (BufferedReader br = new BufferedReader(new FileReader(selectedDestinationFile.getAbsolutePath()))) {
            String line;
            while ((line = br.readLine()) != null) {
                //Split each line, then check value in the array as an int and add to sum.
               String[] temp = line.split(", ");
               sum = 0;

               for (int i = 0; i < temp.length; i++) 
                   sum = Integer.parseInt(temp[i]); 

               textToWrite+= sum + System.getProperty("line.separator");
            }
        }

    }

    public static void main(String[] args) {
        fileSumCompute cpy1 = new fileSumCompute();
        cpy1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        cpy1.setSize(600, 150);
        cpy1.setVisible(true);
    }
}

我做了一些大的改动,也做了很多小的改动。总的来说,你很接近。让我详细说明一下重大变化。

  • 首先,我让 fileSumCompute 只实现了 ActionListener 接口。这样,您就不需要编写私有内部 class 来处理操作。您可以在需要的任何组件上使用 .addActionListener(this)
  • 接下来,我修改了 actionPerformed() 方法。我将它分成 3 部分,每个按钮一个。我还更改了变量的分配方式。你看起来已经很接近了,但有些地方不对劲。据我了解,您需要获取源文件,读入源文件,对源文件中的每一行求和,然后将这些总和写入与源文件同名并附加 _out 的新文件。如果我误解了,我道歉。
  • 最后,我改变了computeF方法。再一次,你很接近。我将其更改为使用一种简单的方法逐行读取文件,可在本网站 here 上找到。它读入每一行,用 split() 方法拆分每一行,然后获取每个数字的 int 值。

有很多细微的变化。尝试研究并理解它们——这段代码并不完美,但阅读工作代码有助于理解概念。

此外,我知道 Java 面向对象编程作为一个整体可能令人望而生畏。我建议查看 Oracle 文档以获取有关 GUI 等概念的示例——那里有一些很好的示例。最后,不要试图在一夜之间学习这些。有很多东西要学,所以一次只花一天时间。另外,不要害怕查看此站点的代码片段。这里有很多好的解决方案,比如我找到的那个。