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
Related
I have used the following code to write elements from an arraylist into a file, to be retrieved later on using StringTokenizer. It works perfect for 3 other arraylists but somehow for this particular one, it throws an exception when reading with .nextToken() and further troubleshooting with .countTokens() shows that it only has 1 token in the file. The delimiters for both write and read are the same - "," as per the other arraylists as well.
I'm puzzled why it doesnt work the way it should as with the other arrays when I have not changed the code structure.
=================Writing to file==================
public static void copy_TimeZonestoFile(ArrayList<AL_TimeZone> timezones, Context context){
try {
FileOutputStream fileOutputStream = context.openFileOutput("TimeZones.dat",Context.MODE_PRIVATE);
OutputStreamWriter writerFile = new OutputStreamWriter(fileOutputStream);
int TZsize = timezones.size();
for (int i = 0; i < TZsize; i++) {
writerFile.write(
timezones.get(i).getRegion() + "," +
timezones.get(i).getOffset() + "\n"
);
}
writerFile.flush();
writerFile.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
==========Reading from file (nested in thread/runnable combo)===========
public void run() {
if (fileTimeZones.exists()){
System.out.println("Timezone file exists. Loading.. File size is : " + fileTimeZones.length());
try{
savedTimeZoneList.clear();
BufferedReader reader = new BufferedReader(new InputStreamReader(openFileInput("TimeZones.dat")));
String lineFromTZfile = reader.readLine();
while (lineFromTZfile != null ){
StringTokenizer token = new StringTokenizer(lineFromTZfile,",");
AL_TimeZone timeZone = new AL_TimeZone(token.nextToken(),
token.nextToken());
savedTimeZoneList.add(timeZone);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}
}
}
===================Trace======================
I/System.out: Timezone file exists. Loading.. File size is : 12373
W/System.err: java.util.NoSuchElementException
at java.util.StringTokenizer.nextToken(StringTokenizer.java:349)
at com.cryptotrac.trackerService$1R_loadTimeZones.run(trackerService.java:215)
W/System.err: at java.lang.Thread.run(Thread.java:764)
It appears that this line of your code is causing the java.util.NoSuchElementException to be thrown.
AL_TimeZone timeZone = new AL_TimeZone(token.nextToken(), token.nextToken());
That probably means that at least one of the lines in file TimeZones.dat does not contain precisely two strings separated by a single comma.
This can be easily checked by making sure that the line that you read from the file is a valid line before you try to parse it.
Using method split, of class java.lang.String, is preferable to using StringTokenizer. Indeed the javadoc of class StringTokenizer states the following.
StringTokenizer is a legacy class that is retained for compatibility reasons although its use is discouraged in new code. It is recommended that anyone seeking this functionality use the split method of String or the java.util.regex package instead.
Try the following.
String lineFromTZfile = reader.readLine();
while (lineFromTZfile != null ){
String[] tokens = lineFromTZfile.split(",");
if (tokens.length == 2) {
// valid line, proceed to handle it
}
else {
// optionally handle an invalid line - maybe write it to the app log
}
lineFromTZfile = reader.readLine(); // Read next line in file.
}
There are probably multiple things wrong, because I'd actually expect you to run into an infinite loop, because you are only reading the first line of the file and then repeatedly parse it.
You should check following things:
Make sure that you are writing the file correctly. What does the written file exactly contain? Are there new lines at the end of each line?
Make sure that the data written (in this case, "region" and "offset") never contain a comma, otherwise parsing will break. I expect that there is a very good chance that "region" contains a comma.
When reading files you always need to assume that the file (format) is broken. For example, assume that readLine will return an empty line or something that contains more or less than one comma.
Can someone explain and help me fix this program.
import java.util.*;
import java.io.*;
public class test {
public static void main(String[] args) {
Scanner key = new Scanner(System.in);
boolean clear;
int in = 0;
do {
clear = true;
try {
in = key.nextInt();
} catch (InputMismatchException e) {
System.out.println("Invalid");
clear = false;
}
} while (clear == false);
String stringIn = Integer.toString(in);
String[] dec = stringIn.split("");
for (int i = 1; i < (dec.length); i++) {
System.out.print(dec[i] + " ");
}
}
}
Whenever I enter a invalid input instead of an int, my program keeps looping "Invalid" instead of giving the option to enter a new value for in.
The problem is that if the scanner fails to find an input in the correct format, it will throw an exception and not read the input.
Because the scanner does not read the invalid int input, the next time nextInt is called, it will try to read the invalid input again, and miserably fails at it, printing another "invalid!"
So you need to read the input afterwards if it finds an invalid int:
// do this in the catch block:
key.next();
This makes sure that the next token is read.
Full code:
Scanner key = new Scanner(System.in);
boolean clear;
int in = 0;
do {
clear = true;
try {
in = key.nextInt();
} catch (InputMismatchException e) {
System.out.println("Invalid");
clear = false;
key.next();
}
} while (clear == false);
String stringIn = Integer.toString(in);
String[] dec = stringIn.split("");
for (int i = 1; i < (dec.length); i++) {
System.out.print(dec[i] + " ");
}
Check the API of the nextInt method:
This method will throw InputMismatchException if the next token cannot be translated into a valid int value as described below. If the translation is successful, the scanner advances past the input that matched.
Meaning, that if it's not successful - it will not advance and will try to execute nextInt over the illegal token over and over again failing every time.
Try adding next() into the exception catch clause, it should skip the token and read the next one then. next() reads a String, so it does not really care about the formatting, and will allow you to advance the position in the stream to read the next token.
The problem is that you are writing to the console inside the catch, so then when you call key.nextInt() in the try the program reads the value you print to the console, so an easy way to solve this is to add a line like: key.nextLine() inside the catch and that will solve your problem.
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
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);
I've got some Java code that runs quite the expected way, but it's taking some amount of time -some seconds- even if the job is just looping through an array.
The input file is a Fasta file as shown in the image below. The file I'm using is 2.9Mo, and there are some other Fasta file that can take up to 20Mo.
And in the code im trying to loop through it by bunches of threes, e.g: AGC TTT TCA ... etc The code has no functional sens for now but what I want is to append each Amino Acid to it's equivalent bunch of Bases. Example :
AGC - Ser / CUG Leu / ... etc
So what's wrong with the code ? and Is there any way to do it better ? Any optimization ? Looping through the whole String is taking some time, maybe just seconds, but need to find a better way to do it.
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class fasta {
public static void main(String[] args) throws IOException {
File fastaFile;
FileReader fastaReader;
BufferedReader fastaBuffer = null;
StringBuilder fastaString = new StringBuilder();
try {
fastaFile = new File("res/NC_017108.fna");
fastaReader = new FileReader(fastaFile);
fastaBuffer = new BufferedReader(fastaReader);
String fastaDescription = fastaBuffer.readLine();
String line = fastaBuffer.readLine();
while (line != null) {
fastaString.append(line);
line = fastaBuffer.readLine();
}
System.out.println(fastaDescription);
System.out.println();
String currentFastaAcid;
for (int i = 0; i < fastaString.length(); i+=3) {
currentFastaAcid = fastaString.toString().substring(i, i + 3);
System.out.println(currentFastaAcid);
}
} catch (NullPointerException e) {
System.out.println(e.getMessage());
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
} finally {
fastaBuffer.close();
}
}
}
currentFastaAcid = fastaString.toString().substring(i, i + 3);
Please replace with
currentFastaAcid = fastaString.substring(i, i + 3);
toString method of StringBuilder create new instance of String object every time you call it. It still contain a copy of all your large string. If you call substring directly from StringBuilder it will return a small copy of substring.
Also remove System.out.println if you don't really need it.
The big factor here is you are doing the call to substring over a new String each time.
Instead, use substring directly over the stringbuilder
for (int i = 0; i < fastaString.length(); i+=3){
currentFastaAcid = fastaString.substring(i, i + 3);
System.out.println(currentFastaAcid);
}
Also, instead of print the currentFastaAcid each time, save it into a list and print this list at the end
List<String> acids = new LinkedList<String>();
for (int i = 0; i < fastaString.length(); i+=3){
currentFastaAcid = fastaString.substring(i, i + 3);
acids.add(currentFastaAcid);
}
System.out.println(acids.toString());
Your main problem besides the debug output surely is, that you are creating a new String with your completely read data from the file in each iteration of your loop:
currentFastaAcid = fastaString.toString().substring(i, i + 3);
fastaString.toString() will give the same result in each iteration and therefore is redundant. Get it outside the loop and you will surely save some seconds runtime.
Apart from suggested optimization in the serial code, I will go for parallel processing to reduce time further. If you have really big file, you can divide the work of reading file and processing read-lines, in separate threads. That way, when one thread is busy reading nextline from large file, other thread can process read-lines and print them on console.
If you remove the
System.out.println(currentFastaAcid);
line in the for loop, you will gain quite decent time.