Format a chart of random numbers from a .txt - java

I want to put a newline character at a certain position instead of all of my numbers then newline character.
I tried to put the newline character with System.out.print("\n"); outside of the loop but I can't figure out how to put it at a certain position. I want my chart to be a simple 10 x 10 chart, with 10 numbers per row, 10 rows in total. My numbers.txt has 100 random numbers.
import java.io.*;
public class numbersChart {
public static void main(String[] args) throws IOException {
File myFile = new File("numbers.txt");
Scanner text = new Scanner(myFile);
while (text.hasNextInt()) {
System.out.print("\n");
System.out.printf("%6s", " ");
System.out.print(text.nextInt());
}
}
}

You don't really need the while loop, the idea is to put \n after 10ths numbers.
Try the code below:
public static void main(String[] args) throws IOException {
File myFile = new File("numbers.txt");
Scanner scanner = new Scanner(myFile);
int d = 10;
for (int i = 0; i < d * d; i++) {
if (scanner.hasNextInt()) {
System.out.print(scanner.nextInt());
} else {
break;
}
if ((i + 1) % d == 0) {
System.out.println();
} else {
System.out.print(" ");
}
}
}

Build your rows as you read the file pretty much in the same fashion as you are doing. Print each row (of whatever) as they are developed. Using a while loop to read the file is the usual practice for this sort of thing since you may not necessarily know exactly how many numbers may actually be contained within the file to generate the chart (table). In your particular case you for whatever reason know there are going to be 100 numbers. This however may not always be the case in other real world situations. Your code should be able to create table rows of ten (or whatever you desire) whether there is 1 number or 1 million (or even more) numbers in the file.
A slightly different play on the task would be to consider a numerical data file which contains any number of numerical values be it signed or unsigned integer, floating point or both. We want to read this file so to create and display a numerical table consisting of whatever desired number of rows with all rows consisting of whatever number of columns with the exception of perhaps the last row which there may not be enough values in the data file to accommodate the require number of columns. The columns are to also be spaced to our desired width when creating the table.
With the supplied code below, this can all be accomplished. Maximum Rows, columns, and table spacing is all configurable. I suggest you read the comments in code for further insight:
/* Create a numbers.txt file for testing. Save a copy
of your existing one somewhere else for safekeeping
if you use this portion of code! */
int quantityOfNumbers = 100;
// 'Try With Resources' used here to auto-close the writer.
try (java.io.PrintWriter writer = new java.io.PrintWriter(new java.io.File("numbers.txt"))) {
for (int i = 1; i <= quantityOfNumbers; i++) {
writer.append(String.valueOf(i));
if (i < quantityOfNumbers) {
writer.write(System.lineSeparator());
}
}
writer.flush();
}
catch (FileNotFoundException ex) {
System.err.println(ex.getMessage());
System.exit(0);
}
// ---------------------------------------------------------------------
String fileName = "numbers.txt"; // The numerical data file to read.
int desiredColumns = 10; // The number of columns per row you want.
int formatSpacing = 8; // Each column will be this many spaces wide.
int maxRows = 0; // Max rows we might want. If 0 then unlimited.
java.io.File myFile = new java.io.File(fileName); // File Object
// Read & process the numerical data file...
// 'Try With Resources' used here to auto-close the reader.
try (Scanner reader = new Scanner(myFile)) {
String num;
StringBuilder sb = new StringBuilder(""); // Used for building each numerical row
int columnCounter = 0; // Used to keep track of columns added to 'sb'.
int rowCounter = 0; // Used to keep track of the number of rows created.
while (reader.hasNextLine()) { // Read file until there is nothing left to read.
num = reader.nextLine().trim(); // Retrieve data line on each iteration.
/* Make sure the line in the file is actually a number
and not something alphanumeric or a blank line. Carry
out some form of validation. The regular expression
(regex) within the matches() method allows for signed
or unsigned integer or floating point string numerical
values. If it's invalid we skip the line. Remove this
`if` block if you want everything regardless: */
if (!num.matches("-?\\d+(\\.\\d+)?")) {
continue;
}
columnCounter++; // Valid line so increment Column Counter by 1
/* Format the string value as we append to sb. If you want the
table values right justified then remove the '-' from the format. */
sb.append(String.format("%-" + String.valueOf(formatSpacing) + "s", num));
if (columnCounter == desiredColumns) { // Have we reached our desired number of columns?
System.out.println(sb.toString()); // Print the row to console.
sb.setLength(0); // Clear the StringBuilder object (sb).
columnCounter = 0; // Reset the Column Counter to 0.
rowCounter++; // Increment Row Counter by 1
if (rowCounter == maxRows) { // If we've reach our max rows then stop reading.
break; // Break out of 'while' loop.
}
}
}
/* Reading has finished but is there anything that didn't
make 10 columns worth of data? If the StringBuilder
object (sb) contains anything at this point then yes
there is something so print it to console window. */
if (!sb.toString().isEmpty()) {
System.out.println(sb.toString());
}
}
catch (FileNotFoundException ex) {
// Whoops...can't find the numerical data file.
System.err.println("Can not locate the numerical data file!");
System.err.println("Data File: --> " + myFile.getAbsolutePath());
}

Related

How to read predefined number of lines from scanner input based on multiple conditions for the input line

I need to read maximum 10 lines, with each lines having only characters * and . also with other conditions like begin with * and length 10. the last line that should be read should have a line following it with the word END. I want to know if there is a better way to solve it than below. If I can check all the conditions within the while loop
Scanner keyboard = new Scanner(System.in);
int countLine = 0;
String line = "";
while (countLine < 10) {
line = keyboard.nextLine();
countLine++;
if (line.matches("[*.]+") && !line.equals("END") && line.startsWith("*") && line.length() < 10
) {
// do something
} else {
break;
}
}
keyboard.close();
One way you can do this is:
read the entire document into your application.
parse each (row/column) into arrayLists (so the first 10 lines of the document)
perform necessary calculations (still in the while loop).

Java Reading Strings to a 2D Boolean Array

I am trying to read a txt file which consists of # and spaces to a 2D boolean array, so that technically a # represents true and a space represents false.
With the help of similar posts i got together a code, although they were reading integers to an array.
My code is:
public static void main(String[] args) {
String x;
String y;
Scanner fileName = null;
try {
fileName = new Scanner(new File("C:/Users/USER/Desktop/hashtag.txt"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
x = fileName.nextLine();
y = fileName.nextLine();
boolean[][] cells = new boolean[x][y];
String finalX = fileName.nextLine();
String finalY = fileName.nextLine();
cells[finalX][finalY] = true;
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[i].length; j++) {
if (cells[i][j])
System.out.print("#");
else
System.out.print(" ");
}
System.out.println();
}
}
In my code where I have written boolean[][] cells = new boolean[x][y];
It says the [x] and [y] requires an int, but found a string. The same issue is for cells[finalX][finalY] = true;
I tried parsing i.e. Integer.parseInt(x) however this gets me an error:
Exception in thread "main" java.lang.NumberFormatException: For input string: "#####################"
At what point is my issue? If I parse to an Int, then it can't read the # correct?
I think this would solve it:
1- read each line of file until the end of it to get the number of cells rows which is n then take length of any String line to get number of columns which is m.
2- create boolean array cells[n][m].
3- read file line by line and put each line in String variable and iterate over the string variable characters if character is # put true in cells array otherwise put false.
String line="";
int n=0;
while(fileName.hasNextLine()){
line = fileName.nextLine();
n++;
}
int m = line.length();
boolean[][] cells = new boolean[n][m];
// initialize Scanner to read file again
Scanner in = new Scanner(new File("C:/Users/USER/Desktop/hashtag.txt"));
int i=0;
while(in.hasNextLine()){
line = in.nextLine();
for(int j=0; j < line.length(); j++){
char c = line.charAt(j);
if(c == '#'){
cells[i][j] = true;
}
else{
cells[i][j] = false;
}
}
i++;
}
You have many mistakes in code and this approach is definitely wrong, you don't even save values that you read from file inside array. Also this code is simply not how you do it, for reading files where you don't know length of file you want to use Lists where you don't need to specify number of elements that list will take(its possible to do get semi-working solution with arrays but there is no point of learning something that is simply wrong). Before even trying to work with files you should learn more basic things, you don't even initialize your arrays properly, you use string for size and index which is causing those issues you mentioned, another beginner mistake is trying to parse non-integer string to int(you are trying to convert ############ to int which is impossible, you can only use this if you know that string is an integer like 1 or 5 or 1000).
So my answer to your question is to just go slowly and learn basics then add new stuff step by step instead just rushing with it.
It says the [x] and [y] requires an int, but found a string. The same
issue is for cells[finalX][finalY] = true;
I tried parsing i.e. Integer.parseInt(x) however this gets me an
error: Exception in thread "main" java.lang.NumberFormatException: For
input string: "#####################"
One approach you could do is first read the entire file.
Example:
List<String> tempList = new ArrayList<>();
while (fileName.hasNextLine()) {
String line = fileName.nextLine();
tempList.add(line);
}
then you can do this:
boolean[][] cells = new boolean[tempList.size()][tempList.get(0).length()];
note - this solution assumes the length() of each line is the same and the columns of each line is the same.
Also, why do you need to perform this outside the loop?
cells[finalX][finalY] = true;
you should remove that line and let the loop do all the work to determine what's # or ' '. Also, your if condition doesn't seem to be doing the correct operation. Consider implementing this approach and then go on from there.

Changing input loop condition skips half of input values

So I wrote a program that creates a red black tree and determines the percentage of red nodes in the tree. Right now I'm making the main method for it. So here's what I have right now:
public static void main(String[] args) {
Scanner s;
if (args.length > 0){
try{
s = new Scanner(new File(args[0]));
} catch(java.io.FileNotFoundException e){
System.out.printf("Unable to open %s\n",args[0]);
return;
}
System.out.printf("Reading input values from %s.\n",args[0]);
} else {
s = new Scanner(System.in);
System.out.printf("Enter a list of non-negative integers. Enter a negative value to end the list.\n");
}
RedBlackBST<String, Integer> st = new RedBlackBST<String, Integer>();
int i = 0;
while ((s.hasNextInt())){
int key = s.nextInt();
st.put(key, i);
i++;
}
double percent = percentRed();
System.out.println("There are " + redcount + " red nodes so");
System.out.println(percent + "% of the nodes are red");
}
What I'm trying to do is create a tree based on either a file of integers (so if the user runs the program by typing "java RedBlackBST test10.txt" which would contain 10 values to insert into the tree) or if the user doesn't specify a file then it would prompt the user to type in his own values and put a negative value at the end to end the list. Right now typing in your own values don't work but if you pass in a .txt file of numbers then it works exactly as intended. Now as for typing in your own values, I was thinking of changing the while loop to look like this:
while ((s.hasNextInt()) && (s.nextInt()) >= 0){
So what this is supposed to do is go through the list of values and if you hit a negative value in the list then it stops reading the values. The problem with this is that for some reason (even if I pass in a file) it only reads half the values for any array in integers. So how come changing the while loop has now made the program only read half the array values?
Also the put method that I'm calling is the insert method which inserts the values into the tree.
Assuming you literally made the precise change you mentioned, your loop would end up looking like:
while ((s.hasNextInt()) && (s.nextInt()) >= 0){
int key = s.nextInt();
st.put(key, i);
i++;
}
Which calls nextInt() twice per iteration, which of course skips every other value, as nextInt() consumes the input.
One typical approach here is to declare key outside the loop so you have it available in the condition's scope, then assign and test it all in one go, like:
int key;
while ((s.hasNextInt()) && (key = s.nextInt()) >= 0){ // <- key is assigned *and* tested
st.put(key, i);
i++;
}
Thus, one nextInt() per iteration.

Read from .csv excel file and compute average

How do I read a .csv excel file with x number of rows and y number of columns, ignore irrelevant cells (things like names), then compute an average of the numbers in each column?
The Excel I have is something like this (, indicates new cell):
ID, week 1, week 2, week 3, .... , week 7
0 , 1 , 0.5 , 0 , , 1.2
1 , 0.5 , 1 , 0.5 , , 0.5
y , ......
so, how do I make it so it reads that kind of .csv file then computes an average in the format Week 1 = (Week 1 average), Week 2 = (week2 average) for all weeks?
Also am I correct in assuming I need to use a 2D Array for this?
Edit
Here's my code so far, it's very crude and I'm not sure if it does things properly yet:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class ClassAverage {
public static void main(String[] args){
readFile2Array("attendance.csv");
}
public static double[][] readFile2Array(String fileName){
try {
int rowCount = 0;
int colCount = 0;
Scanner rc = new Scanner(new File("attendance.csv"));
while (rc.hasNextLine()) {
rowCount++;
rc.nextLine();
}
rc.close();
System.out.println(rowCount);
Scanner cc = new Scanner(new File("attendance.csv"));
while (cc.hasNext()) {
colCount++;
cc.next();
}
cc.close();
colCount = colCount/rowCount;
System.out.println(colCount);
Scanner sc = new Scanner(new File("attendance.csv"));
double[][] spreadSheet = new double[rowCount][colCount];
while (sc.hasNext()) {
for (int i=0; i<spreadSheet.length; ++i){
for (int j=0; j<spreadSheet[i].length; ++j){
spreadSheet[i][j] = Double.parseDouble(sc.next());
}
}
}
sc.close();
return spreadSheet;
} catch (FileNotFoundException e) {
System.out.println("File cannot be opened");
e.printStackTrace();
}
return null;
}
public static double weeklyAvg(double[][] a){
}
}
So a summary of what it's intended to do
readFile2Array: read the csv file and count the number of rows, then count the total number of cells, divide total number of cells by number of rows to find number of columns. Read again and put each cell into the correct place in a 2D array.
weeklyAvg: I haven't thought up a way to do this yet, but it's supposed to read the array column by column and compute an average for each column, then print out the result.
PS. I'm very new at Java so I have no idea what some suggestions mean so I'd really appreciate suggestions that are pure java based without addons and stuff (I'm not sure if that's what some people are suggesting even). I hope it's not too much to ask for (if it's even possible).
You can use a Java library to handle your CSV file. For example opencsv ( you can find the latest maven version here http://mvnrepository.com/artifact/com.opencsv/opencsv/3.5)
And then you can parse your file like this :
CSVReader reader = new CSVReader(new FileReader("PATH_TO_YOUR_FILE"));
String[] nextLine;
int counter = 0;
while ((nextLine = reader.readNext()) != null) {
// nextLine[] is an array of values from the line
System.out.println(nextLine[0] + nextLine[1]);
}
You have to ignore the header line, you can simply do this by incrementing a counter and skipping the zero value.
To compute the average you can use a hashmap where the key is the column header name (example week 1). Then you increment with the current line value and after the loop is completed you divide by the number of lines (don't forget to substract the ignored lines like header line)
To parse simple CSV files, it's pretty simple to just manually parse through it, as long as you know the format is the same throughout the file and it does not contain errors
Create a storage data structure for each column you wish to compute (use a LinkedList<String>)
Read through the CSV file line by line with a BufferedReader
Use String.split(',') on each line and add the specific columns in the returned array to the correct LinkedList
Loop through the LinkedLists at the end and compute your averages (using Double.parseDouble() to convert the Strings to doubles)
To make sure that the String you're attempting to parse is a double, you can either use a try-catch statement or use a regex. Check Java: how to check that a string is parsable to a double? for more information

Getting InputMismatchException When Reading Text File into Integer Array

I am reading a text file filled with numbers (on individual lines) into an integer array. I thought I wrote the program well but am having issues when I try to run it. Netbeans is telling me "InputMismatchException." I think the problem is located in my second method called readTxtFile specifically the while loop. Any help would be greatly appreciated.
package arrayspa;
import java.util.Scanner;
public class ArraysPA {
/**
* Using the enrollment.txt file, count and display the number of full
* sections and the percentage of the sections that are full. A section is
* full if it contains 36 students.
*/
public static void main(String[] args) throws Exception
{
//an array to hold total # of students in each section
int[] numStud = new int[100];
int count; //number of elements actually used
int fullSections; //number of full sections (36 enrolled students)
int percent; //percentage of sections that are full
//read data into numStud[] from txt file
count = readTxtFile(numStud);
//print the array on the screen
System.out.println("The original file:");
displayLines(numStud,count);
//calculate number of sections that are full and display number
fullSections = calcFullSections(numStud, count);
System.out.println("There are "+fullSections+ "full sections.");
//display percentage of sections that are full
percent = fullSections/count;
System.out.println("The percentage of sections that are full is "
+percent);
} //end main()
/**
* This methods read data from enrollment.txt (located in project folder)
* line by line into an integer array. It then uses an if statement to
* display the total number of full sections (a section is considered full
* if there are 36 students enrolled).
*/
public static int readTxtFile(int[] numStud) throws Exception
{
int i=0; //number of elements in array initialized to zero
//Create File class object linked to enrollment.txt
java.io.File enrollment = new java.io.File("enrollment.txt");
//Create a Scanner named infile to read input stream from file
Scanner infile = new Scanner(enrollment);
/**Create while loop to read lines of text into array. It uses the
*Scanner class boolean function hasNextLine() to see if there is
*another line in the file.
*/
while (infile.hasNextLine())
{
//read a line and put it in an array element
numStud[i] = infile.nextInt();
i ++; //increment the number of array elements
} //end while
infile.close();
return i; //returns number of items used in the array
} //end readTxtFile(int[] numStud
public static void displayLines(int[] lines, int count)
{
int i; //loop counter
// iterate the elements actually used
for (i=0; i < count; i++)
System.out.println(lines[i]);
} //end displayLines()
public static int calcFullSections(int[] numStud, int count)
{
int fullSections=0; //number of full sections
int i; //loop counter
for (i=0; i < count; i++)
if (numStud[i]==36)
{
fullSections = fullSections + 1;
}
return fullSections;
} //end calcFullSections()
}
An InputMismatchException is thrown when input does not match the type of variable you are writing to. I have tested your code and it seemed to work fine unless the file "enrollment.txt" has a blank line or spaces. I have tested adding a blank line to the end of the file and running it, and I received a NoSuchElementException, so the problem is probably a blank line or non-integer somewhere in your file. To fix this, you can either remove any blank lines/non-integers in your file, or, preferably, you can modify your readTxtFile() method to ignore blank lines by catching a NoSuchElementException, like so:
public static int readTxtFile(int[] numStud) throws Exception
{
int i=0; //number of elements in array initialized to zero
//Create File class object linked to enrollment.txt
java.io.File enrollment = new java.io.File("enrollment.txt");
//Create a Scanner named infile to read input stream from file
Scanner infile = new Scanner(enrollment);
/**Create while loop to read lines of text into array. It uses the
*Scanner class boolean function hasNextLine() to see if there is
*another line in the file.
*/
while (infile.hasNextLine())
{
// Add this try/catch block to prevent reading blank line
try {
numStud[i] = infile.nextInt();
i ++;
} catch (NoSuchElementException e) {
}
} //end while
infile.close();
return i; //returns number of items used in the array
} //end readTxtFile(int[] numStud
As you can see, I have added a try/catch block into your readTxtFile() void that catches a NoSuchElementException, which includes InputMismatchException, preventing an attempt to add in any non-integers. I hope this solves your problem!

Categories