Help again guys, why do I always get this kind of error when using scanner, even though I'm sure that the file exists.
java.util.NoSuchElementException: No line found
I am trying to count the number of occurences of a by using for loop. the text file contain lines of sentence. At the same time, I want to print the exact format of sentences.
Scanner scanLine = new Scanner(new FileReader("C:/input.txt"));
while (scanLine.nextLine() != null) {
String textInput = scanLine.nextLine();
char[] stringArray = textInput.toCharArray();
for (char c : stringArray) {
switch (c) {
case 'a':
default:
break;
}
}
}
while(scanLine.nextLine() != null) {
String textInput = scanLine.nextLine();
}
I'd say the problem is here:
In your while condition, you scan the last line and come to EOF. After that, you enter loop body and try to get next line, but you've already read the file to its end. Either change the loop condition to scanLine.hasNextLine() or try another approach of reading files.
Another way of reading the txt file can be like this:
BufferedReader reader = new BufferedReader(new InputStreamReader(new BufferedInputStream(new FileInputStream(new File("text.txt")))));
String line = null;
while ((line = reader.readLine()) != null) {
// do something with your read line
}
reader.close();
or this:
byte[] bytes = Files.readAllBytes(Paths.get("text.txt"));
String text = new String(bytes, StandardCharsets.UTF_8);
You should use : scanner.hasNextLine() instead of scanner.nextLine() in the while condition
Scanner implements the Iterator interface which works by this pattern:
See if there is a next item (hasNext())
Retrieve the next item (next())
To count the number of occurrences of "a" or for that matter any string in a string, you can use StringUtils from apache-commons-lang like:
System.out.println(StringUtils.countMatches(textInput,"a"));
I think it will be more efficient than converting the string to character array and then looping over the whole array to find the number of occurrences of "a". Moreover, StringUtils methods are null safe
Related
I'm writing some code in Java to scan through a .txt file. Each line in the file contains two tokens, and there's only about 7 rows of data.
My aim is to use the while loop to scan through each line, store the tokens in a HashMap, and when the scanner reaches the end of the document I want the while loop to terminate. Here is a snippet of the code I am using:
while ((line = b.readLine()) != null) {
s = new Scanner(line);
String fileName = s.next();
String source = s.next();
sourceMap.put(fileName, source);
}
This is something I have done many times before, however there are now some issues with the while loop terminating. The while loop continues to operate even after the 'final' line has been read. When the scanners attempt to read tokens, a java.util.NoSuchElementException is returned.
From using the debugger I can see that the line immediately after the 'final' line of code is being read as: ""
I believe this is an empty string, however I am unsure if this is different to a line being null. I attempted to add code for the condition while (line != "") however this did not result in the while loop being terminated.
Has anyone experienced similar issues before, and if so how did you overcome them?
EDIT: This has now been resolved. There was a line with an empty string after the 'final' line in the .txt file. The corrected code is as follows:
while ((line != null) && (!line.isEmpty())) {
s = new Scanner(line);
String fileName = s.next();
String source = s.next();
sourceMap.put(fileName, source);
line = b.readLine();
}
I am using the following code after reading from a text file as to break the input of the text file into tokens:
String input;
while(true)
{
input = bin.readLine();
if (input == null)
{
System.out.println( "No data found in the file");
return 0;
}
break;
}
StringTokenizer tokenizer = new StringTokenizer(input);
Then:
for (int i=0; i < numAtt; i++)
{
attributeN[i] = tokenizer.nextToken();
}
I cannot understand why the attributeNames gets the tokens in the first line of the text file only, doesn't while(true) keep on reading the whole file? Also is there a way to avoid the while(true) and using break to terminate it?
Your break after if (input == null) { } is breaking the while, so your code only read one line.
Also is there a way to avoid the while(true) and using break to
terminate it?
Do it in this way:
while ((input = bin.readLine()) != null) {
//split input line here
}
Also, consider using String#split() to split the line in tokens. Example for the separator , :
String attributeNames[] = input.split(",");
The best way is using:
String splittedString[] = input.split("the separator");
It's recommended by Oracle.
Are you just trying to get tokens from the first line? If so, you don't need the while loop at all. Just remove the while { from the beginning and break; } from the end.
I need help with this. Can you tell me how to calculate the number of lines in the input.txt without counting the empty space lines?
So far, I tried:
BufferedReader reader = new BufferedReader(new FileReader("input.txt"));
int lines = 0;
while (reader.readLine() != null)
lines++;
So, this code is able to count the number of lines, but with the empty lines! I know that there are characters /n which illustrates the new line but I do not know how to integrate it in the solution.
I also tried to calculate number of lines, number of empty lines and subtract them, but I wasn't successful.
BufferedReader reader = new BufferedReader(new FileReader("input.txt"));
int lines = 0;
String line;
while ((line = reader.readLine()) != null){
if(!"".equals(line.trim())){
lines++;
}
}
You just need to remember the line you're looking at, and check it before counting:
int lines = 0;
String line;
while ((line = reader.readLine()) != null) {
if (!line.isEmpty()) {
lines++;
}
}
Note that you should be closing your reader too - either in an explicit finally statement, or using a try-with-resources statement in Java 7. I'd advise not using FileReader, too - it always uses the platform default encoding, which isn't a good idea, IMO. Use FileInputStream with an InputStreamReader, and state the encoding explicitly.
You might also want to skip lines which consist entirely of whitespace, but that's an easy change to make to the if (!line.isEmpty()) condition. For example, you could use:
if (!line.trim().isEmpty())
instead... although it would be cleaner to find a helper method which just detected whether a string only consisted of whitespace rather than constructing a new string. A regex could do this, for example.
BufferedReader's readLine() method only returns null when the end of the stream has been reached. To not count empty lines, test if the line exists and if it's empty then don't count it.
Quoting the linked Javadocs above:
Returns:
A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached
Clean and fast.
try (BufferedReader reader = new BufferedReader("Your inputStream or FileReader")) {
nbLignes = (int) reader.lines().filter(line -> !line.isEmpty()).count();
}
I believe I am not using correctly String Tokenizer. Here is my code:
buffer = new byte[(int) (end - begin)];
fin.seek(begin);
fin.read(buffer, 0, (int) (end - begin));
StringTokenizer strk = new StringTokenizer(new String(buffer),
DELIMS,true);
As you can see I am reading a chunk of lines from a file(end and begin are line numbers) and I am transfering the data to a string tokenizer. My delimitators are:
DELIMS = "\r\n ";
because I want to separate words that have a space between them, or are on the next line.
However this code sometimes separates whole words also. What could be the explanation?? Is my DELIMS string conceived wrong?
Also I am passing "true" as an argument to the tokenizer because I want the delimitators to be treated as tokens as well.( I want this because I want to count the line I am currently at)
Could you please help me. Thanks a lot.
To start with, your method for converting bytes into a String is a bit suspect, and this overall method will be less-than-efficient, especially for a larger file.
Are you required to use StringTokenizer? If not, I'd strongly recommend using Scanner instead. I'd provide you with an example, but will ask that you just refer to the Javadocs instead, which are quite comprehensive and already contain good examples. That said, it accepts delimiters as well - but as Regular Expressions, so just be aware.
You could always wrap your input stream in a LineNumberReader. That will keep track of the line number for you. LineNumberReader extends BufferedReader, which has a readLine() method. With that, you could use a regular StringTokenizer to get your words as tokens. You could use regular expressions or Scanner, but for this case, StringTokenizer is simpler for beginners to understand and quicker.
You must have a RandomAccessFile. You didn't specify that, but I'm guessing based on the methods you used. Try something like:
byte [] buffer = ...; // you know how to get this.
ByteArrayInputStream stream = new ByteArrayInputStream(buffer);
// if you have java.util.Scanner
{
int lineNumber = 0;
Scanner s = new Scanner(stream);
while (s.hasNextLine()) {
lineNum++;
String line = s.nextLine();
System.out.format("I am on line %s%n", lineNum);
Scanner lineScanner = new Scanner(line);
while (lineScanner.hasNext()) {
String word = lineScanner.next();
// do whatever with word
}
}
}
// if you don't have java.util.Scanner, or want to use StringTokenizer
{
LineNumberReader reader = new LineNumberReader(
new InputStreamReader(stream));
String line = null;
while ((line = reader.nextLine()) != null) {
System.out.println("I am on line " + reader.getLineNumber());
StringTokenizer tok = new StringTokenizer(line);
while (tok.hasMoreTokens()) {
String word = tok.nextToken();
// do whatever with word
}
}
}
I'm trying import CSV file to Arraylist using StringTokenizer:
public class Test
{
public static void main(String [] args)
{
List<ImportedXls> datalist = new ArrayList<ImportedXls>();
try
{
FileReader fr = new FileReader("c:\\temp.csv");
BufferedReader br = new BufferedReader(fr);
String stringRead = br.readLine();
while( stringRead != null )
{
StringTokenizer st = new StringTokenizer(stringRead, ",");
String docNumber = st.nextToken( );
String note = st.nextToken( ); /** PROBLEM */
String index = st.nextToken( ); /** PROBLEM */
ImportedXls temp = new ImportedXls(docNumber, note, index);
datalist.add(temp);
// read the next line
stringRead = br.readLine();
}
br.close( );
}
catch(IOException ioe){...}
for (ImportedXls item : datalist) {
System.out.println(item.getDocNumber());
}
}
}
I don't understand how the nextToken works, because if I keep the initialize three variables (docNumber, note and index) as nextToken(), it fails on:
Exception in thread "main" java.util.NoSuchElementException
at java.util.StringTokenizer.nextToken(Unknown Source)
at _test.Test.main(Test.java:32)
If I keep docNumber only, it works. Could you help me?
It seems that some of the rows of your input file have less then 3 comma separated fields.You should always check if tokenizer has more tokens (StringTokenizer.hasMoreTokens), unless you are are 100% sure your input is correct.
CORRECT parsing of CSV files is not so trivial task. Why not to use a library that can do it very well - http://opencsv.sourceforge.net/ ?
Seems like your code is getting to a line that the Tokenizer is only breaking up into 1 part instead of 3. Is it possible to have lines with missing data? If so, you need to handle this.
Most probably your input file doesn't contain another element delimited by , in at least one line. Please show us your input - if possible the line that fails.
However, you don't need to use StringTokenizer. Using String#split() might be easier:
...
while( stringRead != null )
{
String[] elements = stringRead.split(",");
if(elements.length < 3) {
throw new RuntimeException("line too short"); //handle missing entries
}
String docNumber = elements[0];
String note = elements[1];
String index = elements[2];
ImportedXls temp = new ImportedXls(docNumber, note, index);
datalist.add(temp);
// read the next line
stringRead = br.readLine();
}
...
You should be able to check your tokens using the hasMoreTokens() method. If this returns false, then it's possible that the line you've read does not contain anything (i.e., an empty string).
It would be better though to use the String.split() method--if I'm not mistaken, there were plans to deprecate the StringTokenizer class.