I need to read a text file line by line till I find a specific string. I'm using BufferedReader.readLine() but when I debug I find that it starts from the third line in the file and skips lines after that.
Here is my code:
try {
reader = new BufferedReader(new FileReader(path));
String line1 = null;
while ((line1 = reader.readLine()) != null) {
if (line1.toString() == invocation0) {
found = true;
return false;
} else if (line1 == invocation1) {
found = true;
return true;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
}
}
I would really appreciate any help, as I tried many different solutions for this and still can't solve this issue.
the content of the file is like:
.//============================================================================
.// File: abc.mark
.// Description: anything
.// Notice: anything
.// .//============================================================================
.invoke RemoveClass("Properties",0)
if(line1.equals(invocation0))
Use equals() method for String value comparison.
Also, instead of return within the if, you can use a break. This is just a suggestion though.
BufferedReader should not be skipping the anything. Unfortunately you are the one who is making read method to skip the line. The equlaity operator == will not compare the content of any two strings, rather it compares whether they are of same object. You could possibly avoid it in two ways.
Call the intern() on invocation0 (line1 object should have been interned before anyway)
More precisely use equals method line1.equals(invocaton0)
This link may be of some help for you to understand it better.
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.
I have this method in Java, which is called within another method's try block. importFormat returns the class with assigned values (//do what is needed) in the try block. The method should read a file line by line. In case the method call to the method with try block is called more times than are the lines in a file, the importFormat() should return null.
I tried to check it with if block, although it doesn't do much and the ClassName is always returned. It seems the class stores always a first line from the file.
private ClassName importFormat(BufferedReader br) throws IOException, ParseException {
String out;
Track t = new ClassName();
if((out = br.readLine()) == null) return null;
//do what is needed
}else{
t = null; //here I unsuccessfully tried to force the method to again return null, no luck
System.err.print(out);
throw new ParseException("", 0);
}
return t;
}
I have tried also the br.ready() method, it didn't make any difference
EDIT: I noticed I have reproduced the code incorrectly, I'm sorry for that. Here it should be clearer
Minimal reproducible code:
private ClassName foo(BufferedReader br) throws IOException {
ClassName t = new ClassName();
String out = null;
out = br.readLine();
if(out.equals(null)) return null; //handle the case where there's no more line to read
if(/*!string red from BufferedReader.isEmpty()*/){
//do something
}else{
t = null; //ensure that null would be returned
//do something more unrelated to this question
}
return t;
}
I dont realy understand your question but I think you should not compare like this:
if((out = br.readLine()) == null) return null;
To compare string in java, let use str1.equals(str2) instead. So I think you should try:
if(out.equals(br.readLine())) {
//do sth here because "out" exists in BufferReader.
} else {
System.out.println("Continue searching...\n");
}
return t;
This question already has answers here:
Using BufferedReader.readLine() in a while loop properly
(7 answers)
Closed 8 years ago.
I have problem with reading from my socket i read only if value isn't null but it doesnt't works.
#Override
public void run() {
System.out.println("Reading from socket");
while(true){
try {
if(!(br.readLine().equals(null)))read += br.readLine();
} catch (IOException e) {
System.out.println("error " + e);
}
}
}
here is error:
Exception in thread "Thread-4" java.lang.NullPointerException
at connection.CreateConnection.run(CreateConnection.java:61)
at java.lang.Thread.run(Unknown Source)
If br.readLine() returns null, then calling .equals(null) on it will throw an exception - it won't return true. You just want to compare reference identity with null.
Calling .equals(null) is never useful, unless you're testing that your equals implementation works properly :)
Additionally, you'll be skipping every other line by calling readLine() twice on each loop iteration.
You want something like:
String line;
if ((line = br.readLine()) != null) {
read += line;
}
... except that will be painfully slow due to repeated string concatenation. You should almost certainly be using a StringBuilder instead.
Also, doing all of this in a loop which catches IOException seems like a recipe for disaster - if the a call fails, it's very likely that it'll keep failing forever, whereupon your program is basically hung in a tight loop. You should almost certainly stop when you get an exception, rather than keeping going. For example:
try {
String line;
while ((line = reader.readLine()) != null) {
read += line; // Or builder.append(line);
}
} catch (IOException e) {
// Whatever you want to do
}
Finally, consider the value of whitespace, both horizontal and vertical, as well as the benefits of using braces even in single-statement if statements etc. The line if(!(br.readLine().equals(null)))read += br.readLine(); is compact at the expense of readability.
Say you are on the last line of your file, you call br.readLine() to check if it's not null. Your line exists so your test passes. Then you call br.readLine() once again. Unfortunately there is nothing left to read! And you get your exception.
Rewrite your code like that:
#Override
public void run() {
System.out.println("Reading from socket");
String line;
while(true){
try {
line = br.readLine()
if((line != null))read += line;
} catch (IOException e) {
System.out.println("error " + e);
}
}
}
You are calling .equals() on a null object, which causes the null pointer issue I assume. If you want to read with a buffered reader, try doing something like:
String line = reader.readLine();
while(line != null){
System.out.println(line);
line = reader.readLine();
}
This will eliminate the issue of null pointers, and will also stop you from skipping any lines during reading.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
[12]
key1=val1
key2=val2
key3=val3
key4=val4
key5=val5
[13]
key1=val1
key2=val2
key3=val3
key4=val4
key5=xyz
[14]
key1=val1
key2=val2
key3=val3
key4=val4
key5=val5
I want to update key5=val5 where [13].
try {
br = new BufferedReader(new FileReader(oldFileName));
bw = new BufferedWriter(new FileWriter(tmpFileName));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
if (line.contains("[13]"))
{
while (line.contains("key5")) {
if (line.contains("key5"))
{
line = line.replace("key5", "key5= Val5");
bw.write(line+"\n");
}
}
}
}
} catch (Exception e) {
return;
} finally {
try {
if(br != null)
br.close();
} catch (IOException e) {
//
}
try {
if(bw != null)
bw.close();
} catch (IOException e) {
//
}
}
This block of code is problematic:
if (line.contains("[13]"))
{
while (line.contains("key5")) {
//etc....
Because there are NO lines which contain both [13] and key5 (they are on separate lines), so the while loop will NEVER be entered.
Instead, when the line [13] is encountered, it's necessary to remember it and store the flag in a boolean, something like the following:
boolean in13 = false;
//... other lines...
if (line.equals("[13]")) {
in13 = true;
} else if (line.startsWith("[")) {
in13 = false; //another block started, clear flag
}
if (in13 && line.startsWith("key5=")) {
// you've found it
}
You really need to step through your logic in your head; in your code:
if (line.contains("[13]")) {
while (line.contains("key5")) {
if (line.contains("key5")) {
line = line.replace("key5", "key5= Val5");
bw.write(line+"\n");
}
}
}
Try writing this out on a piece of paper or something and following it. Look at your while (line.contains("key5")) loop for example. If the line contains "[13]" then it does not contain "key5" and your loop does not even run once. There are many other problems as well (such as the fact that you're only attempting to write one line back out, as another person mentioned in the comments, or that you're not reading any more lines inside your loop, among other issues). For these types of things, work out precisely what you want to do, then write code to match. It looks like you want to do the following:
Search for the line "[13]". Once found...
Search for a line starting with "key5=", but stop when a new section (starting with "[") is encountered. If that is found:
Replace that line with "key5=" + new value.
And for each line you touch that you do not replace, you'd have to write it back out (although a general formula here, barring memory constraints, is to parse/load, then modify, then write).
So you'll want your code to do that.
Also note that some INI file parser implementations (presuming you are treating this as an INI file) ignore whitespace and/or case in the key and section names, so depending on the source of your file, you may want to take that into account.
By the way, perhaps consider using an INI file handling library such as ini4j, where you can load the file and replace keys directly. See What is the easiest way to parse an INI file in Java?.
This part looks wrong:
while (line.contains("key5")) {
if (line.contains("key5"))
I assume that NOT operator is missing in loop condition
I'm writing a file reader that returns an object and I'd like it to warn on parse errors and continue to the next record.
The code below is the obvious implementation of this, but involves recursing from inside the catch block. Is there any technical or stylistic reason not to do this?
public RecordType nextRecord() throws IOException{
if (reader == null){
throw new IllegalStateException("Reader closed.");
}
String line = reader.readLine();
if (line == null){
return null;
}else{
try {
return parseRecord(line);
}catch (ParseException pex){
logger.warn("Record ignored due to parse error: "
+ pex.getMessage());
//Note the recursion here
return nextRecord();
}
}
}
I would prefer to use a loop. With recursion, you never know how deep you can safely go.
String line;
while((line = reader.readLine()) != null) {
try {
return parseRecord(line);
}catch (ParseException pex){
logger.warn("Record ignored due to parse error: " + pex);
}
}
return null;
Why not replace the recursion with a loop:
public RecordType nextRecord() throws IOException {
if (reader == null) {
throw new IllegalStateException("Reader closed.");
}
for (;;) {
String line = reader.readLine();
if (line == null) {
return null;
} else {
try {
return parseRecord(line);
} catch (ParseException pex) {
logger.warn("Record ignored due to parse error: "
+ pex.getMessage());
// continue to the next record
}
}
}
}
Stylistically, I find this preferable.
Would it be cleaner to let the ParseException propagate back to the caller? The caller could then decide what to do about it.
What it seems like to me is that whatever is calling your method is going to keep calling it until the method returns null.
I would probably follow the advice of the previous posters and use a loop, however I would look at whatever is calling the method (as it is probably already using a loop), have it skip the line by looking for an exception to be thrown.