java打开文件来自GUI的两个不规则数组

时间:2016-11-24 17:37:10

标签: java

所以我花了一个小时试图弄清楚如何从GUI打开这个文件,但每次我点击打开文件并点击我要打开的文件时,我的GUI就崩溃了。在这里,我的代码请告诉我什么是错的。 这是给我的,所以这不是错的。

import java.io.File;
import java.io.FileNotFoundException;
import java.text.NumberFormat;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;

public class MvGuiFx extends Application {;
    private double[][] sales;
    public static final int MAX_STORES = 6;
    public static final int MAX_ITEMS = 6;
    private NumberFormat currencyFormat = NumberFormat.getCurrencyInstance();
    Button readFileBtn, exitBtn;
    GridPane dataPane;


    /**
     * Lets the user choose a file to read the sales information and displays
     * the information on the screen
     * @throws FileNotFoundException 
     */
    public void readFile() throws FileNotFoundException {
        File selectedFile;

        FileChooser chooser = new FileChooser();
        chooser.setTitle("Choose a file to read retail items' sales information");
        if ((selectedFile = chooser.showOpenDialog(null)) != null) {
            // Read the file
            sales = TwoDimRaggedArrayUtility.readFile(selectedFile);
        }
        //display on the screen
        int row,col;
        double total;
        for(row=0;row<sales.length; row++)
            for(col=0;col<sales[row].length;col++)
                dataPane.add(new TextField(currencyFormat.format(sales[row][col])),col+1,row+1);

        //display row totals
        for(row=0;row<sales.length;row++)
        {
            total = TwoDimRaggedArrayUtility.getRowTotal(sales, row);
            dataPane.add(new TextField(currencyFormat.format(total)), 7, row+1);
        }

        //find the row with largest number of columns
        int columns = 0;
        for(row=0;row<sales.length;row++)
            if(sales[row].length > columns) columns = sales[row].length;

        //display column totals
        for(col=0;col<columns;col++)
        {
            total = TwoDimRaggedArrayUtility.getColumnTotal(sales, col);
            dataPane.add(new TextField(currencyFormat.format(total)), col+1, 7);
        }

        //find highest in each column
        for(col=0;col<columns;col++)
        {
            total = TwoDimRaggedArrayUtility.getHighestInColumn(sales, col);
            TextField temp = new TextField(currencyFormat.format(total));
            temp.setStyle("-fx-background-color: gray;");
            for(row=0;row<sales.length;row++) {
                if(col < sales[row].length){
                    if(sales[row][col]==total)
                        dataPane.add(temp, col+1, row+1);
                }
            }
        }


}

    // Handler class.
    private class ButtonEventHandler implements EventHandler<ActionEvent> {
        @Override
        public void handle(ActionEvent e) {
            //handler for Load Sales Data
            if (e.getSource() == readFileBtn) {

                try {
                    readFile();
                } catch (FileNotFoundException e1) {
                    e1.printStackTrace();
                }

            //handler for Exit button
            }  else if (e.getSource() == exitBtn)

                System.exit(0);
        }
    }

    @Override
    public void start(Stage stage) {

        Tooltip buttonToolTipArr[] = new Tooltip[5];
        buttonToolTipArr[0] = new Tooltip(
                "Load sales data from a file and Display");
        buttonToolTipArr[1] = new Tooltip("Exit Application");

        // Main Pane
        BorderPane MainPane = new BorderPane();

        // Create Title Pane, add title label and add it to the top of the Main
        // Pane
        HBox titlePanel = new HBox();
        titlePanel.setAlignment(Pos.BASELINE_CENTER);
        Label titleLbl = new Label("DisneyWorld District 5 Sales Report\n");
        titleLbl.setFont(new Font(30));
        titleLbl.setTextFill(Color.BLUE);

        titlePanel.getChildren().add(titleLbl);
        MainPane.setTop(titlePanel);

        // CenterPane
        VBox centerPane = new VBox();
        centerPane.setAlignment(Pos.CENTER);

        // columnHeader Pane
        HBox columnHeaderPane = new HBox(10);
        columnHeaderPane.setAlignment(Pos.CENTER);


        int i,j;
        dataPane = new GridPane();
        dataPane.setAlignment(Pos.BASELINE_CENTER);
        dataPane.add(new Label("     "), 0, 0);
        dataPane.add(new Label("Books"), 1, 0);
        dataPane.add(new Label("Tsum Tsum"), 2, 0);
        dataPane.add(new Label("Trading Pins"), 3, 0);
        dataPane.add(new Label("Star Wars"), 4, 0);
        dataPane.add(new Label("Lego"), 5, 0);
        dataPane.add(new Label("Marvel"), 6, 0);
        dataPane.add(new Label("Total"), 7, 0);

        for(i=1;i<8;i++)
        {
            dataPane.add(new Label("     "), 0,i);
            for(j = 1; j<8;j++)
                dataPane.add(new TextField(), i,j);
        }


        dataPane.add(new Label("Emporium"), 0, 1);
        dataPane.add(new Label("World Traveler"), 0, 2);
        dataPane.add(new Label("Discovery Trading Center"), 0, 3);
        dataPane.add(new Label("Merchant of Venus"), 0, 4);
        dataPane.add(new Label("Once Upon a Toy"), 0, 5);
        dataPane.add(new Label("Tatooine Traders"), 0, 6);
        dataPane.add(new Label("Total"), 0, 7);

        // Create bottom Pane
        HBox bottomPane = new HBox(10);
        bottomPane.setAlignment(Pos.BASELINE_CENTER);

        // Create buttons
        readFileBtn = new Button("Load Sales Data");
        readFileBtn.setTooltip(buttonToolTipArr[0]);
        exitBtn = new Button("Exit");
        exitBtn.setTooltip(buttonToolTipArr[1]);

        // add event handler to buttons
        readFileBtn.setOnAction(new ButtonEventHandler());
        exitBtn.setOnAction(new ButtonEventHandler());

        // add buttons to bottomPane
        bottomPane.getChildren().addAll(readFileBtn, exitBtn);
        MainPane.setBottom(bottomPane);

        // add panes to center pane
        centerPane.getChildren().addAll(dataPane);

        MainPane.setCenter(centerPane);

        Scene scene = new Scene(MainPane, 1200, 400);
        stage.setScene(scene);

        // Set stage title and show the stage.
        stage.setTitle("District Sales Report");
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

到目前为止我所拥有的:

import java.io.PrintWriter;
import java.util.Scanner;

public class TwoDimRaggedArrayUtility {

    public TwoDimRaggedArrayUtility()
    {

    }

    public static double[][] readFile(java.io.File file) throws java.io.FileNotFoundException
    {

        Scanner scan = new Scanner(file);
        int row = 0;

        while(scan.hasNextLine())
        {
            row++;
        }

        double[][] array = new double[row][];

        for(int index = 0; index < array[0].length; index++)

                array[0] = new double[index];

        for(int index = 0; index < array[1].length; index++)

                array[1] = new double[index];

        for(int index = 0; index < array[2].length; index++)

                array[2] = new double[index];

        for(int index = 0; index < array[3].length; index++)

                array[3] = new double[index];

        for(int index = 0; index < array[4].length; index++)

                array[4] = new double[index];

        for(int index = 0; index < array[5].length; index++)

                array[5] = new double[index];

        for(int index = 0; index < array[6].length; index++)

                array[6] = new double[index];

        for(int index = 0; index < array[7].length; index++)

                array[7] = new double[index];

        for(int index = 0; index < array[8].length; index++)

                array[8] = new double[index];

        for(int index = 0; index < array[9].length; index++)

                array[9] = new double[index];

        for(int index = 0; index < array[10].length; index++)

                array[10] = new double[index];

        scan.close();

        return array;
    }

    public static void writeToFile(double[][] data, java.io.File outputFile)throws java.io.FileNotFoundException
    {
        PrintWriter print = new PrintWriter(outputFile);
        print.print(data);
        print.close();
    }

这是衣衫褴褛的数组.txt文件:

1253.65 4566.50 2154.36 7532.45 3388.44 6598.23
2876.22 3576.24 1954.66
4896.23 2855.29 2386.36 5499.29
2256.76 3623.76 4286.29 5438.48 3794.43
3184.38 3654.65 3455.76 6387.23 4265.77 4592.45
2657.46 3265.34 2256.38 8935.26 5287.34

1 个答案:

答案 0 :(得分:1)

我说实话,你的代码有点不对。

首先,你最好完全避免使用GUI。如果将以下main方法添加到TwoDimRaggedArrayUtility,则可以直接运行此类而无需启动GUI:

public static void main(String[] args) throws Exception {
    double[][] sales = readFile(new java.io.File("path/to/your/file"));
    for (double[] row : sales) {
        System.out.println(java.util.Arrays.toString(row));
    }
}

如果一切顺利,应该在您的文件中读取并打印出内容。

首先,你的代码没有那么多崩溃(即停止了一个令人讨厌的错误),它实际上是挂起的(似乎无所事事)。

让我们先来看看这个循环:

    while(scan.hasNextLine())
    {
        row++;
    }

这是做什么的?

答案如下:当扫描仪中有下一行时,请在row 中添加一行。

请注意,您在任何时候都不会从扫描仪中读取任何行。因此,如果扫描仪中有任何文本,此循环将永远运行,无休止地增加row

要从扫描仪中读取一行,请调用其nextLine()方法。使用扫描仪时,在读取数据之前检查那里的一些数据是很常见的。所以我们现在有:

    while (scan.hasNextLine()) {
        String line = scan.nextLine();
        row++;
    }

如果我们对您的代码进行此更改,那么它就不会再挂起了。它读取文件中的所有行。但是,它会在此行上抛出NullPointerException

    for (int index = 0; index < array[0].length; index++)

要了解原因,我们需要查看上一行:

    double[][] array = new double[row][];

这是做什么的?它创建了一个包含6个元素的数组,因为row在完成6循环后最终得到值while。但是,数组中的每个元素(即每个&#39;内部数组&#39;)都是null,因为您还没有为内部数组指定大小。因此,当您尝试读取其中一个数组的长度时,会得到一个NullPointerException,因为没有数组可以读取它的长度。

暂时搁置一下,假设array[0].length返回,比如4。然后我们可能期望以下循环运行四次:

    for (int index = 0; index < array[0].length; index++)

        array[0] = new double[index];

这里的问题是这个循环的第一次迭代(index为零)然后将array[0]设置为空数组。下一次循环index为1,但array[0].length现在为0,因此循环结束。

这个循环并不是非常有用,因为它只运行一次,如果我们能够运行它,它只是创建一个double的空数组并将其放入{ {1}}。这个循环,以及其他十个循环,都不值得保留,所以让我们全部删除它们。

让我们回到顶部的array[0]循环:

while

我们仍然没有对 while (scan.hasNextLine()) { String line = scan.nextLine(); row++; } 正在阅读的内容做任何事情。我们希望将其分成数字并将其全部读入。目前,我们正在使用扫描仪将文件拆分成行,我们实际上可以使用另一台扫描仪将行拆分为数字:

line

请注意,我插入的五行与我们开始使用的 while (scan.hasNextLine()) { String line = scan.nextLine(); int column = 0; Scanner doubleScanner = new Scanner(line); while (doubleScanner.hasNextDouble()) { double value = doubleScanner.nextDouble(); column++; } row++; } 循环类似。在我们读出之前,我们检查是否还有另外while从双打扫描仪中读出来,就像我们在阅读线条时所做的那样。

这让我们更加接近。但是,虽然我们现在正在从线扫描仪中读取double值,但我们仍然没有将它们存储在任何位置。

不幸的是,这是事情在这里变得有点繁琐的地方。 Java的阵列是不灵活的,因为一旦你创建了它们,你就无法改变它们的大小。如果要使数组更大或更小,则必须创建所需大小的新数组并复制值。为了简单起见,并且因为这看起来像是一个类赋值而不是实际的生产代码,所以我们假设最多有10行和10列。因此,我们可以通过修改代码将值存储在数组中:

double

我添加了一行来创建数组,并调整了从 double[][] array = new double[10][10]; while (scan.hasNextLine()) { String line = scan.nextLine(); int column = 0; Scanner doubleScanner = new Scanner(line); while (doubleScanner.hasNextDouble()) { array[row][column] = doubleScanner.nextDouble(); ++column; } row++; } 中读取double的行。请注意,doubleScanner是一个包含10个数组的数组,每个内部数组都有10个元素,最初都设置为零。

此时我们现在应该可以运行代码并让它显示一些输出。但是,结果并不是我们想要的,因为行和列用零填充以使它们达到10×10。解决此问题的最简单方法可能是使用Arrays.copyOfRange()方法仅创建我们感兴趣的数组部分的副本,并将副本替换为副本。我们需要为每一行执行一次,对整个数组执行一次:

new double[10][10]

最后,这将返回我们想要的数据,没有任何填充零。

由于这是(疑似)课程作业,请花时间了解此代码的作用及其工作原理。使用软件,理解很重要。切勿盲目地将代码从互联网上复制而不了解它的作用。