3

I'm creating C# winforms app which has to find all occurences of a string within a file, crop the text in between, then do some processing.

The text file has following format:

---- Key_String ----

text to crop 1

---- Key_String ----

text to crop 2

---- Key_String ----

text to crop 3

Basically I'm croping "text1", "text2", "text3" from that file.

And here is the code to do the mentioned action:

string contents = "";
MatchCollection matches;
using (StreamReader reader = File.OpenText(filepath))
{
    contents = reader.ReadToEnd();
    matches = Regex.Matches(contents, "Key_String");
}
int totalmatchcount = matches.Count;

for (int i = 0; i < totalmatchcount; i++ )
{
    int indd1 = matches[i].Index;
    int indd2 = 0;
    string sub_content = "";
    if (i != totalmatchcount - 1)
    {
        indd2 = matches[i+1].Index;
        try
        {
            sub_content = contents.Substring(indd1, indd2); // error here
        }
        catch
        {
            MessageBox.Show("Index 1: "  + indd1 + "\n" +
                "Index 2: "  + indd2 + "\n" +
                "Max index (length - 1): "  + (contents.Length - 1)
                );
        }
    }
    else { sub_content = contents.Substring(indd1); }
    // do some stuff with "sub_content"
}

It works great for some of my files, however in some cases - I'm getting following error:

Index and length must refer to a location within the string. Parameter name: length

It is very strange, because the substring that I'm cropping is located INSIDE the main string, not outside as you have guessed. I can prove it with "try-catch" output:

Index 1: 3211

Index 2: 4557

Max index (length - 1): 5869

As you can see - I'm not cropping something that is located outside the index range, so what's the problem?

P.S. I've googled solutions but the basic idea in every case is - "wrong index". In my case - index is "inside" the range. Well, at least I think so.

Edit

Something similar to this should solve the problem:

 public string SubstringFix(string original, int start, int end)
    {
        int endindex = 0;
        if (end < original.Length)
        {
            endindex = end;
        }
        else
        {
            endindex = original.Length - 1;
        }

        return original.Substring(start, (end - start));
    }
halfer
  • 19,824
  • 17
  • 99
  • 186
Alex
  • 4,607
  • 9
  • 61
  • 99

2 Answers2

3

Substring does not take two indices. It takes one index and a length. Probably, you want

indd2 - indd1

as the second parameter (and check that expression for off-by-one errors).

usr
  • 168,620
  • 35
  • 240
  • 369
  • 1
    Ooops my bad ;( I've never expected to fail this much. Sorry for obviously stupid question.. and +1 to your rep. – Alex Aug 18 '12 at 14:17
  • @Alex Don't feel too bad. `Substring` implementations across languages tend to vary. I still occasionally have to stop myself when I make a `Substring` call to remember if it's length or EndIndex that I want. – Chris Sinclair Aug 18 '12 at 14:22
  • 1
    Just to add, _some_ languages seem to want to play psychological warfare with you and have both implementations but only slight ambiguous variations in the name. JavaScript for example: http://www.xpertdeveloper.com/2012/01/substr-vs-substring-javascript/ – Chris Sinclair Aug 18 '12 at 14:26
1

With what you have this is what you are getting

3211+4557 = 7768

and that is greater than the length of the string.

This is how substring works

substring(startindex, length)

Length of string should not be less than startIndex + length

codingbiz
  • 26,179
  • 8
  • 59
  • 96