-1
[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) {
            //
         }
      }
Code Hungry
  • 3,930
  • 22
  • 67
  • 95
  • And what is the problem? What output are you seeing and how does it differ from what you are expecting? – Jason C Oct 28 '13 at 09:36
  • By the way, you may wish to check out something like http://ini4j.sourceforge.net/, although it will be helpful in general for you to brush up on your logic skills first (and I still recommend fixing your code, if only for the learning experience). – Jason C Oct 28 '13 at 09:49

3 Answers3

2

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
}
NickJ
  • 9,380
  • 9
  • 51
  • 74
  • You don't *have* to store the state in a flag, you *could* do it with nested or successive loops like the OP is trying to do. A flag will lead to clearer and more flexible code, however. By the way, you'd want `.equals("[13]")` and `.startsWith("key5=")` (and optionally case- and whitespace-insensitive in both, INI parser implementations vary on these details). – Jason C Oct 28 '13 at 09:56
  • No, I really did mean line.startsWith("[") in order to clear the flag when encountering [14] etc. The problem with not using the flag is that when line[13] is encountered, it will enter the if block, but then never enter the while block because key5 is on a separate line. By the time it gets to key5, the if block will be skipped because the line won't have [13] on it. [13] and key5 are on 2 separate lines. – NickJ Oct 28 '13 at 10:02
  • 1
    I was unclear; that's not the line I was pointing out. As it stands, your code would see e.g. "key=[13]" as the start of the section and "key1=somekey5" or "key50=whatever" as the line to replace. What I meant was: your `.contains("[13]")` should be `.equals("[13]")` and your `.contains("key5")` should be `.startsWith("key5=")`. Your `.startsWith("[")` is correct. Sorry about that. – Jason C Oct 28 '13 at 10:07
  • 1
    Yes, that's fair. I will edit accordingly. – NickJ Oct 28 '13 at 10:08
  • Thanks Jason C and NickJ your comments helped me. – Code Hungry Oct 28 '13 at 10:19
1

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:

  1. Search for the line "[13]". Once found...
  2. Search for a line starting with "key5=", but stop when a new section (starting with "[") is encountered. If that is found:
  3. 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?.

Community
  • 1
  • 1
Jason C
  • 38,729
  • 14
  • 126
  • 182
  • There's no point in having a while and and if with the same condition. Also, if there was a line with BOTH [13] and key5 (which there isn't), the while loop would never exit. – NickJ Oct 28 '13 at 10:07
  • I agree, of course. The code I posted was a snippet from the OP's code, unedited, meant to draw attention to the bit I was talking about. It is not my own proposal for a change. – Jason C Oct 28 '13 at 10:10
  • I misunderstood, Sorry about that. Downvote removed. +1 – NickJ Oct 28 '13 at 10:13
0

This part looks wrong:

while (line.contains("key5")) {
    if (line.contains("key5"))

I assume that NOT operator is missing in loop condition

Leos Literak
  • 8,805
  • 19
  • 81
  • 156