views:

495

answers:

7

hey all,

i'm trying to get Color information that i've stored in a text file and then use that color as the forecolor for a label. BUT, at run time when i click the button to do it, it doesnt give me any error messages or anything. the code i have is below:

MatchCollection lines = Regex.Matches(File.ReadAllText(Path), @"(.+?)\r\n""([^""]+)""\r\n(\d+),\s(\d+)\r\n([\w\s]*)\r\n(\d+\.\d+)""\r\n(\d+?)");
        foreach (Match match in lines)
            int color = Int32.Parse(match.Groups[5].Value);

I have other regex for other info inn files too, but the other regex isnt the problem. the problem is the regex that i have just added to try and match a color (argb). it's at the end of the string:

\r\n(\d+?)

So as far as I understand it, the above little regex thing means this: "Find a carriagereturn and newline, and then 1 or more digits but dont be greedy". is that right?

can somebody please help me with this. thank you very much.

Note: The color info that is saved in the text file is a negative number (ARGB color):

-16744193

The file contents is like this:

Control
Control Text
Control Location
Control Font Name
Control Font Size
Control Font Color

Explanation:

Label
"this is a label"
23, 77
Tahoma
14.0
-55794414

So, the regex works, it gets all the other details correctly but it just doesnt get the color information.

A: 

You have only 4 groups in your regular expressions, but you are trying to access groups 5 to 8 which will be empty strings, and an empty string cannot be parsed as an integer by Int32.Parse.

Julien Lebosquain
+1  A: 

I'd set a breakpoint on the line with the error and see what match.Groups[5].Value really is.

I'm betting it can't be converted to an int.

Jay Riggs
i've tried double float string i've even tried coffee and nothing converts to anything on that line :(
baeltazor
+7  A: 

- is not matched by \d. Also, if you do a non-greedy match on \d+ only the first digit will be captured since that satisfies the regexp. Change your regexp into (-?\d+) to match an optional - at the start of your number and as many digits as there are in the number, up to (but not including) the character following the number (newline, end-of-string, ...).

Wim
thank you @Wim. i have updated it, but with No luck. the regex i have now is:@"(.+?)\r\n""([^""]+)""\r\n(\d+),\s(\d+)\r\n([\w\s]*)\r\n(\d+\.\d+)""\r\n(-?\d+)" --- and the code i have to convert it to system.drawing.color is:int fcolor = Int32.Parse(match.Groups[7].Value); int F_Color = Convert.ToInt32(fcolor); Color ControlForeColor = Color.FromArgb(fcolor);
baeltazor
And you have "" before the last \r\n, try this: --> (.+)\r\n""([^""]+)""\r\n(\d+),\s(\d+)\r\n([\w\s]*)\r\n(\d+\.\d+)\r\n(-?\d+) <-- the result is in group 7 btw ;)
Stormenet
thank you for helping @Stormenet, but it still doesn't want to work :( any ideas?
baeltazor
+5  A: 

Try this regex and see if it works.

(.+?)\r\n""([^""]+)""\r\n(\d+),\s(\d+)\r\n([\w\s]*)\r\n(\d+.\d+)\r\n(-?\d+)

Your regex appeared to be looking for the " after the font size value.

Also, your ARGB colour will be in group match 7, not 5.

WDuffy
@baeltazor I've tested this code in RegexBuddy and it matches your sample with matches for each Group as expected.
WDuffy
A: 

You can use this regex:

@"(.+)\r\n""([^""]+)""\r\n(\d+),\s(\d+)\r\n([\w\s]*)\r\n(\d+\.\d+)\r\n(-?\d+)"

A usage example from which it can be seen that it works:

string value = @"Label
""this is a label""
23, 77
Tahoma
14.0
-55794414
Label
""this is a label""
23, 77
Tahoma
14.0
-55794415";

MatchCollection lines = Regex.Matches(
 value,
 @"(.+)\r\n""([^""]+)""\r\n(\d+),\s(\d+)\r\n([\w\s]*)\r\n(\d+\.\d+)\r\n(-?\d+)");
var colors = new List<int>();
foreach (Match match in lines)
{
    colors.Add(Int32.Parse(match.Groups[7].Value));
}

CollectionAssert.AreEquivalent(new[] { -55794414, -55794415}, colors);

In this example we have 2 labels with different colors, as can be seen the regex matches the colors.

The groups of the regex:

  • 0: Control
  • 1: Text
  • 2: X
  • 3: Y
  • 4: Font
  • 6: Size
  • 7: Color
Elisha
+1  A: 

Your regex is not the problem. Your regex as well as the one given by Wim works fine. So the problem has to be with the way the input is being handled.

Here are some things you can try:

Run this with different input, i.e. instead of using this number:

-16744193

Use something like this instead:

100
-100

Then print out the value after this line:

int fcolor = Int32.Parse(match.Groups[7].Value);

And see what it is.

Another time-saving thing you should do is print out the values in

match.Groups[1].Value
match.Groups[2].Value
match.Groups[3].Value
match.Groups[4].Value
match.Groups[5].Value
match.Groups[6].Value
match.Groups[7].Value
match.Groups[8].Value

And post them here. This will make it easy for you as well as every at SO to see what the problem is.

Goose Bumper
thank you aditya
baeltazor
No problem! Glad I helped.
Goose Bumper
+1  A: 

Printing out the match values as suggested elsewhere would be a help, as well as shortening the regexp to make it easier to isolate the problem.

But I can suggest one more thing. Here's the last part of the regexp starting from the font size match:

..."(\d+\.\d+)\r\n(-?\d+)"

Which is supposed to match against

...
14.0
-55794414

Since you have the match for the newline immediately after the match for the font size digits, the match will fail if you have a space after 14.0. Try with

..."(\d+\.\d+)\s*\r\n(-?\d+)"

which should work both with and without trailing spaces. (Depending on your regexp engine, just "\s*" may be better than "\s*\r\n".)

There are actually a whole bunch of other things that could go wrong. It is generally easier to split up the strings and work with smaller regexps.

I suppose you already know the quote?

Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.

j-g-faustus
thank you for the detailed answer. Personally, I've never liked Regex. But I was advised by a few people on S/O to use them. I'm trying out your advice now. Thank you :)
baeltazor
I like regexps, they are convenient in that you can replace a page of programming with a single line. Of course, then you get one page's worth of potential bugs as well :)In practice, I have given up on regexps the size of yours, I spend too much time debugging them. In your case I would split on lines first, and have one regexp per value; it becomes more tractable that way.Good luck :)
j-g-faustus