【问题标题】:Cannot print to text file from within while-loop无法从while循环中打印到文本文件
【发布时间】:2014-06-16 05:38:24
【问题描述】:

所以我在我的程序中想要从 csv 文件(它有两列)中读取数据,对第一列进行一些简单的计算(在我检查它是否有任何内容之后),然后将新数字(我从第一个文件中的第 1 列计算)和第二列的内容从原始文件打印到新的文本文件。

如果没有 while 循环,我可以对原始文本文件中的数字进行计算,然后将它们打印到新文件中。但是,从 while 循环内部进行的任何打印都会给我一个错误。实际上,除了读取文件并将其解析为字符串数组之外的任何操作都会在 while 循环内部给我一个错误。

这些是我的 stackTrace 的前两行,下面是我目前发布的代码:

"Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 0
at finalProyect.User.makeMealPlan(User.java:476)"

第 476 行是我的 while 循环中的行:“if (array2[0].isEmpty())”

经过数小时的搜索和修改,我认为是时候寻求帮助了。提前感谢您提供的任何帮助。

public void makeMealPlan() {
    String fileIn = "mealPlan1.csv";
    Scanner inputStream = null;
    String fileOut = userName + ".txt";
    PrintWriter outputStream = null;

    try {
        inputStream = new Scanner(new File(fileIn));//opens and reads pre-configured meal plan
        outputStream = new PrintWriter(fileOut);//creates output file for meal plan
    } catch(FileNotFoundException e3) {
        fileNotFound();
        e3.printStackTrace();
    }
    outputStream.println(toString());
    outputStream.println();
    String line0 = inputStream.nextLine();
    String[] array0 = line0.split(","); //Splits line into an array of strings
    int baseCalories = Integer.parseInt(array0[0]); //converts first item in array to integer
    double caloricMultiplier = (caloricNeeds / baseCalories); //calculates the caloricMultiplier of the user
    String line1 = inputStream.nextLine();//reads the next line
    String[] array1 = line1.split(",");//splits the next line into array of strings
    outputStream.printf("%12s  %24s", array1[0], array1[1]); //prints the read line as column headers into text file
    while(inputStream.hasNextLine()) {
        String line = inputStream.nextLine(); //reads next line
        String[] array2 = line.split(",");
        if(array2[0].isEmpty()) {
            outputStream.printf("%12s  %24s", array2[0], array2[1]);
        } else {

            double quantity = Double.parseDouble(array2[0]);
            quantity = (quantity * caloricMultiplier);
            outputStream.printf("%12s  %24s", quantity, array2[1]);
        }
    }

    outputStream.close();
    System.out.println(toString());
}

好的,所以有些地方出了问题。但是,根据@NonSecwitter 的建议,我能够将其确定下来。所以第一件事(再次像 NonSecwitter 提到的那样)我的 .csv 中有空字段,这引发了 ArrayIndexOutOfBounds 错误。所以我所做的是我用字符串“empty”填充了 .csv 中的每个空字段。一旦我这样做了我至少能够打印下一行。

在那之后,我遇到了另一个错误,那就是这一行:

double quantity = Double.parseDouble(array2[0]);

不能通过在 if 循环中与前面的 read/split 语句分开。所以我最终重写了整个 while 循环的内容,并且需要像这样抛出异常:

while (inputStream.hasNextLine())
        {
            String[] array2 = null;
            try
            {
            String line = inputStream.nextLine(); //reads next line
            array2 = line.split(",");
            double quantity = Double.parseDouble(array2[0]);
            if (!isStringNumeric(array2[0]))
                throw new NumberFormatException();

            quantity = Math.ceil(quantity * caloricMultiplier);
            outputStream.printf("%12.1f  %15s\n", quantity, array2[1]);
            }
            catch(NumberFormatException e1)
            {
                if (array2[1].equals("empty"))
                    outputStream.printf("%12s  %15s\n", " ", " ");
                else
                    outputStream.printf("%12s %15s\n", " ", array2[1]);
            }

        }

虽然我的程序目前运行良好,但我仍然非常感谢您解释为什么我最终不得不抛出异常以使代码正常运行。在 while 循环中使用 PrintWriter 是否有某些限制?另外,我非常感谢大家的反馈。我认为结合所有 cmets/建议,我能够确定我的问题出在哪里(只是不知道为什么会出现问题)。

谢谢!!!

【问题讨论】:

  • 欢迎来到 SO!请提供触发您描述的错误的示例 CSV 数据。另外,在<userName>.txt 中提供您期望的相关输出示例。

标签: java while-loop printwriter


【解决方案1】:

注释掉有问题的代码并尝试 println() array2[0] 看看它是否给你任何东西。

while (inputStream.hasNextLine())
{
    String line = inputStream.nextLine(); //reads next line
    String[] array2 = line.split(",");
    System.out.println(array2[0]);

    //if (array2[0].isEmpty())
    //   outputStream.printf("%12s  %24s", array2[0], array2[1]);
    //  
    //else
    //{   
    //    
    //    double quantity = Double.parseDouble(array2[0]);
    //    quantity = (quantity * caloricMultiplier);
    //    outputStream.printf("%12s  %24s", quantity, array2[1]);
    //}
}

或者,尝试打印长度。如果由于某种原因数组为空,array2[0] 将超出范围

System.out.println(array2.length);

我还会打印 line 以查看它接收到的内容

System.out.println(line);

【讨论】:

  • @St3v3-0 关于第二个问题,当Double.parseDouble 尝试解析不包含数字字符的字符串时,会导致错误。您的捕获只是通过不尝试转换来优雅地处理错误,并使用printf 格式化%12s 而不是%12.1f
  • 这是有道理的。直到你说我从来没有注意到每次在我的程序中对潜在的非数字数据执行 Number.parseNumber 时,它都会立即出现异常。
  • 这对我提出了另一个问题。如果尝试将字符串解析为某种类型的数字会导致错误,那么程序如何通过 if 语句在解析语句之外继续运行并允许它被抛出的异常捕获?解析失败后似乎会立即引发运行时错误。 if 语句或不言而喻的机器语言规则是否有一些特殊的力量,只要在错误的解析后抛出 if 语句,它就可以继续运行?
  • 我无法肯定地回答这个问题,但我的第一个猜测是它与try 子句有关。
【解决方案2】:

如果您在 <userName>.txt 中提供示例 CSV 数据和相关输出示例,将会有所帮助。

除此之外,我只能说 我的代码没有异常

这是我在 Eclipse 中使用从异常输出中收集的项目和类文件名(分别为finalProyectUser.java)获得的快速 Java 项目,将代码粘贴到类文件中 (User.java) ,然后稍微按摩一下以进行健全性检查...

package finalProyect;

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

public class User {
    public void makeMealPlan()
    {
        String fileIn = "C:\\Temp\\mealPlan1.csv";//"mealPlan1.csv"; // FORNOW: adjusted to debug
        Scanner inputStream = null;
        String userName = "J0e3gan"; // FORNOW: added to debug
        String fileOut = "C:\\Temp\\" + userName  + ".txt"; // FORNOW: adjusted to debug
        PrintWriter outputStream = null;

        try
        {
            inputStream = new Scanner(new File(fileIn));//opens and reads pre-configured meal plan
            outputStream = new PrintWriter(fileOut);//creates output file for meal plan
        }   
        catch(FileNotFoundException e3)
        {
            //fileNotFound(); // FORNOW: commented out to debug
            e3.printStackTrace();
        }
        outputStream.println(toString());
        outputStream.println();
        String line0 = inputStream.nextLine();
        String[] array0 = line0.split(","); //Splits line into an array of strings
        int baseCalories = Integer.parseInt(array0[0]); //converts first item in array to integer
        int caloricNeeds = 2000; // added to debug
        double caloricMultiplier = (caloricNeeds  / baseCalories); //calculates the caloricMultiplier of the user
        String line1 = inputStream.nextLine();//reads the next line
        String[] array1 = line1.split(",");//splits the next line into array of strings
        outputStream.printf("%12s  %24s", array1[0], array1[1]); //prints the read line as column headers into text file
        while (inputStream.hasNextLine())
        {
            String line = inputStream.nextLine(); //reads next line
            String[] array2 = line.split(",");
            if (array2[0].isEmpty())
                outputStream.printf("%12s  %24s", array2[0], array2[1]);

            else
            {   

                double quantity = Double.parseDouble(array2[0]);
                quantity = (quantity * caloricMultiplier);
                outputStream.printf("%12s  %24s", quantity, array2[1]);
            }
        }

        outputStream.close();
        System.out.println(toString());
    }

    public static void main(String[] args) {
        // FORNOW: to debug
        User u = new User();
        u.makeMealPlan();
    }
}

...以及它输出到J0e3gan.txt...的示例...

finalProyect.User@68a6a21a

        3000                        40      2500.0                        50      4000.0                        25

...mealPlan1.csv 中包含以下(完整的 WAG)数据:

2000,20
3000,40
2500,50
4000,25

【讨论】:

    猜你喜欢
    • 2016-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-08
    • 2021-06-17
    • 1970-01-01
    • 2017-04-23
    • 2016-03-24
    相关资源
    最近更新 更多