This question already has answers here:
Can you recommend a Java library for reading (and possibly writing) CSV files? [closed]
(8 answers)
Closed 6 years ago.
So I have received quite a few tips and acquired some resources for learning Java since joining this community. I have now reached week 6 in my class and am working through my third project. I feel like I'm learning a lot but I also have a long road ahead if I want to master Java.
My question this time is how do I get my code to save more than one output to file?
Part of my current project is to do the following:
"When the window is closed, the efficiency values should be computed with >values of n from 0 to 10 and written to a file. Each line of the file > >should contain the value of n, the efficiency of the iterative method for >that value of n and the efficiency of the recursive method. The values >should be separated by commas so the file can be opened with Excel."
I have managed to get the program to write a single entry into the output file. However,I either made an error in the code or missing something critical. Can someone point me to the correct solution? I think I may have to create an array, store the outputs there, then output the array to csv. I have looked at roseindia and viralpatel but those didn't reveal what I was hoping.
Sequence (part I'm screwing up)
package cmisproject3;
public class Sequence {
private static int efficiency = 0;
// method to compute iterative
public static int computeIterative(int n) {
int result = 0;
efficiency = 0;
if (n == 0) {
result = 0;
} else if (n == 1) {
result = 1;
} else {
int secondPrevious = 0;
int previous = 1;
for (int i = 2; i <= n; i++) {
efficiency++;
result = 2 * previous + secondPrevious;
secondPrevious = previous;
previous = result;
}
}
return result;
}
// method to comopute recursive
public static int computeRecursive(int n) {
efficiency = 0;
return computeRecursiveHelper(n);
}
private static int computeRecursiveHelper(int n) {
if (n == 0) {
return 0;
} else if (n == 1) {
efficiency++;
return 1;
} else {
efficiency++;
return 2 * computeIterative(n - 1) + computeIterative(n - 2);
}
}
public static int getEfficiency() {
return efficiency;
}
}
GUI (nailed it?)
package cmisproject3;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import javax.swing.*;
public class CMISProject3 extends JFrame implements ActionListener {
private final int TWICE = 2;
private JLabel jLabel1 = new JLabel(), jLabel2 = new JLabel(), jLabel3 = new JLabel(), jLabel4 = new JLabel(), jLabel5 = new JLabel(), jLabel6 = new JLabel();
private ButtonGroup radioButtons = new ButtonGroup();
private JRadioButton iterativeBtn = new JRadioButton(), recursiveBtn = new JRadioButton();
private JTextField enterN = new JTextField(16), textResult = new JTextField(16), textEfficiency = new JTextField(16);
private JButton computeBtn = new JButton();
private int efficiency;
private Sequence sequence;
private static FileWriter fileWriter;
private File file = new File("output.txt");
// Beginning of the constructor for the GUI
public CMISProject3() throws IOException {
sequence = new Sequence();
setSize(300, 200); // define size of GUI
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new GridLayout(6, 2));
getContentPane().add(jLabel4);
radioButtons.add(iterativeBtn);
iterativeBtn.setSelected(true); // sets Iterative as default GUI selection
iterativeBtn.setText("Iterative");
getContentPane().add(iterativeBtn);
getContentPane().add(jLabel5);
radioButtons.add(recursiveBtn);
recursiveBtn.setText("Recursive");
getContentPane().add(recursiveBtn);
jLabel1.setText("Enter n: ");
getContentPane().add(jLabel1);
getContentPane().add(enterN);
getContentPane().add(jLabel6);
computeBtn.setText("Compute");
computeBtn.addActionListener(this);
getContentPane().add(computeBtn);
jLabel2.setText("Result: ");
getContentPane().add(jLabel2);
getContentPane().add(textResult);
textResult.setEditable(false);
jLabel3.setText("Efficiency: ");
getContentPane().add(jLabel3);
getContentPane().add(textEfficiency);
textEfficiency.setEditable(false);
pack();
}
public void actionPerformed(ActionEvent event) {
int result;
efficiency = 0;
try {
fileWriter = new FileWriter(file);
} catch (IOException e1) {
e1.printStackTrace();
}
if (iterativeBtn.isSelected()) {
result = sequence.computeIterative(Integer.parseInt(enterN.getText()));
} else {
result = sequence.computeRecursive(Integer.parseInt(enterN.getText()));
}
try {
System.out.println(result);
fileWriter.write(result + ", " + sequence.getEfficiency());
} catch (IOException e) {
e.printStackTrace();
}
textResult.setText(Integer.toString(result));
textEfficiency.setText(Integer.toString(sequence.getEfficiency()));
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
CMISProject3 CMISProject3 = new CMISProject3();
CMISProject3.setVisible(true);
}
}
For those interested, here are the parameters I'm working within.
Instructions
You are reopening the file each time an action was performed without telling FileWriter to append instead of overwrite.
See:
https://docs.oracle.com/javase/7/docs/api/java/io/FileWriter.html#FileWriter(java.io.File,%20boolean)
I think you have a good start on your project. However, I see other problems apart from your question.
First I'll address your question then move on to other items. I assume when you say:
write a single entry into the output file
that you're saying you are able to write a single line to the file. So that would mean your question is: How can I write multiple lines to a file?
In that case you have at least two options. One is to setup your FileWriter to append rather than the default behavior of overwriting the existing file content.
Another option would be to avoid closing the FileWriter until you're finished writing. You could, for example, do this by moving the construction of your fileWriter to the constructor of your GUI and moving the call to the close method into an event handler that fires when the GUI closes.
Whatever you chose to do, you need to remember to write the newline character at the end of each line or else your file will be one very long line. So, modifying what you have now it would look like this:
fileWriter.write(result + ", " + sequence.getEfficiency()+"\n");
Other Issues:
Your Sequence.computeRecursiveHelper method is not recursive. A recursive method calls itself, yours does not do this.
I don't think you're following the instructions correctly. Perhaps you're just not finished yet and you intend to modify your code. If that is the case you can ignore what I'm about to point out. The instructions state:
When the window is closed, the efficiency values should be computed with values of n from 0 to 10 and written to a file.
You are currently writing to the file every time the user clicks the "Compute" button rather than doing the above. Also, you're not writing the correct data - you're writing the value you got based on the user's input not values obtained using n from 0 to 10.
Related
I am creating a program that takes an input file, parses that information and builds a GUI calculator from that information. Currently the program works well except for when I implement an ActionListener on buttons that should set a text field to the value of the buttons getText() method.
I have tried a few different loop constructions using for and while, but all of them I have implemented have not found the where i or a counter is equal to the parsed int from numPad.getText() or returned 0 for all of the buttons.
The problem I am having while testing is that the variable i never matches numPoint. Logically my approach is to decrement i so that the loop will continue to look for matches, but never does this. The test output statements infinite loop "-1" for i and "7" for numPoint. As a note, the numPad array is not in order but instead the elements are as follows {7, 8, 9, 4, 5, 6, 1, 2, 3, 0}.
I realize that this loop may not be logically correct, but I am having a hard time finding a solution that works. I want to avoid hard coding if statements (such as i == Integer(parseInt.numPad[0].getText()) which would work.
This is the loop that creates the new buttons and adds them to an Array, sets the text based on a list created from the values of the input file and adds an ActionListener.
for (int i = 0; i < run.buttons.size(); i++) {
numPad[i] = new JButton();
numPad[i].setText(run.buttons.get(i));
numPad[i].addActionListener(new ButtonActionListener());
panel1.add(numPad[i]);
}
This is the most recent attempt at creating a loop that should make the assignment.
public static class ButtonActionListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
int i;
int numPoint;
for (i = 0; i < numPad.length; i++) {
numPoint = Integer.parseInt(numPad[i].getText());
if (i == numPoint) {
//Match, assign
System.out.println("works");
break;
} else {
//Decrement and continue
i--;
System.out.println("test statement" + i + " " + numPoint);
continue;
}
}
}
}
There are several ways you might do this, but let's start with the basics
for (int i = 0; i < run.buttons.size(); i++) {
numPad[i] = new JButton();
numPad[i].setText(run.buttons.get(i));
// You don't "have" to do this, as the action command defaults
// to the text of the button, but this is away to provide some
// kind of identifier to the action which might be
// different from the text
numPad[i].setActionCommand(run.buttons.get(i))
numPad[i].addActionListener(new ButtonActionListener());
panel1.add(numPad[i]);
}
Then in your ActionListener...
public static class ButtonActionListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
int numPoint = Integer.parseInt(command);
// Perform what ever action you need
}
So, I've searched around stackoverflow for a bit, but I can't seem to find an answer to this issue.
My current homework for my CS class involves reading from a file of 5000 random numbers and doing various things with the data, like putting it into an array, seeing how many times a number occurs, and finding what the longest increasing sequence is. I've got all that done just fine.
In addition to this, I am (for myself) adding in a method that will allow me to overwrite the file and create 5000 new random numbers to make sure my code works with multiple different test cases.
The method works for the most part, however after I call it it doesn't seem to "activate" until after the rest of the program finishes. If I run it and tell it to change the numbers, I have to run it again to actually see the changed values in the program. Is there a way to fix this?
Current output showing the delay between changing the data:
Not trying to change the data here- control case.
elkshadow5$ ./CompileAndRun.sh
Create a new set of numbers? Y for yes. n
What number are you looking for? 66
66 was found 1 times.
The longest sequence is [606, 3170, 4469, 4801, 5400, 8014]
It is 6 numbers long.
The numbers should change here but they don't.
elkshadow5$ ./CompileAndRun.sh
Create a new set of numbers? Y for yes. y
What number are you looking for? 66
66 was found 1 times.
The longest sequence is [606, 3170, 4469, 4801, 5400, 8014]
It is 6 numbers long.
Now the data shows that it's changed, the run after the data should have been changed.
elkshadow5$ ./CompileAndRun.sh
Create a new set of numbers? Y for yes. n
What number are you looking for? 1
1 was found 3 times.
The longest sequence is [1155, 1501, 4121, 5383, 6000]
It is 5 numbers long.
My code:
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;
public class jeftsdHW2 {
static Scanner input = new Scanner(System.in);
public static void main(String args[]) throws Exception {
jeftsdHW2 random = new jeftsdHW2();
int[] data;
data = new int[5000];
random.readDataFromFile(data);
random.overwriteRandNums();
}
public int countingOccurrences(int find, int[] array) {
int count = 0;
for (int i : array) {
if (i == find) {
count++;
}
}
return count;
}
public int[] longestSequence(int[] array) {
int[] sequence;
return sequence;
}
public void overwriteRandNums() throws Exception {
System.out.print("Create a new set of numbers? Y for yes.\t");
String answer = input.next();
char yesOrNo = answer.charAt(0);
if (yesOrNo == 'Y' || yesOrNo == 'y') {
writeDataToFile();
}
}
public void readDataFromFile(int[] data) throws Exception {
try {
java.io.File infile = new java.io.File("5000RandomNumbers.txt");
Scanner readFile = new Scanner(infile);
for (int i = 0; i < data.length; i++) {
data[i] = readFile.nextInt();
}
readFile.close();
} catch (FileNotFoundException e) {
System.out.println("Please make sure the file \"5000RandomNumbers.txt\" is in the correct directory before trying to run this.");
System.out.println("Thank you.");
System.exit(1);
}
}
public void writeDataToFile() throws Exception {
int j;
StringBuilder theNumbers = new StringBuilder();
try {
PrintWriter writer = new PrintWriter("5000RandomNumbers.txt", "UTF-8");
for (int i = 0; i < 5000; i++) {
if (i > 1 && i % 10 == 0) {
theNumbers.append("\n");
}
j = (int) (9999 * Math.random());
if (j < 1000) {
theNumbers.append(j + "\t\t");
} else {
theNumbers.append(j + "\t");
}
}
writer.print(theNumbers);
writer.flush();
writer.close();
} catch (IOException e) {
System.out.println("error");
}
}
}
It is possible that the file has not been physically written to the disk, using flush is not enough for this, from the java documentation here:
If the intended destination of this stream is an abstraction provided by the underlying operating system, for example a file, then flushing the stream guarantees only that bytes previously written to the stream are passed to the operating system for writing; it does not guarantee that they are actually written to a physical device such as a disk drive.
Because of the HDDs read and write speed, it is advisable to depend as little as possible on HDD access.
Perhaps storing the random number strings to a list when re-running and using that would be a solution. You could even write the list to disk, but this way the implementation does not depend on the time the file is being written.
EDIT
After the OP posted more of its code it became apparent that my original answer is not relatede to the problem. Nonetheless it is sound.
The code OP posted is not enough to see when is he reading the file after writing. It seems he is writing to the file after reading, which of course is what is percieved as an error. Reading after writing should produce a program that does what you want.
Id est, this:
random.readDataFromFile(data);
random.overwriteRandNums();
Will be reflected until the next execution. This:
random.overwriteRandNums();
random.readDataFromFile(data);
Will use the updated file in the current execution.
I wasn't too sure what to title this question, apologies in advance. I currently have a value of say 50 stored in the BidderArray. I want to be able to increase that 50 by any given number entered into a text field.
So say I want to add 10 to the existing 50, it will return 60. Currently when I add the 10 the 50 is replaced by 10 instead of adding the two together. I understand why my code is doing this but haven't been able to find any tutorials or hints on what I should be doing instead.
Here is the code:
package abc;
import java.awt.*;
public class Funds extends javax.swing.JFrame {
int i = 0;
Bidder bidbal = new Bidder();
/** Creates new form Funds */
public Funds() {
initComponents();
}
private void addActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
int f = 0;
boolean validEntries = true;
try{
f = Integer.parseInt(amount.getText());
Bidder.BidderArray.get(i).setRegFee(f);
} catch (Exception error) {
validEntries = false;
amount.setBackground(Color.red);
}
if (validEntries) {
Bidder.exportBidder();
Home home = new Home();
home.setVisible(true);
this.dispose();
}
}
}
You aren't actually adding anything
Bidder.BidderArray.get(i).setRegFee(f);
is apparently just setting something to f, you have to get the current value, add to it, and then put it back. But this is just a guess as we don't have enough actual code to know what you are doing wrong.
You have to get the current fee, add the value, and then set the fee:
f = Integer.parseInt(amount.getText());
Bidder.BidderArray.get(i).setRegFee( f + Bidder.BidderArray.get(i).getRegFee() );
Or you could add a new method the Bidder class that adds to the fee:
class Bidder
{
//...
public void addToRegFee( int amount )
{
this.regFee += amount;
}
}
f = Integer.parseInt(amount.getText());
Bidder.BidderArray.get(i).addToRegFee( f );
f = Integer.parseInt(amount.getText());
Bidder.BidderArray.get(i).setRegFee(f);
Here, it seems like you're getting the user's input (f), and just set the array's element value to it. What it sounds like you want to do is to take that input (f), and the array's element existing value, combine (read: add) them, before setting the element's value to that new combined value.
In pseudo-code, this is what you're doing:
f := get user's input
setValue(f)
What you need to do:
f := get user's input
g := get current value
setValue(f + g)
You must add it to your old value:
//Add old to new (Unless you have a different method set for get like
//getRegFee (Not sure how bidder is implemented))
Bidder.BidderArray.get(i).setRegFee(Bidder.BidderArray.get(i) + f);
ok, so here is the deal. I have made a program that creates a byte array that has 150000000 different addresses. I then put that into a for loop that will assign the values a random positive number between 0-9 and it outputs that number to a file.
that all works but where i'm running into problems is where I actually try to square it. im using the class BigInteger to try to store the number im trying to square. this is my code to try to put the number into a BigInteger
for(int i = 0; i<150000000; i++)
{
square = square.add(BigInteger.valueOf(number[i]));
}
and my compiler at run time gives me the error: Exception in thread "main" java.lang.NullPointerException
at numberge.Numberge.main(Numberge.java:44)
Java Result: 1
I have also tried to make the for loop iterate a smaller amount of times and it does not help. any ideas?
the entire output that the program gives me is:
run:
done generating/now writing to file
squaring
150000000
Exception in thread "main" java.lang.NullPointerException
at numberge.Numberge.main(Numberge.java:43)
Java Result: 1
BUILD SUCCESSFUL (total time: 9 seconds)
the entire code is
import java.util.Random;
import java.io.*;
import java.math.BigInteger;
public class Numbersqu {
static byte[] number = new byte[150000000];
static Random generator = new Random(System.currentTimeMillis());
static BigInteger square = null;
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException
{
for(int i = 0; i<150000000; i++)
{
number[i] = (byte) Math.abs(generator.nextInt(9));
}
System.out.println("done generating/now writing to file");
File file = new File("number.txt");
if (!file.exists()) {
file.createNewFile();
}
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
for(int i = 0; i<150000000; i++)
{
bw.write(Integer.toString(number[i]));
}
bw.close();
System.out.println("generating number to square");
System.out.println(Integer.toString(number.length));
for(int i = 0; i<150000000; i++)
{
square = square.add(BigInteger.valueOf(number[i]));
}
System.out.println("Writing square to file");
File file2 = new File("square.txt");
if (!file2.exists())
{
file2.createNewFile();
}
FileWriter fw2 = new FileWriter(file2.getAbsoluteFile());
BufferedWriter bw2 = new BufferedWriter(fw2);
bw2.write(square.toString());
bw2.close();
}
}
this is as far as I have gotten, once I can actually store the number then I will square it.
So here it is. Your variable square is null.
static BigInteger square = null;
Initialize it to some value before using here :
for(int i = 0; i<150000000; i++)
{
square = square.add(BigInteger.valueOf(number[i]));
}
I can see two possible issues, but with this code snippet, not enough information is presented to really know either of these items are the true problem.
Perhaps square is not initalized. If so, the
square = square.add(...
will dereference a null pointer at the square.add(...) call, causing a null pointer exception.
To fix such an item
square = new Square();
should be called beforehand.
Perhaps number is not initialized.
fixing it is the same as fixing square.
Perhaps number[i] lacks a value. This happens quite often when dealing with arrays of objects.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
I'm building a table of runners and their times. I need to find the time behind the previous runner in minutes and seconds using modulo. the first 2 records are
Runner: 198
Minutes: 29
Seconds: 05
Runner: 419
Minutes: 30
Seconds: 01
Time behind runner #1?
Here is my code so far:
import java.io.*;
import java.text.*;
public class read3
{
public static void main(String[] args)throws IOException
{
DataInputStream in=new DataInputStream(new FileInputStream("c:\\java\\chapter13\\sheet2\\program2.jdat2"));
int id;
int mins;
int secs;//,num3;
double calc=0,calc2=0;
char chr;
double tcalc=0;
double t1=0,t2=0,t3=0;
NumberFormat money=NumberFormat.getCurrencyInstance();
System.out.println("Runner\tTotal \tTotal \tTime");
System.out.println("Number\tMinutes\tSeconds\tBehind\n");
try
{
while(true)
{
id=in.readInt();
in.readChar();
mins=in.readInt();
in.readChar();
secs=in.readInt();
in.readChar();
System.out.println(id+"\t "+mins+"\t "+secs+"\t"+calc);
}
}
catch(EOFException e)
{
//Hi
}
in.close();
}
}
I just need to know the equation for finding minutes/seconds (in separate variables) using modulo. Can anybody help?
int time1=nbMinutes1*60+nbSeconds1;
int time2=nbMinutes2*60+nbSeconds2;
int differenceInMinutes = (time2-time1)/60;
int differenceinSeconds = (time2-time1)%60;
EDIT:
To apply it to your code, I would do the following :
Integer duration=null;
while(true)
{
id=in.readInt();
in.readChar();
mins=in.readInt();
in.readChar();
secs=in.readInt();
in.readChar();
Integer newDuration=60*mins+secs;
//duration is null for the first one.
if(duration!=null){
System.out.println(id+"\t "+(newDuration-duration)/60+"\t "+secs+"\t"+(newDuration-duration)%60);
}
duration = newDuration;
}
Your problem here is only tangentially associated with knowing how to use modulus. You have one master function doing a mess of things: initializing variables, opening files, iterating through rows, and figuring out display parameters. This is known as procedural programming, and bad procedural programming at that: you want to leverage object oriented programming here.
//note the standards regarding class names: Capitalize Class Names!
//also, pick names that make it clear what you're doing.
public class DisplayTimes
{
DataInputStream in;
//This is not actually the correct way to do this, but it's lightweight enough for this example
List<Integer> runnerIds = new ArrayList<Integer>();
List<Integer> runnerMinutes = new ArrayList<Integer>();
List<Integer> runnerSeconds = new ArrayList<Integer>();
//note that your main method should not throw an exception. Nothing can catch it!!
//also note that this is just an entry point; it probably shouldn't do any work
public static void main(String[] args)
{
DisplayTimes display = new DisplayTimes("c:\\java\\chapter13\\sheet2\\program2.jdat2");
display.readAndDisplay();
}
//constructors are the proper way to initialize object variables
public DisplayTimes(String inputFile) {
//see how much easier this next line is to read?
this.in = new DataInputStream(new FileInputStream(fileName));
}
public void readAndDisplay() {
processData(); //offload processing somewhere else
System.out.println("Runner\tTotal \tTotal \tTime");
System.out.println("Number\tMinutes\tSeconds\tBehind\n");
for (int idx = 0; idx++; idx<runnerIds.size()) {
String output = runnerIds.get(idx)+"\t";
output = output + runnerMinutes.get(idx)+"\t";
output = output + runnerSeconds.get(idx)+"\t";
output = output + calculateDifference(idx)+"\t";
System.out.println(output);
}
}
private void processData() {
boolean moreData = true;
while (moreData) { //offload the work of the loop to another method
moreData = processRunner();
}
}
private boolean processRunner() {
try {
int id=in.readInt();
in.readChar();//how is this file formatted that you need to skip a char?
int mins=in.readInt();
in.readChar();
int secs=in.readInt();
//Here you should really sanity-check your values
//Instead we'll just store them
this.runnerIds.add(id);
this.runnerMinutes(mins);
this.runnerSeconds(secs);
return isFinished();
} catch (EOFException e) {
//Exceptions should NOT be used for program control.
//They should be used when there is bad data.
System.out.println("There was an unexpected termination of the datafile.");
}
}
private boolean isFinished() {
in.mark(1);
if (in.read == -1) {//checks cleanly if we're at the end of the file.
return false;
} else {
in.reset();//moves you back to mark
return true;
}
}
private String calculateDifference(int idx) {
if (idx == 0) { return "\t"; } //First runner is first!
int previousTimeInSeconds = (runnerMinutes.get(idx-1) * 60) + runnerSeconds.get(idx-1);
int nextTimeInSeconds = (runnerMinutes.get(idx) * 60) + runnerSeconds.get(idx);
int delta = (nextTimeInSeconds - previousTimeInSeconds);
return (delta / 60) + "min " + (delta % 60) + "sec \t";
}
}
The main thing you should take away here is that the problem you came here with - calculating the difference between runner a and b - is only a small part of the code you presented. You couldn't present a Short, Self Contained, Correct (Compilable), Example because your code was improperly tangled with other code. By writing clean code you can focus on the one function (calculateDifference()) that you actually needed help with. While I understand you may be beginning and working out of a book (based on what was presented), the most fundamental thing you can learn is how to break down a problem into the smallest pieces possible. Utilize the language to help you with this; don't fight it.