Java - retrieve file, calculate, output to another file? - java

I'm new here so please excuse me if I make a mistake with the question asking process. I have researched my question for the last week and a half and haven't found what I'm looking for (although I feel like the answer is very close). I'm a student and have been working on an assignment using Eclipse for my Java class. I have written a code that takes information from one file, uses it in a calculation and now I need to output it into another file. This is where I am having difficulty. This is my code so far:
import java.util.Scanner;
import java.nio.file.Paths;
import java.io.IOException;
import java.util.NoSuchElementException;
import java.util.ArrayList;
public class Program6 {
private Scanner input;
private ArrayList<Double> payRoll = new ArrayList<>();
public static void main(String[] args) {
Program6 myObject = new Program6();
myObject.openFile();
myObject.readFile();
myObject.calculateRecords();
myObject.closeFile();
}
public void openFile() {
try {
input = new Scanner(Paths.get("Program6.txt"));
} catch (IOException ioException) {
System.err.println("Error opening file. Terminating.");
System.exit(1);
}
}
public void readFile() {
try {
while (input.hasNext()) {
payRoll.add(input.nextDouble());
}
} catch (NoSuchElementException elementException) {
System.err.println("File improperly formed. Terminating.");
} catch (IllegalStateException stateException) {
System.err.println("Error reading from file. Terminating.");
}
}
public void calculateRecords() {
System.out.printf("%10s%25s%15s%19s", "Before Payroll",
"Raise Percent",
"Raise Amount",
"After Payroll\n");
double raisePercent;
double raiseAmount;
double totalBeforePayroll = 0;
double totalAfterPayroll = 0;
for (int i = 0; i < payRoll.size(); i++) {
if (payRoll.get(i) > 70000) {
raisePercent = 4;
} else if (payRoll.get(i) > 50000) {
raisePercent = 7;
} else {
raisePercent = 5.5;
}
raiseAmount = payRoll.get(i) * raisePercent / 100;
System.out.printf("%12.2f%21.1f%18.2f%17.2f%n",
payRoll.get(i), raisePercent, raiseAmount, payRoll.get(i) + raiseAmount);
totalBeforePayroll += payRoll.get(i);
totalAfterPayroll += payRoll.get(i) + raiseAmount;
}
System.out.printf("%nTotal amount of raises: $%,.2f%n",
totalAfterPayroll - totalBeforePayroll);
System.out.printf("Average raise percent : %.0f%%",
(totalAfterPayroll - totalBeforePayroll) * 100.0 / totalBeforePayroll);
System.out.printf("%nAverage raise amount : $%,.2f%n",
(totalAfterPayroll - totalBeforePayroll) / payRoll.size());
}
public void closeFile() {
if (input != null)
input.close();
}
}

Assuming you want to output just the payroll amount after adding the raise amount.
You can write a void method writeFile() in which you loop through your list and append every entry to an empty file.
For this I'm going to be using the BufferedWriter class, but you are free to chose whatever class you like. I'm going to proceed with the BufferedWriter example though.
So what we need to do in our writeFile method is setting up the bufferedwriter. This is done like this:
BufferedWriter b = new BufferedWriter(new FileWriter("path here" + System.getProperty("file.separator") + "filename.txt"));
Replacing "path here" by wherever you want to save your file. One example would be to replace it by System.getProperty("user.dir") which is the users working directory.
System.getProperty("file.seperator") would be a \ in Windows. But using System.getProperty("file.separator") will make it work on different systems as well.
So:
BufferedWriter bw = new BufferedWriter(new FileWriter(System.getProperty("user.dir") + System.getProperty("file.separator") + "filename.txt"));
Now you can loop through your list and append every entry to the writer:
for (int i = 0; i < payRoll.size(); i++){
bw.append(payRoll.get(i));
}
After that you can and should "close" the bufferedwriter using:
bw.close();
The method would look something like this:
BufferedWriter b = new BufferedWriter(new FileWriter("path here" + System.getProperty("file.separator") + "filename.txt"));
for (int i = 0; i < payRoll.size(); i++){
bw.append(payRoll.get(i));
}
bw.close();

Related

How to use correctly ZipfDistribution from Apache commons math library in Java?

I want to create a source of data (in Java) based on words (from a dictionary) that follow a Zipf distribution. So I come to ZipfDistribution and NormalDistribution of the Apache commons library. Unfortunately, information about how to use these classes are rarely. I tried to do some tests but I am not sure if I am using it in the right manner. I am following only what is written in the documentation of each constructor. But the results don't seem to be "well-distributed".
import org.apache.commons.math3.distribution.NormalDistribution;
import org.apache.commons.math3.distribution.ZipfDistribution;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
public class ZipfDistributionDataSource extends RichSourceFunction<String> {
private static final String DISTINCT_WORDS_URL = "https://raw.githubusercontent.com/dwyl/english-words/master/words_alpha.txt";
public static void main(String[] args) throws Exception {
ZipfDistributionDataSource zipfDistributionDataSource = new ZipfDistributionDataSource();
StringBuffer stringBuffer = new StringBuffer(zipfDistributionDataSource.readDataFromResource());
String[] words = stringBuffer.toString().split("\n");
System.out.println("size: " + words.length);
System.out.println("Normal Distribution");
NormalDistribution normalDistribution = new NormalDistribution(words.length / 2, 1);
for (int i = 0; i < 10; i++) {
int sample = (int) normalDistribution.sample();
System.out.print("sample[" + sample + "]: ");
System.out.println(words[sample]);
}
System.out.println();
System.out.println("Zipf Distribution");
ZipfDistribution zipfDistribution = new ZipfDistribution(words.length - 1, 1);
for (int i = 0; i < 10; i++) {
int sample = zipfDistribution.sample();
System.out.print("sample[" + sample + "]: ");
System.out.println(words[sample]);
}
}
private String readDataFromResource() throws Exception {
URL url = new URL(DISTINCT_WORDS_URL);
InputStream in = url.openStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in));
StringBuilder builder = new StringBuilder();
String line;
try {
while ((line = bufferedReader.readLine()) != null) {
builder.append(line + "\n");
}
bufferedReader.close();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return builder.toString();
}
}
output
size: 370103
Normal Distribution
sample[185049]: metathesize
sample[185052]: metathetically
sample[185051]: metathetical
sample[185050]: metathetic
sample[185049]: metathesize
sample[185050]: metathetic
sample[185052]: metathetically
sample[185050]: metathetic
sample[185052]: metathetically
sample[185050]: metathetic
Zipf Distribution
sample[11891]: anaphasic
sample[314]: abegge
sample[92]: abandoner
sample[3]: aah
sample[36131]: blepharosynechia
sample[218]: abbozzo
sample[8]: aalii
sample[5382]: affing
sample[6394]: agoraphobia
sample[4360]: adossed
You are using it just fine from a code perspective :) The problem is in assuming the source material is ordered by Zipf when it is clearly alphabetical. The whole point of using ZipfDistribution is that words[0] must be the most common word (hint: it's 'the') and roughly twice the freq of words[1]) etc.
https://en.wikipedia.org/wiki/Word_lists_by_frequency
https://en.wikipedia.org/wiki/Most_common_words_in_English

Merging sorted Files using multithreading

Multithreading is new to me so sorry for mistakes.
I have written the below program which merges files with mulithreading but I am not able to figure out how to manage the last file and after one iteration how to merge the newly created files.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
public class MergerSorter extends Thread {
int fileNumber = 1;
public static void main(String[] args) {
startMergingfiles(9);
}
public MergerSorter(int fileNum) {
fileNumber = fileNum;
}
public static void startMergingfiles(int numberOfFiles) {
int objectcounter = 0;
while (numberOfFiles != 1) {
try {
ArrayList<MergerSorter> objectList = new ArrayList<MergerSorter>();
for (int j = 1; j <= numberOfFiles; j = j + 2) {
if (numberOfFiles == j) {// Last Single remaining File
} else {
objectList.add(new MergerSorter(j));
objectList.get(objectcounter).start();
objectList.get(objectcounter).join();
objectcounter++;
}
}
objectcounter = 0;
numberOfFiles = numberOfFiles / 2;
} catch (Exception e) {
System.out.println(e);
}
}
}
public void run() {
try {
FileReader fileReader1 = new FileReader("src/externalsort/" + Integer.toString(fileNumber));
FileReader fileReader2 = new FileReader("src/externalsort/" + Integer.toString(fileNumber + 1));
BufferedReader bufferedReader1 = new BufferedReader(fileReader1);
BufferedReader bufferedReader2 = new BufferedReader(fileReader2);
String line1 = bufferedReader1.readLine();
String line2 = bufferedReader2.readLine();
FileWriter tmpFile = new FileWriter("src/externalsort/" + Integer.toString(fileNumber) + "op.txt", false);
int whichFileToRead = 0;
boolean file_1_reader = true;
boolean file_2_reader = true;
while (file_1_reader || file_2_reader) {
if (file_1_reader == false) {
tmpFile.write(line2 + "\r\n");
whichFileToRead = 2;
} else if (file_2_reader == false) {
tmpFile.write(line1 + "\r\n");
whichFileToRead = 1;
} else {
String value1 = line1.substring(0, 10);
String value2 = line2.substring(0, 10);
int ans = value1.compareTo(value2);
if (ans < 0) {
tmpFile.write(line1 + "\r\n");
whichFileToRead = 1;
} else if (ans > 0) {
tmpFile.write(line2 + "\r\n");
whichFileToRead = 2;
} else if (ans == 0) {
tmpFile.write(line1 + "\r\n");
whichFileToRead = 1;
}
}
if (whichFileToRead == 1) {
line1 = bufferedReader1.readLine();
if (line1 == null)
file_1_reader = false;
} else {
line2 = bufferedReader2.readLine();
if (line2 == null)
file_2_reader = false;
}
}
tmpFile.close();
bufferedReader1.close();
bufferedReader2.close();
fileReader1.close();
fileReader2.close();
} catch (Exception e) {
System.out.println(e);
}
}
}
I am trying to merge sorted files with multithreading. Say I have 50 files and I want to merge all these individual files into one final sorted file but I want to speed up and utilize every core by multi threading but I am not able to do it. And the files are big so they can't be placed in heap/RAM so I have to read every file and keep writing.
You can do this with merge sort, but instead of lots of little sorted lists, you'll need to use lots of little sorted files. Once you have broken all of the files down into small sorted files, you can start merging them together again until you end up with a single sorted file.
Unfortunately, you likely won't be able to achieve high CPU utilisation as much of the time will be spend waiting for disk I/O to complete.
Edit: just read your response to a comment and it sounds like you are asking for help on the last step of the merge sort. The graphics in the wiki link above will also help you understand. So, assuming all of your files are sorted, here we go:
Read 1 item from each file
Figure out which lowest/smallest/whatever and write that line to the result file
Read a new item from the file which just provided the last item
Repeat steps 2 and 3 until all files have been completely read.

Counting words from a file

for this program I have to write I'm given an input file of strings that has a line (or lines) of text, for example: "The high HIGH cat High jumped (WOW 6SOFT)". From this line I have to scan the file, count the number of times a word appears (regardless of capitalization), and then output it to a formatted file. If a digit comes before a word, the word should not be counted. The format has to be started with the count right justified in three spaces, followed by another space, followed by the word counted in lower case.
package InClass;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Scanner;
public class CountWords {
public static void main(String[] args) {
try {
File inputFile = new File("input.txt");
Scanner scanner = new Scanner(inputFile);
File outputFile = new File("output.txt");
PrintWriter writer = new PrintWriter(outputFile);
boolean next = scanner.hasNext();
ArrayList<String> inputWords = new ArrayList<String>();
ArrayList<String> outputWords = new ArrayList<String>();
while (next) { // Adds all the strings to an array list
inputWords.add(scanner.next());
for (int i = 0; i < inputWords.size(); i++) {
inputWords.get(i).toLowerCase();
}
}
while (next) {
for (int i = 0; i < inputWords.size(); i++) {
String word = inputWords.get(i);
int count = 1;
if (!Character.isDigit(word.charAt(0))) {
outputWords.add(inputWords.get(i));
if (outputWords.contains(word)) {
count++;
}
} else {
inputWords.remove((i));
}
for (int j = 0; i < outputWords.size(); j++) {
word = outputWords.get(i);
writer.printf("%3s" + "%1s\n", count, word);
}
}
}
scanner.close();
writer.close();
} catch (FileNotFoundException e) {
}
}
}
My tester file is giving me an error saying there is a NoSuchElementException for only one of the tester classes, which is testing two words. Here is the test class giving the error"
#Test
public void testTwoWords() {
try {
File inputFile = new File(INPUT);
File outputFile = new File(OUTPUT);
// If assert fails it is (usually) because the file was (wrongly)
// left open in an earlier run.
// Using a file manager application (e.g. explorer), go to project
// directory and delete it.
// Make sure that your program closes these files before ending.
if (inputFile.exists()) {
assertTrue("Your program left \"" + INPUT
+ "\" open in a previous test.", inputFile.delete());
}
if (outputFile.exists()) {
assertTrue("Your program left \"" + OUTPUT
+ "\" open in a previous test.", outputFile.delete());
}
// create INPUT file
PrintWriter input = new PrintWriter(inputFile);
input.println("King");
input.println("");
input.println("");
input.println("");
input.println("hill");
input.close();
// invoke program
CountWords.main(null);
// verify OUTPUT file exists and is empty
assertTrue("Output file doesn't exist", outputFile.exists());
Scanner output = new Scanner(outputFile);
String actual = output.nextLine();
assertEquals("Incorrect result", " 1 king", actual);
actual = output.nextLine();
assertEquals("Incorrect result", " 1 hill", actual);
assertFalse("There should be no more data", output.hasNext());
output.close();
// delete I/O files
assertTrue("Input file could not be deleted", inputFile.delete());
assertTrue("Output file could not be deleted", outputFile.delete());
} catch (IOException e) {
fail("No exception should be thrown");
}
}
Finally, my other testers are saying "Your program left "input.txt" open in a previous test". Any idea why? Thank you tons in advance!
The for loop for your outputWords is using the i loop counter instead of j.
for (int j = 0; i < outputWords.size(); j++) {
word = outputWords.get(i);
writer.printf("%3s" + "%1s\n", count, word);
}
Change that to
for (int j = 0; i < outputWords.size(); j++) {
word = outputWords.get(j);//NEED TO USE J HERE
writer.printf("%3s" + "%1s\n", count, word);
}
The reason the other tests are failing is because you are apparently supposed to delete the output files after each test is run.

Trying to implement a score system while using if/else. [JAVA]

I'm a beginner at java and I'm trying to have a score system that uses my if/else statements to either increment or decrement according to right or wrong answers. The program should increment if the user matches the text that is found in the text file and decrement if incorrect. Right now, the program will display "-1" if incorrect and "1" if correct, regardless of how many times it goes through the loop. It should change the value of result but it keeps resetting to "0". I have tried already but I believe I had an issue with scope. If anyone could help I'd be very grateful.
package typetrain;
import java.util.*;
import java.io.*;
import javax.swing.*;
/**
*
* #author Haf
*/
public class Game1 {
public void Game () {
JOptionPane.showMessageDialog(null, "Please answer in the correct line of text. \n" +
"each line of text will grant you one point. "
+ "\nIncorrect answers will lead to a point being subtracted");
String fileName = "test.txt";
String line;
ArrayList aList = new ArrayList();
try {
BufferedReader input = new BufferedReader (new FileReader(fileName));
if (!input.ready()) {
throw new IOException();
}
while ((line = input.readLine()) !=null) {
aList.add(line);
}
input.close();
} catch (IOException e) {
System.out.println(e);
}
int sz = aList.size();
for (int i = 0; i< sz; i++) {
int result = 0;
String correctAnswer = aList.get(i).toString();
String userAnswer = JOptionPane.showInputDialog(null, "Copy this line of text! \n" + aList.get(i).toString());
if (correctAnswer.equals(userAnswer)) {
JOptionPane.showMessageDialog(null, "Correct!");
result++;
}
else if (!correctAnswer.equals(userAnswer)) {
JOptionPane.showMessageDialog(null, "Incorrect!");
result--;
}
JOptionPane.showMessageDialog(null, result);
}
}
}
You just need to move your int result = 0; to the line before your for loop. Otherwise, it will get reset to 0 each time.

How do I create a method to create serial numbers based on an input parameter?

I am creating a delimited text string from a data source that contain non-delimited document metadata. All of the data is sorted by index, then subindex, and one of the first things I want to do is create a serial number for each record. The first characters of each line dictate if this is an index or subindex record, and I use these in increment the data as noted in the logic below, which works as expected.
import java.util.*;
import java.io.*;
import java.nio.file.*;
import java.util.regex.*;
import java.lang.StringBuilder;
//
public class mdata
{
public static void main(String[] args)
{
double indexNo = 0;
double subIndexNo = 0;
double recNo = 0 ;
try
{
FileInputStream inputStream = new FileInputStream("whidata0.htm");
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
String inputLine = null;
while((inputLine=br.readLine())!=null)
{
String recordNumber = "";
if (inputLine.trim().startsWith("aIE(2")) {
indexNo = indexNo + 1;
subIndexNo = .00;
} else
if (inputLine.trim().startsWith("aIE(3")) {
subIndexNo = subIndexNo + .01;
}
recNo = indexNo + subIndexNo;
System.out.println(recNo);
}
}
//
catch (Exception e)
{
System.err.println("Error: " + e.getMessage());
}
}
}
I have other applications that require me to serialize data, and want to create a standalone method that assigns the serial number. I'm having some issues which may be scope-related, and I need an few extra set of eyes to help me understand what's happening.
Here's where I am so far with creating a serialization method:
import java.util.*;
import java.io.*;
import java.nio.file.*;
import java.util.regex.*;
import java.lang.StringBuilder;
//
public class mdata2
{
public static void main(String[] args)
{
try
{
FileInputStream inputStream = new FileInputStream("whidata0.htm");
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
String inputLine = null;
while((inputLine=br.readLine())!=null)
{
recNo = generateSerial(inputLine.trim());
System.out.println(recNo);
}
}
//
catch (Exception e)
{
System.err.println("Error: " + e.getMessage());
}
}
//
public static double generateSerial(String inputLine)
{
double indexNo = 0; // where do
double subIndexNo = 0; // these have
double recNo = 0 ; // to go?
String recordNumber = "";
if (inputLine.trim().startsWith("aIE(2")) {
indexNo = indexNo + 1;
subIndexNo = .00;
} else
if (inputLine.trim().startsWith("aIE(3")) {
subIndexNo = subIndexNo + .01;
}
recNo = indexNo + subIndexNo;
System.out.println(recNo);
return recNo;
}
}
In the first block of code, my recNo prints as a sequence 1.00,2.00,2.01,2.02,2.03,3.00 etc. In the second, that same sequence returns as 1.00,1.00,1.01,1.01,1.01,1.00 etc. Looking at it, that makes sense; the first thing I'm doing in the method is resetting the variables to 0. Initializing the variables in main gives me scope issues--generateSerial doesn't recognize the variable.
I played around with using combinations of this.[variableName] but that didn't seem to ave any effect. What's the best way to handle this?

Categories