Convert String array to an Int array and total it - java

I need to create a program that accepts input from a file. I need to ask the user to enter two(2) variables, the interest rate and months for the loan. I then calculate the monthly payment, output the original input from the file along with the number of months on the loan and the monthly payment.
I am having issues with getting the numbers in the array to int's so that I can calculate them. I have tried a few things, but cannot get this to do what I want. After reading through some other questions I was able to find how to convert the array to an int and get the sum so I have included this in the code. I know how to do the calculations after I get the array of "item" to an int. I am only looking for assistance on the part of converting item[1] to an array that I can use to calculate the sum of the items. I have included comments in the code that might better show what I'm looking for.
This is what the input file looks like:
Driver 425
Putter 200
Wedges 450
Hybrid 175
This is my code:
import java.io.*;
import java.util.Scanner;
import java.util.ArrayList;
import java.util.*;
public class Assignment3t {
public static void main(String[] args) {
File inputFile = new File("Project3.txt");
File outputFile = new File("Project3Output.txt");
Scanner scanner = new Scanner(System.in);
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
System.out.print("Enter the interest rate: ");
float interestRate = scanner.nextFloat();
System.out.print("Enter months for the loan: ");
int loanMonths = scanner.nextInt();
try {
bufferedReader = new BufferedReader(new FileReader(inputFile));
bufferedWriter = new BufferedWriter(new FileWriter(outputFile));
String line;
while ((line = bufferedReader.readLine()) !=null) {
String[] item = line.split("\\s+");//create an array. This is the part I cant figure out. It creates the array, but I cant figure out how to get this data to "results" below.
int[] results = Stream.of(item).mapToInt(Integer::parseInt).toArray(); //converts the string array to an int array.
int sum = Arrays.stream(results).sum(); //calculates the sum of the array after its converted to an int to use in the monthly payment calculation.
bufferedWriter.write(line);
bufferedWriter.newLine();
}
bufferedWriter.write("Number of months of the loan: " + String.valueOf(loanMonths));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bufferedReader.close();
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

Your input consists of alternating numeric and non-numeric data. And after splitting the line on white spaces with split("\\s+") you are trying all the strings into int. That will inevitably lead to NumberFormatException at runtime.
To avoid that you need to add a filter() to the stream to ensure that only strings that are comprised of digits will be parsed.
And since you are using int[] results only as a source of the second stream that calculates the sum then you should get rid of redundancy. There's no need to create a second stream and allocate in memory unused array.
Another mistake is that the scope of the variable sum is limited to the while loop. And according to your example of the input, a line will contain only at most only one digit. That doesn't make much sense and I think that wasn't your intention.
Here is one of the ways how to resolve these issues:
int sum = 0;
try(Stream<String> lines = Files.lines(inputFile.toPath())) {
sum = getSum(lines);
} catch (IOException e) {
e.printStackTrace();
}
Note that try-with-resources is a preferred way to deal with resources that implement AutoCloseable. When execution of the try block finishes (normally or abruptly) all resources will be closed.
Logic for calculating the sum:
public static int getSum(Stream<String> lines) {
return lines.flatMap(line -> Stream.of(line.split("\\s+")))
.filter(str -> str.matches("\\d+"))
.mapToInt(Integer::parseInt)
.sum();
}
That basically the answer to the question:
Convert String array to an Int array and total it
To fix other parts of your code you have to have a clear understanding of what you are trying to achieve. There is a lot of actions packed together in this code, you need to split it into separate methods each with its own responsibility.
The code for writing to the outputFile seems to be unrelated to the process of calculating the sum. Basically, you are creating a copy of the inputFile with only one additional line: "Number of months of the loan: " + String.valueOf(loanMonths).
If you insist these actions must be done at the same time, for instance, the inputFile could be large, then it might be done like this:
try(BufferedReader reader = new BufferedReader(new FileReader(inputFile));
BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile))) {
String line;
while ((line = reader.readLine()) != null) {
writer.write(line);
writer.newLine();
if (!line.isBlank()) {
sum += Integer.parseInt(line.split("\\s+")[1]);
}
}
writer.write("Number of months of the loan: " + String.valueOf(loanMonths));
} catch (IOException e) {
e.printStackTrace();
}
Note that in this case, Java 8 streams are not needed because a line can contain only a single value and there's nothing to process with a stream.

Related

Why is my program reading one less line than there actually is? And why is my array taking in only ones?

In my high school comp sci class I have to read a text file with marks and then create an array with those marks in them (so I can manipulate them later). When I try and read the number of lines in the program it reads one less than there is, and when I output the array it consists of only "1.00" written to the amount of lines it has counted (which is incorrect).
import java.awt.*;
import java.io.*;
import hsa.Console;
public class Assignment3Q3
{
static Console c;
public static void main (String[] args) throws IOException
{
c = new Console ();
BufferedReader input = new BufferedReader (new FileReader ("marks.txt"));
String mark = input.readLine ();
int lines = 0;
while (input.readLine () != null)
lines++;
input.close ();
c.println (lines);
double[] marks = new double [lines];
int count = 0;
BufferedReader input1 = new BufferedReader (new FileReader ("marks.txt"));
while (input1.readLine () != null)
{
marks [count] = Double.parseDouble (mark);
count += 1;
if (count == lines)
{
break;
}
}
for (int x = 0 ; x < lines ; x++)
{
c.println (marks [x]);
}
}
}
In your second while loop, you are always assigning the parsed version of mark variable to the marks array elements. But you have only set mark variable once in your code, which is the first line of your file.
Anyway without reading the file twice (once to get the number of lines and then to store the actual line content), you can do this in a single read cycle by using a List instead of an array.
try (BufferedReader input = new BufferedReader (new FileReader("src/marks.txt"))) {
List<Double> marks = new ArrayList<>();
String line;
while ((line = input.readLine()) != null) {
marks.add(Double.parseDouble(line));
}
System.out.println(marks);
} catch (IOException e) {
e.printStackTrace();
}
In case you really want to get these marks to an array, you can onvert the above list into an array as follows.
Double[] marksArray = marks.toArray(new Double[marks.size()]);
Also as I have done in the above code snippet, better to use try with resources approach when you create AutoCloseable resources such as BufferedReader or FileReader. Then you don't have to close them explicitly in your code.
Why this separation in two steps at all? This is error prone. No values in the marks-array above the current line-count are accessed. So store the doubles in a dynamicly growing ArrayList<Double> instead and do the job in one step.

Java : How do I print an ascending column and next to that column the same set of integers except in descending order all in one single text file

I need some help in how to do a certain step as I can not seem to figure it out.
I was given a text file with 100 numbers in it all random, I am supposed to sort them either in ascending order, descending order, or both depending on the user input. Then which ever the user inputs the set of integers will be sorted and printed in a text file. I am having trouble printing the both file. Here is my code up until the both statement.
public static void print(ArrayList<Integer> output, String destination){
try {
PrintWriter print = new PrintWriter(destination);
for(int i = 0; i < output.size(); i++){
print.print(output.get(i) + " ");
}
print.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
BufferedReader br = null;
ArrayList<Integer> words = new ArrayList<>();
BufferedReader reader;
String numbers;
try {
reader = new BufferedReader(new FileReader("input.txt"));
while((numbers = reader.readLine()) != null)
{
words.add(Integer.parseInt(numbers));
}
System.out.println("How would you like to sort?");
System.out.println("Please enter asc(For Ascending), desc(For Decending), or both");
String answer = input.next();
Collections.sort(words);
if(answer.equals("asc")){
Collections.sort(words);
System.out.println(words);
print(words,"asc.txt");
}
else if(answer.equals("desc")){
Collections.reverse(words);
System.out.println(words);
print(words,"desc.txt");
When I type in "both" the text file that is created only has one column set of integers that is going in descending order, not both and I have no idea how to print both sets. If someone could shed some light I would really appreciate it.
else if(answer.equals("both")){
System.out.println(words);
print(words,"both.txt");
Collections.reverse(words);
System.out.println(words);
print(words,"both.txt");
You need to use FileOutputStreams#Constructor where you can pass a boolean value to tell whether to append to my file or not.
So use like this:
PrintWriter print = new PrintWriter(new FileOutputStream(destination, true));
/\
||
||
To append to the file
From JavaDocs
public FileOutputStream(File file,
boolean append)
throws FileNotFoundException
Parameters:
file - the file to be opened for writing.
append - if true, then bytes will be written to the end of the file
rather than the beginning

Java Simulate an incoming stream and organize it

I have a homework assignment that is the following:
"Write a program which will separate a stream of non-negative integers into a stream consisting of; firstly, the integers which are divisible by 3, secondly, the integers equivalent to 1 mod 3,and lastly equivalent to 2 mod 3. You program should simulate the incoming stream by generating 20 random integers between 0 and 100 and should use at most 4 stacks of integers to solve the problem."
I'm not very familiar with streams, my experiences with streams has been limited to simple reading and writing from files. So naturally when I was thinking about a solution I was thinking I could just generate a file and write 20 random integers to it. Then just read it in to simulate an incoming stream.
This is where I start to get confused, because I am supposed to separate the stream in a stream(???). I understand the math aspect of the separation: x%3=0, x%3=1, and x%3=2, but should I create a new stream here? So I would take the input stream and "separate" it into an output stream?
Then he mentions using up to four stacks and I don't see where I need to use to stacks to complete this problem, unless I should be using the stacks to hold the integers before I put them into the new stream?
Please let me know if my understanding of this problem seems logical and correct.
Edit: My current solution
import java.io.*;
import java.util.Iterator;
import java.util.Random;
import java.util.Scanner;
import java.util.Stack;
/**
* write a program which will seperate a stream of nonnegative integers into a stream consisting of, firstly , the
* integers which are divisible by 3, secondly, the integers equivalent to 1 modula three, and lastly, the integers
* equivalent to 2 modulo 3. Your program should simulate the incoming stream by generating 20 random integers between
* 0 and 100 and should use at most 4 stack of integers to solve the problem.
*/
public class StreamSeperator {
public static void main (String[] args)
{
/*
* Generate file to simulate incoming stream
*/
int arr[] = new int[20];
Random rand = new Random();
for(int i = 0; i<20;i++){
arr[i] = rand.nextInt(100);
}
try{
File inputFile = new File("stream_sim.txt");
if(!inputFile.exists()){
inputFile.createNewFile();
}
FileWriter inputWriter = new FileWriter(inputFile.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(inputWriter);
for(int j=0;j<arr.length-1;j++){
bw.write(String.valueOf(arr[j]));
bw.newLine();
}
bw.close();
System.out.println("Sim file generated");
}catch (IOException e){
e.printStackTrace();
}
/*
* Read file in and sort into stacks
*/
Stack<Integer> divisByThree = new Stack<Integer>();
Stack<Integer> remainderOne = new Stack<Integer>();
Stack<Integer> remainderTwo = new Stack<Integer>();
BufferedReader br = null;
try {
String sCurrentLine;
br = new BufferedReader(new FileReader("stream_sim.txt"));
while ((sCurrentLine = br.readLine()) != null) {
int _temp = Integer.parseInt(sCurrentLine);
//divisible by three
if(_temp%3==0){
divisByThree.push(_temp);
}
//remainder of one
else if(_temp%3==1){
remainderOne.push(_temp);
}
//remainder of two
else if(_temp%3==2){
remainderTwo.push(_temp);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null)br.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
/*
* Feed stacks into output stream
*/
try{
File outFile = new File("out.txt");
if(!outFile.exists()){
outFile.createNewFile();
}
FileWriter outWriter = new FileWriter(outFile.getAbsoluteFile());
BufferedWriter outbw = new BufferedWriter(outWriter);
Iterator itStack1 = divisByThree.iterator();
Iterator itStack2 = remainderOne.iterator();
Iterator itStack3 = remainderTwo.iterator();
//first stack
while(itStack1.hasNext()){
outbw.write(String.valueOf(divisByThree.pop()));
outbw.newLine();
}
//second stack
while(itStack2.hasNext()){
outbw.write(String.valueOf(remainderOne.pop()));
outbw.newLine();
}
//thrid stack
while(itStack3.hasNext()){
outbw.write(String.valueOf(remainderTwo.pop()));
outbw.newLine();
}
outbw.close();
System.out.println("Out file generated");
}catch (IOException e){
e.printStackTrace();
}
}
}
I'm not very familiar with streams
That's the point of the assignment - to make you more familiar.
You're on the right track. Decompose the problem into pieces: reading, organizing, and redirecting.
Create an OutputStream for each case and write the values that match your criterion to it.

How do I quadruple the integer values in a text file? [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I guess this comes down to reading and writing to the same file. I would like to be able to return the same text file as is input, but with all integer values quadrupled. Should I even be attempting this with Java, or is it better to write to a new file and overwrite the original .txt file?
In essence, I'm trying to transform This:
12
fish
55 10 yellow 3
into this:
48
fish
220 40 yellow 12
Here's what I've got so far. Currently, it doesn't modify the .txt file.
import java.io.*;
import java.util.Scanner;
public class CharacterStretcher
{
public static void main(String[] args)
{
Scanner keyboard = new Scanner( System.in );
System.out.println("Copy and paste the path of the file to fix");
// get which file you want to read and write
File file = new File(keyboard.next());
File file2 = new File("temp.txt");
BufferedReader reader;
BufferedWriter writer;
try {
// new a writer and point the writer to the file
FileInputStream fstream = new FileInputStream(file);
// Use DataInputStream to read binary NOT text.
reader = new BufferedReader(new InputStreamReader(fstream));
writer = new BufferedWriter(new FileWriter(file2, true));
String line = "";
String temp = "";
int var = 0;
int start = 0;
System.out.println("000");
while ((line = reader.readLine()) != null)
{
System.out.println("a");
if(line.contains("="))
{
System.out.println("b");
var = 0;
temp = line.substring(line.indexOf('='));
for(int x = 0; x < temp.length(); x++)
{
System.out.println(temp.charAt(x));
if(temp.charAt(x)>47 && temp.charAt(x)<58) //if 0<=char<=9
{
if(start==0)
start = x;
var*=10;
var+=temp.indexOf(x)-48; //converts back into single digit
}
else
{
if(start!=0)
{
temp = temp.substring(0, start) + var*4 + temp.substring(x);
//writer.write(line.substring(0, line.indexOf('=')) + temp);
//TODO: Currently writes a bunch of garbage to the end of the file, how to write in the middle?
//move x if var*4 has an extra digit
if((var<10 && var>2)
|| (var<100 && var>24)
|| (var<1000 && var>249)
|| (var<10000 && var>2499))
x++;
}
//start = 0;
}
System.out.println(temp + " " + start);
}
if(start==0)
writer.write(line);
else
writer.write(temp);
}
}
System.out.println("end");
// writer the content to the file
//writer.write("I write something to a file.");
// always remember to close the writer
writer.close();
//writer = null;
file2.renameTo(file); //TODO: Not sure if this works...
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Given that this is a pretty quick and simple hack of a formatted text file, I don't think you need to be too clever about it.
Your logic for deciding whether you are looking at a number is pretty complex and I'd say it's overkill.
I've written up a basic outline of what I'd do in this instance.
It's not very clever or impressive, but should get the job done I think.
I've left out the overwriting and reading the input form the console so you get to do some of the implementation yourself ;-)
import java.io.*;
public class CharacterStretcher {
public static void main(String[] args) {
//Assumes the input is at c:\data.txt
File inputFile = new File("c:\\data.txt");
//Assumes the output is at c:\temp.txt
File outputFile = new File("c:\\temp.txt");
try {
//Construct a file reader and writer
final FileInputStream fstream = new FileInputStream(inputFile);
final BufferedReader reader = new BufferedReader(new InputStreamReader(fstream));
final BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile, false));
//Read the file line by line...
String line;
while ((line = reader.readLine()) != null) {
//Create a StringBuilder to build our modified lines that will
//go into the output file
StringBuilder newLine = new StringBuilder();
//Split each line from the input file by spaces
String[] parts = line.split(" ");
//For each part of the input line, check if it's a number
for (String part : parts) {
try {
//If we can parse the part as an integer, we assume
//it's a number because it almost certainly is!
int number = Integer.parseInt(part);
//We add this to out new line, but multiply it by 4
newLine.append(String.valueOf(number * 4));
} catch (NumberFormatException nfEx) {
//If we couldn't parse it as an integer, we just add it
//to the new line - it's going to be a String.
newLine.append(part);
}
//Add a space between each part on the new line
newLine.append(" ");
}
//Write the new line to the output file remembering to chop the
//trailing space off the end, and remembering to add the line
//breaks
writer.append(newLine.toString().substring(0, newLine.toString().length() - 1) + "\r\n");
writer.flush();
}
//Close the file handles.
reader.close();
writer.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
You may want to consider one of these:
Build the new file in memory, rather than trying to write to the same file you are reading from. You could use StringBuilder for this.
Write to a new file, then overwrite the old file with the new one. This SO Question may help you there.
With both of these, you will be able to see your whole output, separate from the input file.
Additionally, with option (2), you don't have the risk of the operation failing in the middle and giving you a messed up file.
Now, you certainly can modify the file in-place. But it seems like unnecessary complexity for your case, unless you have really huge input files.
At the very least, if you try it this way first, you can narrow down on why the more complicated version is failing.
You cannot read and simultaneously write to the same file, because this would modify the text you currently read. This means, you must first write a modified new file and later rename it to the original one. You probably need to remove the original file before renameing.
For renaming, you can use File.renameTo or see one of the many SO's questions
You seem to parse integers in your code by collecting single digits and adding them up. You should consider using either a Scanner.nextInt or employ Integer.parseInt.
You can read your file line by line, split the words at white space and then parse them and check if it is either an integer or some other word.

Print data from file to array

I need to have this file print to an array, not to screen.And yes, I MUST use an array - School Project - I'm very new to java so any help is appreciated. Any ideas? thanks
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
public class HangmanProject
{
public static void main(String[] args) throws FileNotFoundException
{
String scoreKeeper; // to keep track of score
int guessesLeft; // to keep track of guesses remaining
String wordList[]; // array to store words
Scanner keyboard = new Scanner(System.in); // to read user's input
System.out.println("Welcome to Hangman Project!");
// Create a scanner to read the secret words file
Scanner wordScan = null;
try {
wordScan = new Scanner(new BufferedReader(new FileReader("words.txt")));
while (wordScan.hasNext()) {
System.out.println(wordScan.next());
}
} finally {
if (wordScan != null) {
wordScan.close();
}
}
}
}
Nick, you just gave us the final piece of the puzzle. If you know the number of lines you will be reading, you can simply define an array of that length before you read the file
Something like...
String[] wordArray = new String[10];
int index = 0;
String word = null; // word to be read from file...
// Use buffered reader to read each line...
wordArray[index] = word;
index++;
Now that example's not going to mean much to be honest, so I did these two examples
The first one uses the concept suggested by Alex, which allows you to read an unknown number of lines from the file.
The only trip up is if the lines are separated by more the one line feed (ie there is a extra line between words)
public static void readUnknownWords() {
// Reference to the words file
File words = new File("Words.txt");
// Use a StringBuilder to buffer the content as it's read from the file
StringBuilder sb = new StringBuilder(128);
BufferedReader reader = null;
try {
// Create the reader. A File reader would be just as fine in this
// example, but hay ;)
reader = new BufferedReader(new FileReader(words));
// The read buffer to use to read data into
char[] buffer = new char[1024];
int bytesRead = -1;
// Read the file to we get to the end
while ((bytesRead = reader.read(buffer)) != -1) {
// Append the results to the string builder
sb.append(buffer, 0, bytesRead);
}
// Split the string builder into individal words by the line break
String[] wordArray = sb.toString().split("\n");
System.out.println("Read " + wordArray.length + " words");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (Exception e) {
}
}
}
The second demonstrates how to read the words into an array of known length. This is probably closer to the what you actually want
public static void readKnownWords()
// This is just the same as the previous example, except we
// know in advance the number of lines we will be reading
File words = new File("Words.txt");
BufferedReader reader = null;
try {
// Create the word array of a known quantity
// The quantity value could be defined as a constant
// ie public static final int WORD_COUNT = 10;
String[] wordArray = new String[10];
reader = new BufferedReader(new FileReader(words));
// Instead of reading to a char buffer, we are
// going to take the easy route and read each line
// straight into a String
String text = null;
// The current array index
int index = 0;
// Read the file till we reach the end
// ps- my file had lots more words, so I put a limit
// in the loop to prevent index out of bounds exceptions
while ((text = reader.readLine()) != null && index < 10) {
wordArray[index] = text;
index++;
}
System.out.println("Read " + wordArray.length + " words");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (Exception e) {
}
}
}
If you find either of these useful, I would appropriate it you would give me a small up-vote and check Alex's answer as correct, as it's his idea that I've adapted.
Now, if you're really paranoid about which line break to use, you can find the values used by the system via the System.getProperties().getProperty("line.separator") value.
Do you need more help with the reading the file, or getting the String to a parsed array? If you can read the file into a String, simply do:
String[] words = readString.split("\n");
That will split the string at each line break, so assuming this is your text file:
Word1
Word2
Word3
words will be: {word1, word2, word3}
If the words you are reading are stored in each line of the file, you can use the hasNextLine() and nextLine() to read the text one line at a time. Using the next() will also work, since you just need to throw one word in the array, but nextLine() is usually always preferred.
As for only using an array, you have two options:
You either declare a large array, the size of whom you are sure will never be less than the total amount of words;
You go through the file twice, the first time you read the amount of elements, then you initialize the array depending on that value and then, go through it a second time while adding the string as you go by.
It is usually recommended to use a dynamic collection such as an ArrayList(). You can then use the toArray() method to turnt he list into an array.

Categories

Resources