Java Simulate an incoming stream and organize it - java

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.

Related

Convert String array to an Int array and total it

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.

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.

Reading text from file and comparing it to seriers of characters

can I get recommendation or like an advice for what should be used or be known to complete this task (in the most rudimentary way I guess). if someone would be willing to write a code that would be fantastic but vague answers on the neccesary knowledge or technique will suffice.
I would like a program where at the start you input characters either seperataed by pressing enter or a string that could be like chopped up into separate items of an array (I guess) - characters separated by a comma - and that would be then compared to a txt file that contains series of entries and only those that contain some of (meaning shorter) or all of the characters that have been provided at the start would be printed, perhaps even the print would be separated by a length of the entry (word).
Any ideas on how to do this? Also, can the results be printed somewhere else than the command line, like another txt file? Need to do this in java. Thanks.
Take a look at following example:
public class SimpleExample {
public static void main(String[] args) throws ClassNotFoundException {
Scanner inputNumbers = new Scanner(System.in);
List<Integer> listOfNumbersToStore = new ArrayList<>();
List<Integer> listOfNumbersToCheck = new ArrayList<>();
int number;
String answer;
boolean flag = true;
// do code within a loop while flag is true
do {
// print message to screen
System.out.print("Would you like to put new number to your file list (Y/N): ");
// get answer (Y/N) to continue
answer = inputNumbers.next();
// if answer is Y or y
if ("Y".equalsIgnoreCase(answer)) {
// print message
System.out.print("Put your number: ");
// get input integer and assign it to number
number = inputNumbers.nextInt();
// add that number to a list of numbers to store to file
listOfNumbersToStore.add(number);
} else if ("N".equalsIgnoreCase(answer)) {
flag = false;
}
} while (flag);
writeToFile(listOfNumbersToStore);
System.out.println("---------- Check numbers ----------");
flag = true; // set it again to true
//do code within a loop while flag is true
do {
System.out.print("Would you like to put new number to your check list (Y/N) : ");
answer = inputNumbers.next();
if ("Y".equalsIgnoreCase(answer)) {
System.out.print("Put your number: ");
number = inputNumbers.nextInt();
listOfNumbersToCheck.add(number);
} else if ("N".equalsIgnoreCase(answer)) {
flag = false;
}
} while (flag);
// get a list from a file
List<Integer> readFromFile = readFromFile();
// check if there are any common elements within compared lists
boolean areThereAnyCommonElements = !Collections.disjoint(
listOfNumbersToCheck, readFromFile);
//create a new treeset used for containing unique elements and ordering it naturally, from 0 to n
Set<Integer> set = new TreeSet<>(listOfNumbersToCheck);
set.retainAll(readFromFile);
// print these messages
System.out.println("Are there any common integers between a list from a file and checking list? " + areThereAnyCommonElements);
System.out.println("Those integers are: " + set.toString());
}
/**
* List implements Seriazable interface, therefore store it to a file
* serialized
*
* #param numberOfIntegers
*/
public static void writeToFile(List<Integer> numberOfIntegers) {
try {
// create a file output stream to write to the file with the specified name.
FileOutputStream fileOutputStream = new FileOutputStream("tekstDataOutputStream");
// writes the serialization stream header to the underlying file stream;
ObjectOutputStream dataOutputStream = new ObjectOutputStream(new BufferedOutputStream(fileOutputStream));
// write a list to object output stream
dataOutputStream.writeObject(numberOfIntegers);
//close them
dataOutputStream.close();
fileOutputStream.close();
} catch (IOException ioE) {
System.err.println("JVM reported an error! Take a look: " + ioE);
}
}
public static List<Integer> readFromFile() throws ClassNotFoundException {
//create an empty list of integers
List<Integer> result = new ArrayList<>();
try {
//opening a connection to an actual file
FileInputStream fis = new FileInputStream("tekstDataOutputStream");
//used for reading from a specified input stream
ObjectInputStream reader = new ObjectInputStream(fis);
//get that list
result = (List<Integer>) reader.readObject();
//close streams
reader.close();
fis.close();
} catch (IOException ioE) {
System.err.println("JVM reported an error! Take a look: " + ioE);
}
return result;
}
}

Issues writing doubles to files, writing nothing

I seem to be missing something when it comes to writing doubles to text files, when I check the file, just blank space is present. When I read from the file and print with System.out.println(); it just prints nothing... What's going wrong here? Do I need to do some converting?
import java.io.*;
import javax.swing.JOptionPane;
public class ReadCalcAveragePrint {
double firstNum;
double secondNum;
double average;
public void readFile() {
try {
File f = new File("numbers.txt");
BufferedReader br = new BufferedReader(new FileReader(f));
String one = br.readLine();
String two = br.readLine();
firstNum = Double.parseDouble(one);
secondNum = Double.parseDouble(two);
average = (firstNum + secondNum) / 2;
JOptionPane.showMessageDialog(null, average, "title", JOptionPane.PLAIN_MESSAGE);
} catch (Exception e) {
e.printStackTrace();
System.out.println(e);
}
}
public void writeFile() {
try {
File f = new File("result.txt");
FileOutputStream fos = new FileOutputStream(f);
DataOutputStream dos = new DataOutputStream(fos);
dos.writeDouble(average);
dos.flush();
fos.close();
System.out.println("Printed.");
} catch (Exception e) {
e.printStackTrace();
System.out.println(e);
}
}
public void readResult() {
try {
File f = new File("result.txt");
BufferedReader br = new BufferedReader(new FileReader(f));
String one = br.readLine();
System.out.println(one);
} catch (Exception e) {
e.printStackTrace();
System.out.println(e);
}
}
public static void main(String[] args) {
new ReadCalcAveragePrint().readFile();
new ReadCalcAveragePrint().writeFile();
new ReadCalcAveragePrint().readResult();
}
}
In the main you are creating 3 different objects, only the first is going to contain the numbers you read from the file.
You should just create and reuse one object:
public static void main(String[] args) {
ReadCalcAveragePrint obj = new ReadCalcAveragePrint();
obj.readFile();
obj.writeFile();
obj.readResult();
}
Also you are writing the result file using DataOutputStream which is meant to write the data in binary form. If you just want to save the result as text you should use FileWriter instead:
File f = new File("result.txt");
FileWriter fw = new FileWriter(f);
fw.write(String.valueOf(average));
fw.close();
see the javadoc of writeDouble:
Converts the double argument to a long using the doubleToLongBits method in class Double, and then writes that long value to the underlying output stream as an 8-byte quantity, high byte first.
you write 8 bytes that may not be assigned to any alphanumeric character. Then you read it a line as a String (characters up to the next 'new line' char).
In this case, the 'new line' char can be anywhere, or nowhere (depending on the result).
8 bytes in file means almost 4 chars, very likely, no one is a "visible character".
Try to read a byte[8] from the InputStream (not from a Buffered one), and then put those 8 bytes into DoubleBuffer, then you can get the double value represented by those bytes and writen to the file before.

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