I have the following code snippet from my tester class.
FileReader freader=new FileReader(filename);
BufferedReader inputFile=new BufferedReader(freader);
int numScores = 0;
String playerType = "";
String nameHome = "";
String playerName = "";
String home = "";
String location = "";
int score = 0;
String date = "";
double courseRating = 0;
int courseSlope = 0;
ArrayList<Player> players = new ArrayList<Player>();
while (inputFile.read()!= -1) {
numScores = Integer.parseInt(inputFile.readLine());
playerType = inputFile.readLine();
nameHome = inputFile.readLine();
StringTokenizer st = new StringTokenizer(nameHome,",");
playerName = st.nextToken();
home = st.nextToken();
The program compiles, however when the tester is run, I get the following output error.
Exception in thread "main" java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:592)
at java.lang.Integer.parseInt(Integer.java:615)
at PlayerTest.main(PlayerTest.java:34)
I've tried researching this and what I fould was there's possibly a space when it changes the String that is read from the data file and converts it to an int. I tried reading directly into a strin, trimming the string, then converting to the int, but it got the same error.
This was the code that replaced numScores = Integer.parseInt(inputFile.readLine());
tempScores = inputFile.readLine();
tempScores.trim();
System.out.println(tempScores);
numScores = Integer.parseInt(tempScores);
Any help is appreciated.
*edited to show sample data
Sample data from file
3
B
James Smith, Strikers
FWB Bowling, 112,09/22/2012
White Sands, 142,09/24/2012
Cordova Lanes,203,09/24/2012
Possibly, your File contains empty lines. These are read as "" and therefore cannot be converted to int.
Furthermore, it is possible that you read the first character of each line by the read-statement in the header of the while-loop, so that it is ignored in the readline command. Then a number of length 1 (like "1") would become an empty line.
In any case, the construction of your loop is a bug.
You can put it all in an if statement:
if(!tempScores.equalsIgnoreCase(""))
{
I ran into a similar issue today. I was reading a response from REST end point and try to parse the json response. Bam! hit an error. Later on I realize the file had a BOM.
My suggestion is create a var
String var = inputFile.readLine();
int numScores = Integer.parseInt(var);
add a breakpoint and inspect what var contains, in my case the response had a BOM an empty unicode character code 65279 / 0xfeff. In any debugger worth it's salt you should be able to see each character.
if it's the case you need to strip that value from the string.
I used this library to detect this issue org.yaml:snakeyaml:1.16
import org.yaml.snakeyaml.reader.UnicodeReader;
//more code
private String readStream(InputStream inputStream) throws IOException {
UnicodeReader unicodeReader = new UnicodeReader(inputStream);
char[] charBuffer = new char[BUFFER_SIZE];
int read;
StringBuilder buffer = new StringBuilder(BUFFER_SIZE);
while ((read = unicodeReader.read(charBuffer,0,BUFFER_SIZE)) != -1) {
buffer.append(charBuffer, 0, read);
}
return buffer.toString();
}
You need to understand this please look into it.
Basic understanding is
try {
//Something that can throw an exception.
} catch (Exception e) {
// To do whatever when the exception is caught.
}
There is also an finally block which will always be execute even if there is an error. it is used like this
try {
//Something that can throw an exception.
} catch (Exception e) {
// To do whatever when the exception is caught & the returned.
} finally {
// This will always execute if there is an exception or no exception.
}
In your particular case you can have the following exceptions (link).
InputMismatchException - if the next token does not match the Integer regular expression, or is out of range
NoSuchElementException - if input is exhausted
IllegalStateException - if this scanner is closed
So you would need to catch exceptions like
try {
rows=scan.nextInt();
} catch (InputMismatchException e) {
// When the InputMismatchException is caught.
System.out.println("The next token does not match the Integer regular expression, or is out of range");
} catch (NoSuchElementException e) {
// When the NoSuchElementException is caught.
System.out.println("Input is exhausted");
} catch (IllegalStateException e) {
// When the IllegalStateException is caught.
System.out.println("Scanner is close");
}
Related
I am working on a game, and I want to use this text file of mythological names to procedurally generate galaxy solar-system names.
When I read the text file, I tell the while-loop I'm using to continue if there is something that's not a name on a given line. That seems to throw an exception in some (not all) areas where there are multiple lines without names.
How can I make the program work without throwing exceptions or reading lines without names on them?
My Code:
public class Rewrite {
public static void main(String[] args) {
loadFromFile();
}
private static void loadFromFile() {
String[] names = new String[1000];
try {
FileReader fr = new FileReader("src/res/names/Galaxy_System_Names.txt");
BufferedReader br = new BufferedReader(fr);
String aLine;
int countIndex = 0;
while ((aLine = br.readLine()) != null) {
// skip lines without names
if (aLine.equals(String.valueOf(System.lineSeparator()))) {
aLine = br.readLine();
continue;
} else if (aLine.equals("&")) {
aLine = br.readLine();
continue;
} else if (aLine.startsWith("(")) {
aLine = br.readLine();
continue;
}
System.out.println(aLine);
// capitalize first letter of the line
String firstLetter = String.valueOf(aLine.charAt(0));
aLine = firstLetter + aLine.substring(1);
names[countIndex++] = aLine;
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The Exception Thrown:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 0
at java.base/java.lang.StringLatin1.charAt(StringLatin1.java:47)
at java.base/java.lang.String.charAt(String.java:702)
at utilities.Rewrite.loadHumanNamesFromFile(Rewrite.java:39)
at utilities.Rewrite.main(Rewrite.java:10)
Text-File sample: This throws an error after the name "amor"
áed
áedán
aegle
aella
aeneas
aeolus
aeron
(2)
&
aeson
agamemnon
agaue
aglaea
aglaia
agni
(1)
agrona
ahriman
ahti
ahura
mazda
aias
aigle
ailill
aineias
aino
aiolos
ajax
akantha
alberic
alberich
alcides
alcippe
alcmene
alcyone
alecto
alekto
alexander
alexandra
alexandros
alf
(1)
alfr
alkeides
alkippe
alkmene
alkyone
althea
alvis
alvíss
amalthea
amaterasu
amen
ameretat
amirani
ammon
amon
amon-ra
amor
&
amordad
amulius
amun
From the docs of the BufferedReader::readLine:
Returns: A String containing the contents of the line, not including any line-termination characters
Thus when you get to this part of the file:
amor
&
It will read the blank line and strip the linebreak character, and all that will be left is an empty String. Therefore it will not be caught by your if statement:
if (aLine.equals(String.valueOf(System.lineSeparator())))
You need to add in a check for isEmpty()
After amor is an empty line. You're trying to get the char at index 0 of an empty line. Since it's an empty line, it obviously has no chars, and as such there's no char at index 0
For my assignment, I'm trying to read a sequence of integers into an array and calculate a few things about the array. I'm restricted to using InputStreamReader and BufferedReader to read from the file, and Integer.parseInt() is throwing NumberFormatException after the first line read.
Everything works if I input each number individually by keyboard, but it doesn't work at all if I try and read directly from the file.
Here's the code so far
int[] array = new int[20];
try {
int x, count = 0;
do{
x = Integer.parseInt((new BufferedReader(new InputStreamReader(System.in)).readLine()));
array[count] = x;
count++;
}
while (x != 0);
}
catch (IOException e){
System.out.println(e);
}
catch (NumberFormatException e){
System.out.println(e);
}
The case to be tested is
33
-55
-44
12312
2778
-3
-2
53211
-1
44
0
When I try and copy/paste the whole test case, the program only reads the first line and then throws
NumberFormatException. Why does readLine() only read the first value and ignore everything else?s
You are reopening System.in each time. I don't know what this does but I assume it can't be good.
Instead, you should use one BufferedReader, and in your loop, read lines one by one from it.
The way that I think this is happening is that you create a reader, read one line, and then on the next iteration you create a new one, which is empty but still tries to read, therefore it reads "", passes it to the parser and Integer.parseInt() throws NumberFormatException because it can't be parsed. The correct way to do this is:
int[] array = new int[20];
try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
int x, count = 0;
do {
String s = reader.readLine();
x = Integer.parseInt(s);
array[count] = x;
count++;
}
while (x != 0);
} catch (IOException | NumberFormatException e) {
e.printStackTrace();
}
I am getting java.util.NoSuchElementException error. We get this error for the following reasons.
If we don't check if the file has next line before reading it,
then it throws exception after reading last line since it is trying
to read a line which doesn't exist.
Format of the file is messed up
I think that the format of the file I m using is correct and I am also checking for next line before reading it but I am still getting the error.
When I debug it using print statement, it prints all the line and throws java.util.NoSuchElementException error after reading last line.
Please help me out
Here is the code :
public static void InterpretMessageFromFile() throws FileNotFoundException{
File inputfile = new File("filepath");
Scanner reader = new Scanner(inputfile);
try {
while (reader.hasNextLine()) {
String MessageType = reader.next();
int IsAdd = MessageType.compareToIgnoreCase("A");
int IsCancel = MessageType.compareToIgnoreCase("X");
int IsDelete = MessageType.compareToIgnoreCase("D");
int IsExecute = MessageType.compareToIgnoreCase("E");
int IsReplace = MessageType.compareToIgnoreCase("U");
//if the type of order is add order to existing Order Book
if (IsAdd == 0) {
String retrieve_ts = reader.next();
int ts = Integer.parseInt(retrieve_ts);
String retrieve_id = reader.next();
int id = Integer.parseInt(retrieve_id);
String or_side = reader.next();
String retrieve_share = reader.next();
int share = Integer.parseInt(retrieve_share);
String retrieve_price = reader.next();
int price = Integer.parseInt(retrieve_price);
System.out.println("Add Order : Id is " + id );
AddOrderToExistingBook.AddNewOrder(id, ts, or_side, share, price);
}
//if it is cancel order
if (IsCancel == 0){
String retrieve_ts = reader.next();
int ts = Integer.parseInt(retrieve_ts);
String retrieve_id = reader.next();
int id = Integer.parseInt(retrieve_id);
System.out.println("Cancel Order : Id is " + id + " time stamp is : " + ts );
CancelOrder.CancelPartOfOrder(id, ts);
}
}
}
}
finally {
reader.close();
}
}
Exception (copied from comments):
Exception in thread "main" java.util.NoSuchElementException at
java.util.Scanner.throwFor(Scanner.java:907) at
java.util.Scanner.next(Scanner.java:1416) at
OrderBook.InterpretOrderBookUpdateMessage.InterpretMessageFromFile(InterpretOrderBookUpdateMessage.java:20)
at OrderBook.MainMethod.main(MainMethod.java:50)
you are trying to consume a token that is not there.
you do a number of next() calls without checking if there is next.
in your case, I suspect a newline at the end of your file gives you an empty line as input.
the scanner will see a new line, but as it doesn't contain tokens, calling "next()" will cause an error.
the same would happen if you have empty lines between blocks in your file.
one thing you can use is:
public boolean hasNext(String pattern)
instead of
next()
this will let you do a lookahead without consuming a token.
so instead of:
String MessageType = reader.next();
int IsAdd = MessageType.compareToIgnoreCase("A");
int IsCancel = MessageType.compareToIgnoreCase("X");
// .... left out other classes
//if the type of order is add order to existing Order Book
if (IsAdd == 0){
// .. do stuff
}
you can do something like:
if (reader.hasNext("A") {
reader.next(); // consume A
int ts = reader.nextInt(); // get id
// ... etcetera
} else if (reader.hasNext("X") {
}
I would also recommend you use nextInt() instead of nextString and then calling parseInt
One other thing: you can even make your code better to read by doing:
if (reader.hasNext("A") {
handleAddition(reader);
}
and then later on define a method that only handles this case.
your main method will look like:
try
{
while (reader.hasNextLine())
{
if (reader.hasNext("A")) {
handleAdd(reader);
} else if (reader.hasNext("X")) {
handleCancel(reader);
} else if (reader.hasNext("D")) {
handleDelete(reader);
} else if (reader.hasNext("E")) {
handleExecute(reader);
} else if (reader.hasNext("R")) {
handleReplace(reader);
} else {
// unexpected token. pretty sure this is the case that triggers your exeception.
// basically log as info and ignore.
reader.nextLine();
}
}
}
finally
{
reader.close();
}
Now your method is nice and short, and all the specific actions are taken in methods with their own name.
the only thing I'm not 100% about if it it's good practice to consume A, X, R, etc... inside the main loop, or the actual handler method. I prefer to consume inside the method personally.
hope it helps.
I have a method for my app to read a random line from a text file and return it. Im using the randTxt() to read and return a random line from the txt file.
but it only shows the same line (1st line) everytime.
public String randTxt(){
// Read in the file into a list of strings
InputStreamReader inputStream = new InputStreamReader(getResources().openRawResource(R.raw.randomstuff));
//ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
String theLine="";
int i;
try {
i = inputStream.read();
while (i != -1) {
i = inputStream.read();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
LineNumberReader rdr = new LineNumberReader(inputStream);
int numLines = 30;
Random r = new Random();
rdr.setLineNumber(r.nextInt(numLines));
try {
theLine = rdr.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return theLine;
}
How can I fix it? and Can someone explain what's wrong in my code?
Here's the framework for doing what you need using BufferedReader. In this case, you don't need to store the values in a temp array.
InputStreamReader inputStream = new InputStreamReader
(getResources().openRawResource(R.raw.randomstuff));
BufferedReader br = new BufferedReader(inputStream);
int numLines = 30;
Random r = new Random();
int desiredLine = r.nextInt(numLines);
String theLine="";
int lineCtr = 0;
while ((theLine = br.readLine()) != null) {
if (lineCtr == desiredLine) {
break;
}
lineCtr++;
}
...
Log.d(TAG, "Magic line is: " +theLine);
You have gotten an answer of how to fix your code, but no explanation of why our original code did not work.
LineNumberReader.setLineNumber(int) does not go to the actual line, it just changes what number you call the current line.
So, say you read two lines, getLineNumber() will now return 2 (it started at 0 and increased by 1 each time a newline was encountered). if you now setLineNumber(10), getLineNumber() will return 10. Reading yet another line (your third) will cause getLineNumber() to return 11.
This is described in the Java Doc.
inputStream.read does not return a line number. it returns the byte that was read. this isn't how you would read line by line. to read line by line, you should use buffered reader's readLine method. its probably easier at that point to read it all into a local array and use that array to randomly get an entry, rather than using a line number reader.
I think Random() function returns a value between 0 and 1. hence, you may have to multiply it with 100 to get an integer value. May even consider a MOD "your upper limit" operation to guarentee that the index you finally get is between 0 and your upper limit
Use the index you calculated thus, in your setLineNumber() method.
Edit:
As john said, we can get whole number using Random() object.
public String getRandomLine(String fileLoc) throws IOException
{
BufferedReader reader = new BufferedReader(new FileReader(fileLoc));
ArrayList<String> lines = new ArrayList<String>();
String line =null;
while( (line = reader.readLine())!= null )
lines.add(line);
// Choose a random one from the list
return lines.get(new Random().nextInt(lines.size()));
}
public String getRandomLineOpt(String fileLoc)throws IOException
{
File f=new File(fileLoc);
RandomAccessFile rcf=new RandomAccessFile(f, "r");
long rand = (long)(new Random().nextDouble()*f.length());
rcf.seek(rand);
rcf.readLine();
return rcf.readLine();
}
I have been asked to write a file reader method, I have done one which works fine but cant get the 2nd one to work and keep getting this error after i open the booms.txt file
Error:java.util.NoSuchElementException
public instance variable
public List booms;
Code I'm using for the file reader
try
{
int x;
int y;
double boomTime;
boolean isAHit;
Scanner lineScanner;
bufferedFileReader = new BufferedReader(new FileReader(aFile));
String currentLine = bufferedFileReader.readLine();
while (currentLine != null)
{
lineScanner = new Scanner(currentLine);
lineScanner.useDelimiter(",");
x = lineScanner.nextInt();
y = lineScanner.nextInt();
boomTime = lineScanner.nextDouble();
isAHit = lineScanner.nextBoolean();
booms.add(new Boom(x,y,boomTime));
currentLine = bufferedFileReader.readLine();
}
}
catch (Exception anException)
{
System.out.println("Error:"+anException);
}
finally
{
try
{
bufferedFileReader.close();
}
catch (Exception anException)
{
System.out.println("Error:" +anException);
}
}
}
Please Help
Perhaps a blank line at the end of the file?
as maurice says, probably a blank or incorrect line of data in the file.
the exception (although you haven't posted the stack trace) is being thrown by the Scanner.next... calls.
Scanner.nextInt
NoSuchElementException - if input is
exhausted
this would be far more obvious to you and the members of this forum if you'd included the stack trace. try putting anException.printStackTrace(); in your catch blocks next time.
I'm using a another method that's not that complicated. just do this:
Scanner diskScanner = new Scanner(new File("pathname"));
to read for example a Integer from the specified file just type
int blahblahblah = diskScanner.nextInt();
Got it sorted I had a boolean variable which wasn't in the file it was reading :), its all about taking a break and looking at it again.