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);
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
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
What would be the proper way to use the finally block to close out of the file that I was in : event.dat. If you could help me makes sense of this, I'd greatly appreciate it. I've literally spent 4 hours moving things around, playing with the code and searching for answers online, but to no avail. Code works great without that portion, but I need to know how it works for future instances. Thank you and have a good day!
I am having issues with this block:
finally{
fstream.close();
}
Which is located in the following code:
String answer;
String letter;
String inType = "";
double inAmount = 0;
double amount;
description();
GironEventClass newInput = new GironEventClass();
try{
File infile = new File("event.dat");
Scanner fstream = new Scanner(infile);
System.out.println("File Contents ");
while(fstream.hasNext())
{
inAmount = fstream.nextInt();
inType = fstream.next();
try{
newInput.donations(inType, inAmount);
}
catch(IllegalArgumentException a){
System.out.println("Just caught an illegal argument exception. ");
}
finally{
fstream.close();
}
}
System.out.println("Total Sales: " + newInput.getSale());
System.out.println("Donations: " + newInput.getDonated());
System.out.println("Expenses: " + newInput.getExpenses());
}
catch (FileNotFoundException e){
System.out.println("\nEvent.dat could not be opened. ");
}
do{
System.out.print("Are there any more items to add that were not in the text file? (Type 'Y' or 'N')");
answer = keyboard.next();
if (("Y".equals(answer)) || ("y".equals(answer)))
{
letter = inLetter();
amount = inAmount();
newInput.donations(letter, amount);
}
}while (("Y".equals(answer)) || ("y".equals(answer)));
newInput.display();
}
public static String inLetter(){
Scanner keyboard = new Scanner(System.in);
String result;
String resultTwo;
System.out.println("T = Tiket Sales");
System.out.println("D = Donations");
System.out.println("E = Expenses");
System.out.print("Please input an identifier ");
result = keyboard.nextLine();
resultTwo = result.toUpperCase();
return resultTwo;
}
public static double inAmount(){
Scanner keyboard = new Scanner(System.in);
double result;
System.out.println("Please input an amount ");
result = keyboard.nextInt();
if(result <= 0.0){
System.out.print("Please input a positive and non-zero amount ");
result = keyboard.nextInt();
}
return result;
}
public static void description(){
System.out.println("The program will ask you what amount is being spent on what.");
System.out.println(" ex: expenses, ticket sales, and profts.");
System.out.println("This program will help determine whether the event generated or lost money.");
}
This is how the scanner should work:
while scanner has object
read them ( one object per method's call)
when objects are done
close the reader.
Your problem is that you use the close function when the while conclusion is true. So you should put it outside of the while loop
The Try block attempts to do something.
The Catch block only executes if something went wrong during the Try block.
The Finally block executes after the Try block (and Catch block, if executed) EVERY time.
Your issue is that you attempt to close the fstream inside the while loop.
while(fstream.hasNext()) <----- referencing fstream
{
inAmount = fstream.nextInt();
inType = fstream.next();
try{
newInput.donations(inType, inAmount);
}
catch(IllegalArgumentException a){
System.out.println("Just caught an illegal argument exception. ");
}
finally{
fstream.close(); <---- closing said stream
}
}
Since you've closed the stream, this while loop should only ever execute once. That being said, close the fstream outside the while loop and your program should return to normal.
You can also move the while loop inside the try block, which would work as well.
You need to declare fstream outside the try block otherwise it will be not visible in the finally block.
File infile = null;
File infile = null;
try {
infile = new File("event.dat");
fstream = new Scanner(infile);
...
} catch ( ) {
...
} finally {
// You need to handle exceptions also here
infile.close();
fstream.close();
}
You can also use the new try with resources syntax and leave to the jvm the closure of your streams.
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);
When I run my simple code and enter char instead of integer value which was supposed to be Entered.
Program, listed below is supposed to be terminated after printing "error please Enter integer value".
But this code, also printing the line after Occurrence of error
import java.util.InputMismatchException;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
System.out.println("enter value integer ");
Scanner sn = new Scanner(System.in);
try{
int a = sn.nextInt();
} catch (InputMismatchException ex){
System.out.println("error please enter integer value");
}
System.out.println("not terminating");
}
}
But this code, also printing the line after Occurrence of error
Because it is out side of try-catch, that is the advantage of exception handling.
Exception handling prevents the abnormal termination of program due to run time error. And that is what happened.
See also
exception handing docs
It is terminating, it just prints out the System.out first. This is as expected - it jumps into the catch block, and then continues.
System.out.println("enter value integer ");
Scanner sn = new Scanner(System.in);
try {
int a = sn.nextInt();
} catch (InputMismatchException ex) {
System.out.println("error please enter integer value");
// you are catching input mis match here
// exception will catch and program continues
}
System.out.println("not terminating"); // this is out side the try-catch
So you will get this line in your out put too.
After entering the catch block, flow continues on, so the next line to execute is the bottom print.
If you want to terminate from within the catch:
try {
int a = sn.nextInt();
} catch (InputMismatchException ex) {
System.out.println("error please enter integer value");
return; // program will end
}
If you want it to be terminated you need to re-throw the exception e.g.:
System.out.println("enter value integer ");
Scanner sn = new Scanner(System.in);
try {
int a = sn.nextInt();
} catch (InputMismatchException ex) {
System.out.println("error please enter integer value");
throw new RuntimeException(ex);
}
System.out.println("not terminating"); // this is out side the try-catch
That way the last system output would not be printed and you would get a stacktrace instead.