So I'm trying to write a code that searches a txt file for a specific string, then prints all lines on which the string occurs.
The most straightforward way to do this seems to be running a Scanner and a LineNumberReader through the document, adding lines that fit the bill to the "found" string. However, whenever it stumbles across a line that doesn't contain the word, it throws a NullPointerException and kills the loop no matter what. Can anyone tell me what I'm doing wrong?
FileReader r = new FileReader(f);
LineNumberReader l = new LineNumberReader(r);
Scanner s = new Scanner(l);
int i = 1;
String found = "Instances of string found:\n";
{
while (s.hasNextLine()) {
try {
if (s.findInLine(keyword).isEmpty() == false) {
found = found + l.readLine() + "\n";
s.nextLine();
} else {
s.nextLine();
}
} catch (NullPointerException e) {
s.nextLine();
}
}
display(found, "Match found!");
}
Check the documentation of scanner: If no such pattern is detected in the input up to the next line separator, then null is returned and the scanner's position is unchanged.
You call s.findInLine(keyword).isEmpty() == false, if the word is not contained in findInLine(keyword) will be null, thus you'd be calling null.isEmpty(). There's your exception ;)
You don't have to check for isEmpty(), s.findInLine(keyword)!= null should be enough.
If you're using a method that is documented as returning null in some cases, then you should assign the result of the method to a variable (if you're going to use it for something else) and use == or != to test it for null. It is very poor programming practice to use the result as a reference and then rely on try/catch on NullPointerException to see if it's null. For one thing, what if there's an unexpected null somewhere else in the try body? Now it will be catching the exception for the wrong reason. NullPointerException always indicates a program bug. It should never be part of the "normal" program logic.
As for why it "kills the loop": It shouldn't. Even though your use of try/catch is poor practice, it should still work the way I think you intended, and shouldn't kill the loop. I just tested something similar to your code, but without l.readLine(), and it seemed to behave. If you want the line number, it's l.getLineNumber(), not l.readLine(), which tries to read a line of text and could sabotage the Scanner.
Related
sorry, changed the question slightly.
essentially i want to know if aString contains String. My issue is when comparing say aS a substring of aString) "aS".contains("String") shows true.
String a="st", b="string";
I ran System.out.println(a.contains(b));
That returned false, as expected. I have an understanding of contains, i must be missing something else.
So It had seemed that my program was working properly, but I made some adjustments and came back and the whole thing stopped working. I sussed out what are usually the common culprits (brackets, file io, etc.). I found if(string.contains(string)) would continually run, ie: always true. not sure why this is happening, probably something I missed in the code.
This is an example of my output (Just a char by char reading of the file):
I
n
t
e
g
e
r
G
;
import java.io.File;
import java.util.ArrayList;
import java.util.Scanner;
public class comp{
public static void main(String[] args){
ArrayList<String> lines = new ArrayList<String>();
ArrayList<String> symbolTable = new ArrayList<String>();
ArrayList<String> parsedFile = new ArrayList<String>();
try {
File file = new File("symbolTable.txt");
Scanner scanner=new Scanner(file);
while (scanner.hasNextLine()&&symbolTable.add(scanner.nextLine().replaceAll("\\s+","").toLowerCase()));
scanner.close();
} catch (Exception ex) {
ex.printStackTrace();
}
try {
File file = new File("APU_CS400_input.txt");
Scanner scanner=new Scanner(file);
while (scanner.hasNextLine()&&lines.add(scanner.nextLine().replaceAll("\\s+","").toLowerCase()));
scanner.close();
} catch (Exception ex) {
ex.printStackTrace();
}
//runs through line by line of the input file
for(String line: lines){
String sBuild = "";
StringBuilder identifier = new StringBuilder("");
//moves through the line char by char
for(int i=0;line.length()>i; i++){
sBuild+=line.charAt(i);
//moves through the symbol table comparing each symbol to each string
//that is built char by char
for(String symbol: symbolTable){
//if the char string matches the symbol then any identifiers are saved and
//symbols are saved, the string is then reset to empty
//This is where i seem to get an issue
***if(sBuild.contains(symbol)){***
if(symbol.length()<sBuild.length()){
identifier.append(sBuild,0,sBuild.length()-symbol.length());
parsedFile.add(identifier.toString());
identifier.delete(0,sBuild.length()-symbol.length());
}
sBuild="";
parsedFile.add(symbol);
}
}
}
}
for(String symbol:parsedFile){
System.out.println(symbol);
}
}
}
Blockquote
Think of it this way.
s1.contains(s2)
should return true, if a substring of s1 can be found such that
s1.substring(i, j).equals(s2)
is true.
If s2 is an empty string, then i = 0, j = 0 is one such substring, so contains() returns true.
As it should.
if(String.Contains("")) always should be true, as long as the String is not null.
essentially i want to know if "aString" contains "String".
Yes, "aString" as a string-value does contain the string-value of "String"
My issue is when comparing say "aS" (a substring of "aString") "aS".contains("String") shows true.
Are you sure? This cannot be, therefore I rather suspect bugs in your code.
To spare youself of "empty String symbols" consider this:
try {
File file = new File("symbolTable.txt");
Scanner scanner=new Scanner(file);
while (scanner.hasNextLine()) {
// toLowerCase will do nothing for characters that are not letters
// Don't spend CPU cycles with regex
String symbolLine=scanner.nextLine().toLowerCase();
// Collect the symbol only if non-empty?? This will save you from empty symbols
if(symbolLine.trim().length()>0) {
symbolTable.add(symbolLine); // or .add(symbolLine.trim()) ???
}
}
scanner.close();
} catch (Exception ex) {
ex.printStackTrace();
}
You may have to look at this one a bit mathematically to see why s.contains("") is always true. Suppose you think of this this way:
a.contains(b) is true if there are some values i and j such that a.substring(i,j) is equal to b.
If you think about it a bit, you'll see that this is exactly what contains means when the argument is a nonempty string like "xyz". If there is some substring of x that equals "xyz", then s.contains("xyz") is true. If there is no such substring, then s.contains("xyz") is false.
So it makes sense that the same logic would apply for an empty string, since it applies everywhere else. And it's always true that a.substring(0,0) equals "" (if a is not null). That's why a.contains("") should always be true.
It may not be intuitively obvious from the English meaning of "contains", but when you're dealing with "edge cases" like this, you sometimes have to think in different terms. Often, the Javadoc spells things out so that you can easily figure out what happens in the edge cases, without relying on intuition. Unfortunately, in this case, they didn't.
I'm writing a simple file server that will let the user telnet in, supply a username and search for the access level given to that user, and then show a list of files and only allow them to see the contents of the file if they have a sufficient access level. This code is for the server side, I'm just using PuTTY for the client
I read the userfile in (delimited with colons to separate name and access level)
paul:10
schemm:8
bobbarker:0
with this code
static Map<String, Integer> users = new HashMap<String, Integer>();
file = new File("userfile.txt");
try
{
out.println("Reading userfile.txt");
Scanner scannerusers = new Scanner(file);
while (scannerusers.hasNextLine())
{
String line = scannerusers.nextLine();
line.trim();
String field[] = line.split(":");
users.put(field[0], Integer.parseInt(field[1]));
}
scannerusers.close();
}
catch (FileNotFoundException e)
{
out.println("userfile.txt not found!");
}
But my actual problem is here (at least I think). Both the uncommented and commented code will fail on the first attempt, but succeed on the second.
//socket connection stuff here, and all this is nested in a try-catch to get
//connection errors
while(!check)
{
outToClient.writeBytes("What is your username?");
clientinput = inFromClient.readLine();
String username = clientinput;
//
if(users.get(username) == null)
{
outToClient.writeBytes("Invalid username");
}
else
{
check = true;
}
//
//try
//{
// accesslevel = users.get(username);
// check = true; //my thinking was that the NullPointerException would be thrown
// //before this point, but either way doesn't fix the problem
//}
//catch(NullPointerException e)
//{
// outToClient.writeBytes("Incorrect username");
//}
}
Edit: I put the full source on pastebin here
I agree, this does sound like a race condition but I don't see where a race condition would come from in your code. Perhaps it's the way you open your streams? Now I haven't played with Java in a while, but if I remember right I always had the base stream, then opened an input stream reader (I think) from the base stream, then wrapped a buffered reader around that.
Try printing out the string you receive from the client, in ASCII codes. Printing out the actual string might not show some unprintable characters you might be receiving.
If it ALWAYS fails the first time, and ALWAYS succeeds the second, then it sounds like a race condition. Perhaps the file read code is triggered by the first read operation, but done in a separate thread so the calling thread continues instead of synchronously waiting for the result. We need to see the calling code to be sure.
Perhaps inFromClient.readLine() is reading more (or less) than you expect the first time around. Are you sure it is returning what you expect? I haven't used PuTTY in a while, perhaps it is sending some terminal control characters on initial connect that are getting picked up by your first read? You also don't show us the connection code, are you sending data back and forth prior to this point that is not being fully processed?
I want to make a command line, just to run basic commands. So far, I've made it so that people can tell the program their name. When I don't enter a name, however, it treats it as if I did. Here is my class:
public static void main(String args[])
throws IOException
{
int a = 1;
do
{
System.out.print("$$: ");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String wtt = null; // wtt = what they typed!
wtt = br.readLine();
if(wtt == null)
{
System.out.println("Why wont you tell me your name!");
}
else
{
System.out.println("Thanks for the name, " + wtt);
}
}
while(a == 1);
}
Here is the output
$$: well
Thanks for the name, well
$$: hole
Thanks for the name, hole
$$:
Thanks for the name,
Why does it not work?
Calling readLine() on a BufferedReader will only return null on end of input. Here, the input hasn't ended, you've just entered an empty line, so "" (the empty string) is the result.
You will need to end the input stream, usually with Ctrl-C. Then you'll get "Why wont you tell me your name!". But then you'll need to break out of your infinite loop.
use this
if (wtt == null || wtt.trim().length() == 0)
Try
wtt.length()==0
instead of checking for null
It's because although you set the string to null at first, you are then setting it to br.readLine() which will have a line to read even though the user didn't type anything before hitting enter, so it will set the string to an empty string.
You should also (or instead) compare your string to "" (an empty string) to see if they entered anything.
You should compare wtt to "" as well to make sure the line isn't empty.
if (wtt == null) {
becomes
if (wtt == null && !!("".equals(wtt))) {
Instead of comparing wtt to null, compare it to empty string:
if ("".equals(wtt))
{
System.out.....
}
readLine method doesn't give you end of line characters (e.g. \n, \r). So, you cannot expect the loop to exit when you press just enter without entering anything. You can use read method instead to read characters and determine if there was a new line character or use Scanner class which seems to me better suitable in your situation.
Im trying to go on a loop while the input file has a string on the following line but im getting an error. Any idea why?
while( !((input = in.nextLine()).equals(""))){
...
}
Output:
Enter file name: input1.txt
evil live
Exception in thread "main" This is a palindrome
level
This is a palindrome
dog
Not a palindrome
java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Scanner.java:1516)
at Palindrome.main(Palindrome.java:41)
Your code is not correct, because it is possible that the input would end without providing an empty line. You should check if a line is available before checking it for being empty:
while(in.hasNextLine() && !((input = in.nextLine()).equals(""))){
...
}
There is no line after the end of file. When the last line is read the next call to nextLine() will fail. Use hasNextLine() to protect against this.
in.nextLine() is probably returning a null, which is being assigned to input, which you are trying to invoke equals on.
Use hasNextLine (documentation here) to make sure you can get the next line.
The way your loop is setup, it will never reach a "" string because it will hit the end of the file before doing so. it should be something like
while (input.hasNextLine()) {
...
}
This means that it will continue until the file has no next line.
Compare against null as well to check against End-Of-File
as
while(((input = in.nextLine())!= null) && !(input.equals(""))){
Or try:
while(in.hasNextLine(){
input = in.nextLine();
if(input != null && !(input.equals(""))){
........
}
}
Try to use this type of thing, catching the exception if needed:
input = in.nextLine();
while( !(input.equals(""))){
...
}
and if it throws an error, then set up a try...catch loop
May be you need,
while(in.hasNextLine()){
input = in.nextLine();
}
Scanner throws an exception when it runs out of input. You seem to be thinking that it will return a zero-length string.
Are you using Scanner to read a file a line at a time? That's not what it's for. You may want to look at BufferedReader.
I have a program that reads in lines from a file (with two lines) using a while loop (condition is bufferedReader.readLine()!=null), assigns myJSONObject a JSON read from the file, then I have an if statment (if(bufferedReader.readLine()!=null&&!bufferedReader.readline.matches(DELETE_REGEX)) and if that's true (i.e. if the line we read is not null, and we don't match a regex) then perform some function on the JSON which should append that new JSON to a file.
I have this in some try-catch blocks. It looks a little like so:
try{
openFiles;
while(buff.readLine()!=null){
try {
instatiateAndUseJSONParser;
if(bufferedReader.readLine()!=null
&&!bufferedReader.readline.matches(DELETE_REGEX))
{doSomeStuff;}
else
{continue;}
} catch (AllTheExceptions e){e.printStackTrace}
}
closeFiles;
}catch(SomeMoreExceptions e){e.printStackTrace}
When I run this is gets to the iff statement, and then terminates with exit value:0 (program closed as normal)
Why is this? It doesn't get anywhere near the 'continue' or a catch block.
If I remove the second line I get a NullPointerException due to line 50 of String Reader, but I'm not using StringReader (I've tried importing it, but eclipse yellow-underlines it and this changes nothing). When debugging, it pops up a tab for StringReader.<init>(String) line: 50 and just says 'Source not found'.
I'm pretty new to Java, so I don't really have a clue what's happening. Any help would be appreciated in clearing this up.
Thanks!
Every time readLine() is called, it reads a new line. You can thus read 3 lines per iteration in your current code. You should assign the result of the first call to a variable, and use this variable:
String line = null;
while ((line = buff.readLine()) !=null) {
try {
instatiateAndUseJSONParser;
if (line.matches(DELETE_REGEX)) {
doSomeStuff;
}
}
catch (AllTheExceptions e){
throw new RuntimeException(e);
}
}
You should also avoid swallowing exceptions.