This question already has answers here:
What is a stack trace, and how can I use it to debug my application errors?
(7 answers)
Closed 3 years ago.
I'm currently writing a program that will read in a CSV file that contains data about age, height, and weight. My issue is, when I call in the method that reads the file from the main, it throws an IOException. I'm not sure what's causing this, and as this is for a project, I am not allowed to throw an IOException from the main() method. I inserted a output print line to try and spot where the bug occurs, because debug mode in eclipse is not allowing me to do so, and it seems that the error occurs before the readFile() method even starts.
I am extremely rusty in java and code in general, and am taking this class after not touching coding for an extended period of time. I'm not sure exactly where to start to try and debug this IOException.
public class Project1 {
public static void main(String[] args) {
//main method declaring project object
Project1 project = new Project1();
String fileName = project.checkArgs(args);
File blah = null; //temporary name for the file don't pay attention to it
try {
blah = project.getFile(fileName); //gets the file and sets it to variable in main
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
project.readFile(blah, 500); //trying to read in file of 2d array in the readFileMethod
}
catch (IOException i) { //method gets caught here
System.out.println("IOException");
}
}
//readFile METHOD
public String[][] readFile(File file, int numRecords) throws IOException {
//two parameters: file, being read in this method, and numRecords the amount
//of elements in the array (I haven't done anything with numRecords yet and I
//believe this may possibly be the source of the error
Scanner reader = new Scanner(file); //scanner to read in file
//2d array to be passed back to main
String[][] data = new String[numRecords][3];
System.out.println("hi"); //test for IOException, doesn't get to this point
int iteration = 0; //to skip first line of text in csv file
while (reader.hasNextLine()) { //loading in elements to 2d array
iteration++;
if (iteration < 1) {
reader.nextLine();
continue;
}
else {
String list[] = reader.nextLine().trim().split(",");
for (int i = 0; i < numRecords; i++) {
for (int j = 0; j < 3; j++) {
data[i][j] = list[j];
System.out.println(data[i][j]);
}
}
}
}
return data;
}
The program catches the IOException in method main().
I can't find the reason, please provide a stack trace (i.printStackTrace()).
Since you do not use the delimiters of the scanner, you may try another way:
BufferedReader br = new BufferedReader(new FileReader(file), bufferSize);
String line;
if ((line = br.readLine()) != null) {
// process the line
}
Related
I'm looking at some code for a program which takes a file input and reads it, returning specifics about the data inside such as the amount of words, lines, and characters. In all of the methods which perform those tasks, a nested try block is used as shown in the method below, taken from the program:
private static int countSentences(String inputFile){
int numOfSentences=0;
String delimiters = ".!?";
try{
File input = new File(inputFile);
try (Scanner reader = new Scanner(new FileInputStream(input))) {
while (reader.hasNextLine()) {
String line = reader.nextLine();
for (int i = 0; i < line.length(); i++) {
if (delimiters.indexOf(line.charAt(i)) != -1) {
numOfSentences++;
}
}
}
}
}
catch (Exception ex) {
}
return numOfSentences;
}
Now, the thing which gets to me is the nested try blocks purpose. In the same program, I took away the nested try block and left the single one and its contents which in turn, led to no change in the output.
Is this nested try block redundant in this case? Or is it there for some exception which I have not handled yet?
I wrote a program that generates random numbers into two text files and random letters into a third according the two constant files. Now I need to read from each text file, line by line, and put them together. The program is that the suggestion found here doesn't really help my situation. When I try that approach it just reads all lines until it's done without allowing me the option to pause it, go to a different file, etc.
Ideally I would like to find some way to read just the next line, and then later go to the line after that. Like maybe some kind of variable to hold my place in reading or something.
public static void mergeProductCodesToFile(String prefixFile,
String inlineFile,
String suffixFile,
String productFile) throws IOException
{
try (BufferedReader br = new BufferedReader(new FileReader(prefixFile)))
{
String line;
while ((line = br.readLine()) != null)
{
try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(productFile, true))))
{
out.print(line); //This will print the next digit to the right
}
catch (FileNotFoundException e)
{
System.err.println("File error: " + e.getMessage());
}
}
}
}
EDIT: The digits being created according to the following. Basically, constants tell it how many digits to create in each line and how many lines to create. Now I need to combine these together without deleting anything from either text file.
public static void writeRandomCodesToFile(String codeFile,
char fromChar, char toChar,
int numberOfCharactersPerCode,
int numberOfCodesToGenerate) throws IOException
{
for (int i = 1; i <= PRODUCT_COUNT; i++)
{
int I = 0;
if (codeFile == "inline.txt")
{
for (I = 1; I <= CHARACTERS_PER_CODE; I++)
{
int digit = (int)(Math.random() * 10);
try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(codeFile, true))))
{
out.print(digit); //This will print the next digit to the right
}
catch (FileNotFoundException e)
{
System.err.println("File error: " + e.getMessage());
System.exit(1);
}
}
}
if ((codeFile == "prefix.txt") || (codeFile == "suffix.txt"))
{
for (I = 1; I <= CHARACTERS_PER_CODE; I++)
{
Random r = new Random();
char digit = (char)(r.nextInt(26) + 'a');
digit = Character.toUpperCase(digit);
try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(codeFile, true))))
{
out.print(digit);
}
catch (FileNotFoundException e)
{
System.err.println("File error: " + e.getMessage());
System.exit(1);
}
}
}
//This will take the text file to the next line
if (I >= CHARACTERS_PER_CODE)
{
{
Random r = new Random();
char digit = (char)(r.nextInt(26) + 'a');
try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(codeFile, true))))
{
out.println(""); //This will return a new line for the next loop
}
catch (FileNotFoundException e)
{
System.err.println("File error: " + e.getMessage());
System.exit(1);
}
}
}
}
System.out.println(codeFile + " was successfully created.");
}// end writeRandomCodesToFile()
Being respectfull with your code, it will be something like this:
public static void mergeProductCodesToFile(String prefixFile, String inlineFile, String suffixFile, String productFile) throws IOException {
try (BufferedReader prefixReader = new BufferedReader(new FileReader(prefixFile));
BufferedReader inlineReader = new BufferedReader(new FileReader(inlineFile));
BufferedReader suffixReader = new BufferedReader(new FileReader(suffixFile))) {
StringBuilder line = new StringBuilder();
String prefix, inline, suffix;
while ((prefix = prefixReader.readLine()) != null) {
//assuming that nothing fails and the files are equals in # of lines.
inline = inlineReader.readLine();
suffix = suffixReader.readLine();
line.append(prefix).append(inline).append(suffix).append("\r\n");
// write it
...
}
} finally {/*close writers*/}
}
Some exceptions may be thrown.
I hope you don't implement it in one single method.
You can make use of iterators too, or a very simple reader class (method).
I wouldn't use List to load the data at least I guarantee that the files will be low sized and that I can spare the memory usage.
My approach as we discussed by storing the data and interleaving it. Like Sergio said in his answer, make sure memory isn't a problem in terms of the size of the file and how much memory the data structures will use.
//the main method we're working on
public static void mergeProductCodesToFile(String prefixFile,
String inlineFile,
String suffixFile,
String productFile) throws IOException
{
try {
List<String> prefix = read(prefixFile);
List<String> inline = read(inlineFile);
List<String> suffix = read(productFile);
String fileText = interleave(prefix, inline, suffix);
//write the single string to file however you want
} catch (...) {...}//do your error handling...
}
//helper methods and some static variables
private static Scanner reader;//I just prefer scanner. Use whatever you want.
private static StringBuilder sb;
private static List<String> read(String filename) throws IOException
{
List<String> list = new ArrayList<String>;
try (reader = new Scanner(new File(filename)))
{
while(reader.hasNext())
{ list.add(reader.nextLine()); }
} catch (...) {...}//catch errors...
}
//I'm going to build the whole file in one string, but you could also have this method return one line at a time (something like an iterator) and output it to the file to avoid creating the massive string
private static String interleave(List<String> one, List<String> two, List<String> three)
{
sb = new StringBuilder();
for (int i = 0; i < one.size(); i++)//notice no checking on size equality of words or the lists. you might want this
{
sb.append(one.get(i)).append(two.get(i)).append(three.get(i)).append("\n");
}
return sb.toString()
}
Obviously there is still some to be desired in terms of memory and performance; additionally there are ways to make this slightly more extensible to other situations, but it's a good starting point. With c#, I could more easily make use of the iterator to make interleave give you one line at a time, potentially saving memory. Just a different idea!
I'm tasked, by my professor, to write a program to read a .csv file (778 rows (including header row), 8 columns).
I need to:
1. Write a method to receive the name of the file as its argument and then print the number of lines in the file.
public void printNumberOfLinesInFile(String fileName)
Write a method to receive the name of the file as its argument and then print the number of private and non-private colleges.
public void printNumberOfPrivateNonPrivateCollegesInFile(String fileName)
Write a method to receive the name of the file as its argument and then print the private college name with largest out of state tuition.
public void printMostExpensivePrivateCollegeInFile(String fileName)
Write a method to receive the name of the file as its argument and then print the non-private college with largest out of state tuition.
public void printMostExpensiveNonPrivateCollegeInFile(String fileName)
Write a method to receive the name of the file as its argument and then print the number of applications and the number of applicants that are accepted for private and non-private colleges.
public void printNumberOfApplications(String fileName)
Write a method to receive the name of the file as its argument and then print following information for private and non-private colleges.
Average of expenses for books.
Average of expenses for room.
Average of personal expenses.
public void printAverageOfExpenses(String fileName)
Disclaimer: I do not want anyone to do my homework for me. I need to learn so I can apply my knowledge when I graduate and enter industry. I'm simply asking for a hint or a better way at writing the code.
My code thus far:
public class Week14
{
public String data;
public void printNumberOfLinesInFile(String inFile) throws IOException
{
int collegeCount = 0;
FileReader fileRead = new FileReader(inFile);
BufferedReader bufferRead = new BufferedReader(fileRead);
while(true)
{
String line = bufferRead.readLine();
if(line == null)
{
break;
}
collegeCount++;
//System.out.println(line);
}
System.out.println(collegeCount-1 + " Colleges total.");
}
public void printNumberOfPrivateNonPrivateCollegesInFile(String inFile) throws IOException
{
int privateCount = 0;
int nonprivateCount = 0;
int count = 0;
FileReader fileRead = new FileReader(inFile);
BufferedReader bufferRead = new BufferedReader(fileRead);
while((data = bufferRead.readLine())!= null)
{
String line = bufferRead.readLine();
String [] lineItems = line.split(",");
for(int i = 0; i < line.length(); i++)
{
if(lineItems[i].equals("Yes"))
{
privateCount++;
}
}
break;
}
System.out.println(privateCount+" private Colleges.");
System.out.println(nonprivateCount+ " non-private Colleges.");
}
public void printMostExpensivePrivateCollegeInFile(String inFile) throws FileNotFoundException, IOException
{
int mostExpensive = 0;
int currentExpensive = 0;
FileReader fileRead = new FileReader(inFile);
BufferedReader bufferRead = new BufferedReader(fileRead);
while((data = bufferRead.readLine())!= null)
{
String line = bufferRead.readLine();
if(line.equals("OutstateTuition"))
{
System.out.println(line);
}
else
{
System.out.println(line);
}
}
}
public void printMostExpensiveNonPrivateCollegeInFile(String fileName)
{
}
public void printNumberOfApplications(String fileName)
{
}
public void printAverageOfExpenses(String fileName)
{
}
public static void main(String[] args) throws FileNotFoundException, IOException
{
File inFile = new File("College.csv");
FileReader fileReader = new FileReader(inFile);
BufferedReader buffReader = new BufferedReader(fileReader);
Week14 w1 = new Week14();
//w1.printNumberOfLinesInFile("College.csv");
w1.printNumberOfPrivateNonPrivateCollegesInFile("College.csv");
//^^^The above line goes into an infinite loop^^^
//w1.printMostExpensivePrivateCollegeInFile("College.csv");
}
}
The problem is, I'm stuck on trying to count the amount of private and nonprivate colleges. In my method, printNumberOfPrivateNonPrivateCollegesInFile (line 39), I'm running into an exception: java.lang.ArrayIndexOutOfBoundsException: 8
I've asked my professor how I can avoid this, I've looked online and the problem seems to lie with the iterator int 'i'. I'm trying to traverse the array, and 'i' is out of bounds. When I put a '1' in
if(lineItems[i].equals("Yes"))
for my privateCount, there is an output of 67 from privateCount, (I think it is counting the individual characters for some reason).
My question, what would be the most effective way to traverse the entire .csv file, and to access individual columns so I can count them and output them?
Any help would be greatly appreciated.
edit:
I have changed the while loop:
while(true)
{
String line = bufferRead.readLine();
String [] lineItems = line.split(",");
if(line == null)
{
break;
}
for (String lineItem : lineItems) {
privateCount++;
}
}
Now I can traverse the entire .csv file, but I'm receiving a java.lang.NullPointerException when I try and count.
edit 2:
I've redone my while loop again,
while(true)
{
String line = bufferRead.readLine();
String [] lineItems = line.split(",");
for (String lineItem : lineItems) {
if (lineItem.equals("Yes")) {
privateCount++;
}
}
System.out.println(privateCount);
}
I'm now counting the right value for privateCount, but there's a NullPointerException at :
String [] lineItems = line.split(",");
and the loop will not let me put my 'echo' outside of the while-loop without a 'break' statement.
With respect to actual industry-level code, and assuming that assignment did not specifically focus on actual CSV decoding, I would recommend finding and using a library to handle low-level decoding, such as OpenCSV, SuperCSV or CSV-module for Jackson.
This way your code can focus on more interesting part of finding specific values, and not on intricate details like possible escaping and/or quoting of contents.
If the focus is on CSV edge cases this is not the approach to use; but for real production code one hopefully rarely if ever writes the actual low-level decoding part, given the existence of multiple good libraries for the task.
if(lineItems != null && lineItems.length>0){
// do your loop
}
if (lineItem!= null && !lineItem.trim().equals("") && lineItem.equals("Yes")) {
privateCount++;
}
most likely will prevent your null issue
public void printNumberOfPrivateNonPrivateCollegesInFile(String inFile) throws IOException
{
int privateCount = 0;
int nonprivateCount = 0;
FileReader fileRead = new FileReader(inFile);
BufferedReader bufferRead = new BufferedReader(fileRead);
try
{
while(true)
{
String line = bufferRead.readLine();
String [] lineItems = line.split(",");
//System.out.println(Arrays.toString(lineItems));
for (String lineItem : lineItems)
{
if (lineItem!= null && !lineItem.trim().isEmpty() && lineItem.equals("No"))
{
nonprivateCount++;
}
if (lineItem!= null && !lineItem.trim().isEmpty() && lineItem.equals("Yes"))
{
privateCount++;
}
}
//System.out.println(privateCount);
}
}
catch(NullPointerException npe)
{
}
System.out.println(privateCount);
System.out.println(nonprivateCount);
}
Fixed it. I'm now just catching the exception so it isn't as annoying. Thanks all for the help.
I am working on an assignment and cannot get this method to produce the correct output to the file. I am supposed to get the mean and write it to the file. Their is the StatsDemo class and the StatsFile class. I am kind of a beginner at Java so I'd like just a little help. My method in the StatsFile class is currently like this:
//returns the calculated arithmetic average
public double calculateMean(String filename) throws FileNotFoundException
{
// declare variables step 5
double accumulator = 0.0;
int counter =0;
String line;
try{
File input = new File(filename);
//create a Scanner object passing it the File object
Scanner keyboard = new Scanner(input);
//for (int i = 0; i < input.length(); i++){
// Read a double from the file.
while(keyboard.hasNextDouble()){
accumulator += keyboard.nextDouble();
// Add to counter
counter++;
}
keyboard.close();
}catch(FileNotFoundException e){
}
return (accumulator/counter);
}
The demo is as such:
import java.util.Scanner;
import java.text.DecimalFormat;
import java.io.*;
public class StatsDemo {
public static void main(String[] args) throws FileNotFoundException {
// TODO Auto-generated method stub
DecimalFormat threeDec = new DecimalFormat("0.000");
Scanner keyboard = new Scanner(System.in);
String filename; // the user input file name
System.out.print("Enter the file name: ");
filename = keyboard.nextLine();
FileStats fileObj = new FileStats(filename);
try{
PrintWriter name = new PrintWriter("Results.txt");
name.println("mean = " + threeDec.format(fileObj.getMean()));
name.println("Standard Deviation = " + threeDec.format(fileObj.getStdDev()));
name.close();
}catch(IOException e){
System.out.println("Error");
}
}
}
The catches and throws still kind of confuse me. My issue is that it currently gives me a question mark instead of the mean when i open the file. Any help will be appreciated.
If an exception that occurs within the try block, control jumps to the catch block. You should think about what should happen in that case. You may be able to correct the problem and continue; you may wish to look at the problem and rethrow and exception, or you may wish just to let your caller handle the problem. In the last case, you don't need a catch at all, you can just need a throws on your method declaration.
Catching an exception and doing nothing is rarely a good idea as the problem is just being ignored. Remember that code flow will carry on after the catch clause unless another exception is thrown, so if the file does not exist, you will still process the return (accumulator/counter) line, which is not what you want.
Looking at your code, your method already throws a FileNotFoundException, so just remove the try and the catch.
I have a .csv file and I understand how to read it in Java, my problem is I want to be able to put the values of what is inside the file into a string and then read the string so I can calculate these values.
Alice Jones,80,90,100,95,75,85,90,100,90,92 Bob
Manfred,98,89,87,89,9,98,7,89,98,78
Those are the values, now how could I add up all the integers next to each name and create an average? MY biggest problem was when I read the file it was in a While loop and then was able to print out the lines just as it looks above into the console but when I wanted to print the values outside of the While loop it said the string doesn't exist so therefore I can't calculate the values if there is nothing in it.
import java.io.*;
import java.util.*;
public class Grades {
public static void main(String args[]) throws IOException
{
try{
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream("filescores.csv");
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
String strLine;
//Read File Line By Line
while ((strLine = br.readLine()) != null) {
// Print the content on the console
String line = strLine
System.out.println (strLine);
}
//Close the input stream
in.close();
}catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
}
}
I would suggest to implement a plain old java object (POJO) and store the data there:
public class MyRow {
public final String name;
public final int[] values;
public MyRow(String name, int[] values) {
this.name=name;
this.values=values;
}
}
And split your string and put it in a simple List<MyRow>:
MyRow splitData(String line) {
String[] parts=line.split(" ");
int[] vals=new int[parts.length];
// starting with one for skipping the name
for(int i=1; i<parts.length; i++) {
vals[i-1]=Integer.parse(parts[i]);
}
return new MyRow(parts[0], vals);
}
So basically your read loop will look like this:
List<MyRow> data = new ArrayList<MyRow>();
while((strLine = br.readLine()) != null) {
// Print the content on the console
System.out.println (strLine);
data.add(splitData(strLine));
}
Now all the data are in the data List.
when I wanted to print the values outside of the While loop it said
the string doesn't exist
As I commented you have scope issue in your code. However I dont see anything outside of while loop that your are printing or doing anything. You can use following code snippet to print the line outside of while loop.
ArrayList<String> lines = new ArrayList<String>();// Updated <String>
while ((strLine = br.readLine()) != null) {
// Print the content on the console
lines.add(strLine);
System.out.println(strLine);
}
for(int i = 0; i < lines.size(); i++){
System.out.println(lines.get(i));
}
Variable Scope
EDIT for comment
Note: Grades.java uses unchecked or unsafe operations.
Note: recompile with -Xlint: unchecked for details.
The above are just warning given by compiler to make you aware about unsafe collection use.
See here for more details.