I am making a simple tutorial program in which the user inputs some data, then that data is written into a textfile, then the textfile is read and the data displayed. However, not all of the data is being written into the textfile. Please view the following:
This is my code:
package chasi.fecalMatter.ExcrementalProgram;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import javax.swing.JOptionPane;
public class RedundantExcrement {
static String inputName = JOptionPane.showInputDialog("Please input your FULL name:");
static String inputUsername = JOptionPane.showInputDialog("Please input your desired Username:");
static String inputJobTitle = JOptionPane.showInputDialog("Please input your Job title:");
static String inputSalary = JOptionPane.showInputDialog("Please input your monthly salary:");
static int convertedSalary = 0; /*Convert salary from String to int*/
static int benefitDeduction = 0;
static String empFileName = inputUsername+"INFO";
static BufferedWriter bwriter = null;
public static void main (String[] args) throws IOException {
//Catch NumberFormatException.
try {
Integer.parseInt(inputSalary);
} catch (NumberFormatException nfEx) {
JOptionPane.showMessageDialog(null, "Please ensure that " +
"your salary is entered in NUMERIC form.", "ERROR!", 2);
return;
}
//Specify instructions as regard salary -to- Benefit deduction ratio
if (convertedSalary >= 3500) {
benefitDeduction = 300;
} else {
benefitDeduction = 180;
}
try { /*Catches IOException AND NullPointerException*/
FileWriter fwriter = new FileWriter(empFileName);
bwriter = new BufferedWriter(fwriter);
bwriter.write(inputName);
bwriter.newLine();
bwriter.write(inputJobTitle);
bwriter.newLine();
bwriter.write(inputSalary);
bwriter.newLine();
bwriter.write(benefitDeduction);
bwriter.newLine();
bwriter.write("----------");
bwriter.newLine();
} catch (IOException | NullPointerException ionpEx) {
JOptionPane.showMessageDialog(null, "An ERROR has occured", "ERROR!", 2);
return;
} finally { /*CLOSE the writer*/
try{
if (bwriter != null) {
bwriter.close();
}
} catch (IOException ioEx2) {
JOptionPane.showMessageDialog(null, "ERROR!");
return;
}
}
}
}
As you can see, I use the int convertedSalary to convert the user-inputted inputSalary from a String into a number. In my method, I use
try {
Integer.parseInt(inputSalary);
} catch (NumberFormatException nfEx) {
JOptionPane.showMessageDialog(null, "Please ensure that " +
"your salary is entered in NUMERIC form.", "ERROR!", 2);
return;
}
In order to covert it. It is later (supposed) to be written by the BufferedWriter.
I also have this code:
try {
Integer.parseInt(inputSalary);
} catch (NumberFormatException nfEx) {
JOptionPane.showMessageDialog(null, "Please ensure that " +
"your salary is entered in NUMERIC form.", "ERROR!", 2);
return;
}
In order to change the value of my benefitDeduction depending on the value of the user's salary.
HOWEVER, the benefitDeduction is written into the text file, but instead, I get this:
Thanks if you can help!
Look at the API.
public void write(int c)
throws IOException
Writes a single character. The character to be written is contained in
the 16 low-order bits of the given integer value; the 16 high-order
bits are ignored.
This means that the int is actually a char and will be converted according to Unicode/ASCII table.
To write the integer value use bwriter.writer(String.valueOf(benefitDeduction));
There are two major problems with your code.
First, you are not actually assigning the value from your ParseInt to your convertedSalary variable. Hence, it will always be zero.
Then again, you are not writing convertedSalary to the file, either.
Second, I think you are confusing between BufferedWriter.write(int) and PrintWriter.print(int). The BufferedWriter will print the character represented by this integer if it is between 0 and 65535 (or the whatever there is in its lower two bytes if it isn't).
So, if your integer is, for example, 65, what you will have printed is the character A, whose value is 65 in Unicode.
So maybe you should be using a PrintWriter rather than a BufferedWriter there. Or convert the numbers into strings as other answers have suggested.
As pointed out by the other answers, your problem is the call of write(int). But instead of worrying about the conversion, you can also use StringBuilder to create your text first and write it with one call of write(String). That way you don't have to worry about the type of benefitDeduction:
final String inputName = "Tom";
final String inputJobTitle = "Developer";
final String inputSalary = "1337";
final int benefitDeduction = 180;
try(final BufferedWriter bwriter = new BufferedWriter(new FileWriter("blub.txt"))) {
final StringBuilder builder = new StringBuilder(inputName);
builder.append("\n").append(inputJobTitle);
builder.append("\n").append(inputSalary);
builder.append("\n").append(benefitDeduction);
builder.append("\n----------\n");
bwriter.write(builder.toString());
} catch (IOException | NullPointerException ex) {
JOptionPane.showMessageDialog(null, "An ERROR has occured", "ERROR!", 2);
return;
}
Also note, that I used the try-with-resources statement to handle the BufferedWriter. It will handle the resource and closes it for you. No need to do that manually.
The above code write the following data into the file "blub.txt":
Tom
Developer
1337
180
----------
And as I already wrote in the comment, you're not assigning a new value to the variable convertedSalary.
Change the line:
Integer.parseInt(inputSalary);
to:
convertedSalary = Integer.parseInt(inputSalary);
to do that.
Your problem is that when you are writing your numbers, these values are being written as binary numbers not as text numbers. You can fix this by doing writer.write("" + myNumber);
Integer.parseInt(inputSalary) //returns an integer
Quoting from the JDK:
Integer.parseInt(); = "Parses the string argument as a signed decimal integer. The characters in the string must all be decimal digits, except that the first character may be an ASCII minus sign '-' ('\u002D') to indicate a negative value or an ASCII plus sign '+' ('\u002B') to indicate a positive value. The resulting integer value is returned, exactly as if the argument and the radix 10 were given as arguments to the parseInt(java.lang.String, int) method."
Your code should read:
convertedInt = Integer.parseInt(inputSalary);
Related
I am trying to get Java to read text from a file so that I can convert the text into a series of ascii values, but currently it only seems to be reading and retrieving the first line of the txt file. I know this because the output is much shorter than the text in the file.
The text in the file is below:
AD Mullin Sep 2014 https://hellopoetry.com/poem/872466/prime/
Prime
Have you ever thought deeply about Prime numbers?
We normally think of prime as something unbreachable
In base ten this is most likely true
But there are other languages that might be used to break down numbers
I'm no theorist but I have my theories
What was behind the Big Bang?
Prime
If impermeable ... then the Big Bang never happened
And any good programmer worth a lick of salt, always leaves a back door
So, I bet there are some Prime numbers out there that are permeable, otherwise ...
We wouldn't be the Children of the Big Bang
I think because each line of text has an empty line between them the program is only reading the first line then stopping when it sees there is no line after it, but in facts 2 lines down instead.
Here is the code I have written:
package poetry;
import java.io.FileNotFoundException;
import java.util.Formatter;
import java.util.Scanner;
import java.io.File;
import java.io.IOException;
import java.io.FileWriter;
public class poetry {
public static void main(String[] args) {
// TODO Auto-generated method stub
//Below try catch block reads file text and encodes it.
try {
File x = new File("/Users/jordanbendon/Desktop/poem.txt");
Scanner sc = new Scanner(x);
//Right below is where I think the issue lies!
while(sc.hasNextLine()) {
String lines = sc.nextLine();
char[] stringArray = lines.toCharArray();
String result = "";
for (int i = 0; i < lines.length(); i++) {
int ascii = lines.codePointAt(i);
if ((ascii >= 65 && ascii <= 90) || (ascii >= 97 && ascii <= 122)) {
ascii += 15;
result += Integer.toString(ascii);
} else {
result += stringArray[i];
}
}
System.out.println(result);
//Try catch block here creates a new file.
try {
File myObj = new File("/Users/jordanbendon/Desktop/EncryptedMessage.txt");
File s = myObj;
if (myObj.createNewFile()) {
System.out.println("File created: " + myObj.getName());
} else {
System.out.println("File already exists.");
break;
}
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
//Try catch block here writes the new encrypted code to the newly created file.
try {
FileWriter myWriter = new FileWriter("/Users/jordanbendon/Desktop/EncryptedMessage.txt");
myWriter.write(result);
myWriter.close();
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}}
catch(FileNotFoundException e) {
System.out.println("error");
}
}
}
I have commented in the code where I think the issue is. The first while condition checks whether there is a next line by using the hasNextLine(), I have tried using the method ReadAllLines() but it says this method is undefined for the type scanner.
How can I get the program to read and retrieve the entire text file instead of the first line?
Thanks!
To read the entire input stream:
Scanner sc = new Scanner(x).useDelimiter("\\A");
then just:
String entireInput = sc.next();
This works by setting the token delimiter to start of all input, which of course is never encountered after any byte read, so the "next" token is the entire input.
For each execution you check whether the hard coded file name was created or already exists. In case it already existed you happen to break the loop which halts the execution from progressing.
https://www.javatpoint.com/java-break
I'm using this function to find out if a String is numerical
public static boolean esNumerico(String s) {
return s.matches("[-+]?\\d*\\,?\\d+");
}
When the program starts, It asks the user to introduce a number.
If I introduce the number 88,99 It crashes:
Exception in thread "main" java.lang.NumberFormatException: For input string: "98,8"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at actividad03.Ejercicio01.pideEntero(Ejercicio01.java:32)
at actividad03.Ejercicio01.main(Ejercicio01.java:14)
The complete function code is:
static int pideEntero(){
int number1;
BufferedReader br = new BufferedReader (new InputStreamReader (System.in));
String str = null;
try{
do {
System.out.println("Introduzca un número entero:");
str = br.readLine(); //Toma una línea y la almacena como String
} while (esNumerico(str)==false);
}
catch(Exception e)
{System.out.println("Dato no válido.");
}
number1=Integer.parseInt(str);
System.out.println("Valor numérico correcto!");
//number1=Integer.parseInt(str);
return number1;
}
The aim is that the user can introduce various kind of imputs. Whenever them are not numeric or integer numeric, the program will ask again to introduce the number, but NOT CRASH as it happens now. Any idea?
It is crash in in the below line as you connot convert comma separated string literal to Integer.
number1=Integer.parseInt(str);
You may wanna do this instead.
number1 = Integer.parseInt(str.replaceAll(",", ""));
There might be an much simpler way to handle your problem. You could just try to directly parse the input as a double, and then ensure that no NumberFormatException was being thrown. Something like this:
double number1;
do {
System.out.println("Introduzca un número entero:");
try {
str = br.readLine();
number1 = Double.parseDouble(str);
// with a valid input in hand, we can now break and leave the loop
break;
} catch (NumberFormatException e) {
System.out.println("El numero es inválido, introduzca otra vez:");
} catch (Exception e) {
System.out.println("Otro problema, introduzca otra vez:");
}
} while (esNumerico(str) == false);
This is probably the way to go actually, because we let Java determine what is and is not a valid string number, rather than trying to guess ourselves using a regex.
If you must continue with your current approach, then keep reading. Your code has a problem because it is validating for a double, not an integer, yet you are attempting to parse the validated input as integer via this:
number1 = Integer.parseInt(str);
Instead, if the number passes validation, use this code to parse as a double:
NumberFormat format = NumberFormat.getInstance(new Locale("es", "ES"));
Number number = format.parse(str);
double d = number.doubleValue();
There is also a problem with your regex used for validation, because a number such as +98,8 will not parse correctly as a double (though -99,8 will). Try using this instead:
public static boolean esNumerico(String s) {
return s.matches("[-]?\\d+(,\\d+)?");
}
Explanation of the regex:
[-]? match an optional leading minus sign
\\d+ followed by one or more digits
(,\\d+)? followed by an optional comma, and then one or more digits
If you want to allow for leading plus sign, then modify the regex, but note that you will have to remove it before parsing the string into a double.
Following line is throwing error
number1=Integer.parseInt(str);
A new solution:
public static boolean esNumero (String s)
{
try
{
Integer.parseInt(s);
return true;
}
catch (NumberFormatException e){return false;}
}
Integer.parseInt() does not support commas used for separating digits in some countries. Instead DecimalFormat can be used which does allow this.
NumberFormat format = new DecimalFormat();
System.out.println(format.parse("12,34").intValue());
Output
8899
Note: DecimalFormat is dependent on Locale, it happens that in my current location then my Local is en_GB which means groupingUsed flag is on by default. You can force it by calling...
format.setGroupingUsed(true);
NumberFormat instances thow ParseException when inputs are invalid so this can be used to also validate your number
try {
System.out.println(format.parse("88,99").intValue());
} catch (ParseException e) {
// do something else
}
package addlinenumbers;
import java.util.Scanner;
import java.io.PrintWriter;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class AddLineNumbers {
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
String sentinel = new String();
int i=0;
try
{
FileOutputStream fos = new FileOutputStream
("dataInput.txt", true); //true means we will be appending to dataInput.txt
PrintWriter pw = new PrintWriter (fos);
//write data to the file
while(!(sentinel.equals("-1")))
{
System.out.println("Please enter strings to prepend to 'dataInput.txt'; -1 to EXIT: ");
pw.print(input.nextLine());
i++;
}
}
catch (FileNotFoundException fnfe)
{
System.out.println("Unable to find dataInput.txt...");
}
catch (IOException ioe)
{
ioe.printStackTrace(System.out);
}
finally
{
System.out.println("# of objects: " + i);
System.out.println("Closing file...");
input.close();
}
}
}
Currently my output will endlessly ask me to enter strings to 'dataInput.txt' (which is in the appropriate project folder) but it will not exit from the while loop with the proper sentinel for Java strings. Am I missing something here? I'm not using ==. "-1" does nothing but loop back again. It should kick out, write the inputs to the text file in prepending fashion and then close the file.
Also! As it turns out, nothing is being taken from the while-loop input and transferred to the 'dataInput.txt' file. I'm not sure why.
Any help will be greatly appreciated!
EDIT: Just as an FYI, I must use a while loop with a sentinel. Thanks again everyone who is/has/will help me on this issue.
EDIT #2: Taking into account MadProgrammer's excellent advice, I'm left with one tiny problem left in my output:
run:
Please enter strings to prepend to 'dataInput.txt'; -1 to EXIT:
David
Goliath
Please enter strings to prepend to 'dataInput.txt'; -1 to EXIT:
Delilah
Samson
Please enter strings to prepend to 'dataInput.txt'; -1 to EXIT:
-1
# of objects prepended: 2
Closing file...
BUILD SUCCESSFUL (total time: 18 seconds)
As you can see, it takes in only TWO objects they are "Goliath" and "Samson" and they are the only strings written to the text file. Technically it should have 4 objects and "David" and "Delilah" should be in the text file also, but they're not.
Any help would be greatly appreciated.
while(!(sentinel.equals("-1"))) can never be false (for the loop condition), because sentinel never changes, it's always ""
Conceptually, you need to read the user input and decide what do with it, you would then use this value to determine if you need to exit the loop
So, this is a "really quick" example (not tested) of what you could do...
Scanner input = new Scanner(System.in);
int i = 0;
try (FileOutputStream fos = new FileOutputStream("dataInput.txt", true)) {
try (PrintWriter pw = new PrintWriter(fos)) {
String userInput = "";
do {
userInput = input.nextLine();
if (!userInput.equals("-1")) {
pw.print(input.nextLine());
i++;
}
} while (!userInput.equals("-1"));
}
} catch (FileNotFoundException fnfe) {
System.out.println("Unable to find dataInput.txt...");
} catch (IOException ioe) {
ioe.printStackTrace(System.out);
} finally {
System.out.println("# of objects: " + i);
}
FYI: input.close(); isn't closing the "file", it's closing the stdin, which is never a good idea
NB: The compounding try-with blocks are overkill, you could use a single statement to wrap it all up in, but I wanted to demonstrate the concept around a similar code structure
Suppose that you have a binary file that contains numbers whose type is either int or double. You dont know the order of the numbers in the file, but their order is recorded in a string at the beginning of the file. The string is composed of the letters i for int, and d for double, in the order of the types of the subsequent numbers. The string is written using the method writeUTF.
For example the string "iddiiddd" indicated that the file contains eight values, as follows: one integer, followed by two doubles, followed by two integers, followed by three doubles.
My problem is that, if there are more letters in the string than numbers, how can I create an if statement telling the user there is an error in the file they are trying to read?
I tried using this, where "count" is the amount of numbers and "length" is the length of the string, but this did not work.
if(count!=length){
System.out.println("Error in file: Length of string and numbers are not equal");
System.exit(0);
}
the rest of my code is this:
public static void main(String[] args) {
Scanner keyboard=new Scanner(System.in);
System.out.print("Input file: ");
String fileName=keyboard.next();
int int_num_check=0;
double double_num_check=9999999999999999999999999999.999999999;
int int_num=0;
double double_num=0.0;
int count=0;
try{
FileInputStream fi=new FileInputStream(fileName);
ObjectInputStream input=new ObjectInputStream(fi);
String word=input.readUTF();
int length=word.length();
for(int i=0;i<length;i++){
if(word.charAt(i)=='i'){
int_num=input.readInt();
System.out.println(int_num);
if(int_num>int_num_check){
int_num_check=int_num;
}
}
else if(word.charAt(i)=='d'){
double_num=input.readDouble();
System.out.println(double_num);
if(double_num<double_num_check){
double_num_check=double_num;
}
}
else{
System.out.println("Error");
System.exit(0);
}
count++;
}
System.out.println("count: "+count);
System.out.println("length "+length);
if(count!=length){
System.out.println("Error in file: Length of string and numbers are not equal");
System.exit(0);
}
String checker=input.readUTF();
if(!checker.equals(null)){
System.out.println("Error");
System.exit(0);
}
input.close();
fi.close();
}
catch(FileNotFoundException e){
System.out.println("Error");
System.exit(0);
}
catch(EOFException e){
System.out.println("Largest integer: "+int_num_check);
System.out.println("Smallest double: "+double_num_check);
System.exit(0);
}
catch(IOException e){
System.out.println("Error");
System.exit(0);
}
}
}
If there are more letters than there are numbers, you probably reached the end of file (eof). Check for eof after each file read for a number and report an error if you got to eof before all the expected numbers have been read.
I think that maybe the problem is the way your file was created. Try creating it with this code:
try {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("C:/temp/file.txt"));
oos.writeUTF("idid");
oos.writeInt(8);
oos.writeDouble(4.33316);
oos.writeInt(2);
oos.flush();
oos.close();
} catch (Exception ex) {
ex.printStackTrace();
}
Then read it using your code, it should throw an EOFException.
If you have more letters that integers/doubles, your code will go to the EOFException's catch, but there you have no code regarding the EOF, but you print the largest/smallest values for some reason.
Since the EOF exception should only rise when you have more letters than numbers (since you are making your reads based on word's length), you should move inside that catch your
System.out.println("Error in file: Length of string and numbers are not equal");
System.exit(0);
I'm new to java and having problems with getting input.
This is my code which seems to get the first input as required, but then skips the next two "read" function calls?
Any suggestions?
// open up standard input
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int battMax, battMin, numNodes=0;
System.out.print("Enter minimum battery level:");
try {
battMin = br.read();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.print("Enter maximum battery level:");
try {
battMax = br.read();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.print("Enter number of nodes required:");
try {
numNodes = br.read();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
br.read() is going to read a single character. Furthermore, if you're reading from System.in it's likely to only see something when the user presses return - at which point, if you're on Windows, it will have an extra \r and \n to read (or just \n on Unix).
I suspect you'll find the values read by your second and third read() calls are \r and \n.
Furthermore, you're not actually getting the values you want to anyway - if someone enters '1' then you'll get a value of 49, as that's the Unicode value for that character.
You should use readLine() to read a line at a time (and then parse the string with Integer.parseInt(). Alternatively, you could use the Scanner class - I can't say I've ever used it myself, but it may be useful to you.
Finally, there's a lot of repetition in that code - I would suggest you refactor it by creating a utility method. For example, you might have:
public static int promptUserForInt(String prompt, int defaultValue,
BufferedReader reader)
throws IOException
{
while (true)
{
System.out.print(prompt);
try
{
String line = reader.readLine();
return Integer.parseInt(line);
}
catch (NumberFormatException e)
{
// Adjust as appropriate...
System.out.println
("Unable to parse input; please enter an integer.");
}
}
}
You can then use this very easily:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int battMax = promptUserForInt("Enter minimum battery level:");
int battMin = promptUserForInt("Enter maximum battery level:");
int numNodes = promptUserForInt("Enter number of nodes required:");
You could refactor further by taking in a Writer or BufferedWriter to display the prompt in - that way you could test it more easily.
Finally, I would suggest that you don't wrap each bit in a catch block for IOException; if you can't read the console input, I suspect you don't want to continue anyway, so you want to behave the same way whether the first input generates this exception or the second or third. Either declare that your method throws IOException, or have all three lines in the same try block, handled by the same catch block.
br.read() reads a char. Use Integer.parseInt(br.readLine()) which will read a whole line and convert it into an int.
Also, initialize all your local variables:
int battMax=0, battMin=0, numNodes=0;
If you're using java 1.5 or later, you can use the java.util.Scanner
public static getInt(String prompt){
int n = 0;
try {
System.out.print(prompt);
Scanner kb = new Scanner(System.in);
n = kb.nextInt();
}
catch(Exception ex){
ex.printStackTrace();
}
return n;
}
Sample Usage:
int battMax = getInt("Enter minimum battery level:");
int battMin = getInt("Enter maximum battery level:");
int numNodes = getInt("Enter number of nodes required:");