Substring index and length must refer to a location within the string - c#

I have a string that looks like
string url = "www.example.com/aaa/bbb.jpg";
"www.example.com/" is 18 fixed in length. I want to get the "aaa/bbb" part from this string (The actual url is not example nor aaa/bbb though, the length may vary)
so here's what I did:
string newString = url.Substring(18, url.Length - 4);
Then I got the exception: index and length must refer to a location within the string. What's wrong with my code and how to fix it?

The second parameter in Substring is the length of the substring, not the end index (in other words, it's not the length of the full string).
You should probably include handling to check that it does indeed start with what you expect, end with what you expect, and is at least as long as you expect. And then if it doesn't match, you can either do something else or throw a meaningful error.
Here's some example code that validates that url contains your strings, that also is refactored a bit to make it easier to change the prefix/suffix to strip:
var prefix = "www.example.com/";
var suffix = ".jpg";
string url = "www.example.com/aaa/bbb.jpg";
if (url.StartsWith(prefix) && url.EndsWith(suffix) && url.Length >= (prefix.Length + suffix.Length))
{
string newString = url.Substring(prefix.Length, url.Length - prefix.Length - suffix.Length);
Console.WriteLine(newString);
}
else
//handle invalid state

Your mistake is the parameters to Substring. The first parameter should be the start index and the second should be the length or offset from the startindex.
string newString = url.Substring(18, 7);
If the length of the substring can vary you need to calculate the length.
Something in the direction of (url.Length - 18) - 4 (or url.Length - 22)
In the end it will look something like this
string newString = url.Substring(18, url.Length - 22);

How about something like this :
string url = "http://www.example.com/aaa/bbb.jpg";
Uri uri = new Uri(url);
string path_Query = uri.PathAndQuery;
string extension = Path.GetExtension(path_Query);
path_Query = path_Query.Replace(extension, string.Empty);// This will remove extension

You need to find the position of the first /, and then calculate the portion you want:
string url = "www.example.com/aaa/bbb.jpg";
int Idx = url.IndexOf("/");
string yourValue = url.Substring(Idx + 1, url.Length - Idx - 4);

Try This:
int positionOfJPG=url.IndexOf(".jpg");
string newString = url.Substring(18, url.Length - positionOfJPG);

string newString = url.Substring(18, (url.LastIndexOf(".") - 18))

Here is another suggestion. If you can prepend http:// to your url string you can do this
string path = "http://www.example.com/aaa/bbb.jpg";
Uri uri = new Uri(path);
string expectedString =
uri.PathAndQuery.Remove(uri.PathAndQuery.LastIndexOf("."));

You need to check your statement like this :
string url = "www.example.com/aaa/bbb.jpg";
string lenght = url.Lenght-4;
if(url.Lenght > 15)//eg 15
{
string newString = url.Substring(18, lenght);
}

Can you try this ?
string example = url.Substring(0,(url.Length > 18 ? url.Length - 4 : url.Length))

Related

Get Substring from Url

I have some Urls string, such as:
http://www.testproject.com/tokyo/4
http://www.testproject.com/india/11
http://www.testproject.com/singapore/819
How to get the number ("4". "11", "819") in the end of Url?
The other answers using string methods would be correct if this was a simple string, but since this is a URL, you should use the proper class to handle URIs:
var url = new Uri("http://www.testproject.com/tokyo/4");
var lastSegment = url.Segments.Last();
Without using regex, you can find the index of last "/" by using string.LastIndexOf('/') and get the rest by using string.SubString
Example of what AD.Net meant:
public string getLastBit(string s) {
int pos = s.LastIndexOf('/') + 1;
return s.Substring(pos, s.Length - pos);
}
Returns:
4, 11, 819
When passed in an individual url.
string myUrl = "http://www.testproject.com/tokyo/4";
string[] parts = myUrl.Split('/');
string itIsFour = parts[parts.Length-1];
int LastFwdSlash = URLString.LastIndexOf('/');
String Number = URLString.Substring(LastFwdSlash + 1, URLString.Length);
int Number = int.Parse(URLString);

Split a filename in 2 groups

I am making an application which "Filewatches" a folder and when a file is created in there it will automatically be mailed to the customer.
The problem is that i haven't found any information on how to split filenames
For example i have a file called : "Q1040500005.xls"
I need the first 5 characters seperated from the last 5, so basically split it in half (without the extension ofcourse)
And my application has to recognize the "Q1040" and the "500005" as seperate strings.
Which will be recognized in the database which contains The query number (Q1040) and the customer number "500005" the email of the customer and the subject of the queryfile.
How can i do this the easiest way?
Thanks for the help!
Use SubString method http://msdn.microsoft.com/es-es/library/aka44szs(v=vs.80).aspx
int lengthFilename = filename.Length - 4; //substract the string ".xls";
int middleLength = lengthFilename/2;
String filenameA = filename.SubString(0, middleLength);
String filenameB = filename.SubString(middleLength, lengthFilename - middleLength);
Is string.Substring method what you're looking for?
Use String.SubString(int startindex, int length)
String filename = Q1040500005.xls
var queryNumber = filename.Substring(0, 5); //Q1040
var customerNumber = filename.Substring(5, 6); //500005
This assumes your strings are a constant length.
Hope this helps.
You can use string.SubString() here
string a = fileName.SubString(0, 5); // "Q1040"
string b = fileName.SubString(5, 5); // "50000" <- Are you sure you didn't mean "last 6"?
string b2 = fileName.SubString(5, 6); // "500005"
This only works, if both strings have a constant fixed length
Edit:
If on the other hand, both strings can have variable length, I'd recommend you use a separator to divide them ("Q1040-500005.xml"), then use string.Split()
string[] separatedStrings = fileName.Split(new char[] { '-', '.' });
string a = separated[0]; // "Q1040"
string b = separated[1]; // "500005"
string extension = separated[2]; // "xls"

How to extract string at a certain character that is repeated within string?

How can I get "MyLibrary.Resources.Images.Properties" and "Condo.gif" from a "MyLibrary.Resources.Images.Properties.Condo.gif" string.
I also need it to be able to handle something like "MyLibrary.Resources.Images.Properties.legend.House.gif" and return "House.gif" and "MyLibrary.Resources.Images.Properties.legend".
IndexOf LastIndexOf wouldn't work because I need the second to last '.' character.
Thanks in advance!
UPDATE
Thanks for the answers so far but I really need it to be able to handle different namespaces. So really what I'm asking is how to I split on the second to last character in a string?
You can use LINQ to do something like this:
string target = "MyLibrary.Resources.Images.Properties.legend.House.gif";
var elements = target.Split('.');
const int NumberOfFileNameElements = 2;
string fileName = string.Join(
".",
elements.Skip(elements.Length - NumberOfFileNameElements));
string path = string.Join(
".",
elements.Take(elements.Length - NumberOfFileNameElements));
This assumes that the file name part only contains a single . character, so to get it you skip the number of remaining elements.
You can either use a Regex or String.Split with '.' as the separator and return the second-to-last + '.' + last pieces.
You can look for IndexOf("MyLibrary.Resources.Images.Properties."), add that to MyLibrary.Resources.Images.Properties.".Length and then .Substring(..) from that position
If you know exactly what you're looking for, and it's trailing, you could use string.endswith. Something like
if("MyLibrary.Resources.Images.Properties.Condo.gif".EndsWith("Condo.gif"))
If that's not the case check out regular expressions. Then you could do something like
if(Regex.IsMatch("Condo.gif"))
Or a more generic way: split the string on '.' then grab the last two items in the array.
string input = "MyLibrary.Resources.Images.Properties.legend.House.gif";
//if string isn't already validated, make sure there are at least two
//periods here or you'll error out later on.
int index = input.LastIndexOf('.', input.LastIndexOf('.') - 1);
string first = input.Substring(0, index);
string second = input.Substring(index + 1);
Try splitting the string into an array, by separating it by each '.' character.
You will then have something like:
{"MyLibrary", "Resources", "Images", "Properties", "legend", "House", "gif"}
You can then take the last two elements.
Just break down and do it in a char loop:
int NthLastIndexOf(string str, char ch, int n)
{
if (n <= 0) throw new ArgumentException();
for (int idx = str.Length - 1; idx >= 0; --idx)
if (str[idx] == ch && --n == 0)
return idx;
return -1;
}
This is less expensive than trying to coax it using string splitting methods and isn't a whole lot of code.
string s = "1.2.3.4.5";
int idx = NthLastIndexOf(s, '.', 3);
string a = s.Substring(0, idx); // "1.2"
string b = s.Substring(idx + 1); // "3.4.5"

how to place - in a string

I have a string "8329874566".
I want to place - in the string like this "832-98-4566"
Which string function can I use?
I would have done something like this..
string value = "8329874566";
value = value.Insert(6, "-").Insert(3, "-");
You convert it to a number and then format the string.
What I like most about this is it's easier to read/understand what's going on then using a few substring methods.
string str = "832984566";
string val = long.Parse(str).ToString("###-##-####");
There may be a tricky-almost-unreadable regex solution, but this one is pretty readable, and easy.
The first parameter of the .Substring() method is where you start getting the characters, and the second is the number of characters you want to get, and not giving it sets a default as value.length -1 (get chars until the end of the string):
String value = "8329874566";
String Result = value.Substring(0,3) + "-" + value.Substring(3,2) + "-" + value.Substring(6);
--[edit]--
Just noticed you didn't use one of the numbers AT ALL (number '7') in the expected result example you gave, but if you want it, just change the last substring as "5", and if you want the '7' but don't want 5 numbers in the last set, let it like "5,4".
Are you trying to do this like American Social Security numbers? I.e., with a hyphen after the third and and fifth numerals? If so:
string s = "8329874566";
string t = String.Format("{0}-{1}-{2}", s.Substring(0, 3), s.Substring(3, 2), s.Substring(5));
Just out of completeness, a regular expression variant:
Regex.Replace(s, #"(\d{3})(\d{2})(\d{4})", "$1-$2-$3");
I consider the Insert variant to be the cleanest, though.
This works fine, and I think that is more clear:
String value = "8329874566";
value = value.Insert(3, "-").Insert(6, "-");
The console outputs shows this:
832-98-74566
If the hyphens are to go in the same place each time, then you could simply concatenate together the pieces of the orginal string like this:
// 0123456789 <- index
string number = "8329874566";
string new = number.Substring(0, 3) + "-" + number.Substring(3, 2) + "-" + number.Substring(5);
For a general way of making mutable strings, use the StringBuilder class. This allows deletions and insertions to be made before calling ToString to produce the final string.
You could try the following:
string strNumber = "8329874566"
string strNewNumber = strNumber.Substring(0,3) + "-" + strNumber.Substring(4,2) + "-" strNumber.Substring(6)
or something in this manner
string val = "832984566";
string result = String.Format("{0}-{1}-{2}", val.Substring(0,3), val.Substring(3,2), val.Substring(5,4));
var result = string.Concat(value.Substring(0,3), "-", value.Substring(3,2), "-", value.Substring(5,4));
or
var value = "8329874566".Insert(3, "-").Insert(6, "-");
Now how about this for a general solution?
// uglified code to fit within horizontal limits
public static string InsertAtIndices
(this string original, string insertion, params int[] insertionPoints) {
var mutable = new StringBuilder(original);
var validInsertionPoints = insertionPoints
.Distinct()
.Where(i => i >= 0 && i < original.Length)
.OrderByDescending(i => i);
foreach (int insertionPoint in validInsertionPoints)
mutable.Insert(insertionPoint, insertion);
return mutable.ToString();
}
Usage:
string ssn = "832984566".InsertAtIndices("-", 3, 5);
string crazy = "42387542342309856340924803"
.InsertAtIndices(":", 1, 2, 3, 4, 5, 6, 17, 200, -1, -1, 2, 3, 3, 4);
Console.WriteLine(ssn);
Console.WriteLine(crazy);
Output:
832-98-4566
4:2:3:8:7:5:42342309856:340924803
Overkill? Yeah, maybe...
P.S. Yes, I am regex illiterate--something I hope to rectify someday.
A straightforward (but not flexible) approach would be looping over the characters of the string while keeping a counter running. You can then construct a new string character by character. You can add the '-' character after the 3rd and 5th character.
A better approach may be to use a function to insert a single character in the middle of the string at a specific index. String.Insert() would do well. The only thing to pay attention to here is that the string indexes will get off by one with each insert.
EDIT more language-specific as per comments

C# Using Substring, how do I extract this string?

I want to extract the first folder in the URL below, in this example it is called 'extractThisFolderName' but the folder could have any name and be any length. With this in mind how can I use substring to extract the first folder name?
The string: www.somewebsite.com/extractThisFolderName/leave/this/behind
String folderName = path.Substring(path.IndexOf(#"/"),XXXXXXXXXXX);
It's the length I'm struggling with.
If you're getting a Uri, why not just do uri.Segments[0]?
Or even path.Split(new Char[] { '/' })[1] ?
If you're going to be using each path part, you can use:
String[] parts = path.Split('/');
At which point you can access the "extractThisFolderName" part by accessing parts[1].
Alternatively, you can do this to splice out the foldername:
int firstSlashIndex = path.IndexOf('/');
int secondSlashIndex = path.IndexOf('/', firstSlashIndex + 1);
String folderName = path.Substring(firstSlashIndex + 1, secondSlashIndex - firstSlashIndex);
Daniel's answer gives you other practical ways of doing it. Another alternative using substring:
int start = path.IndexOf('/')+1; // Note that you don't need a verbatim string literal
int secondSlash = path.IndexOf('/', start);
return path.Substring(start, secondSlash-start);
You'll want to add some error checking in there, of course :)
The problem also lends itself to regular expressions. An expression like:
(?<host>.*?)/(?<folder>.*?)/
Is clear about what's going on and you can get the data out by those names.
int start = path.IndexOf('/');
int end = path.IndexOf('/', start + 1);
if (end == -1) end = path.Length;
string folderName = path.Substring(start + 1, end - start - 1);
EDIT: Daniel Schaffer's answer about using uri segments is preferable, but left this in as it may be your path is not really a valid uri.
You could do:
string myStr = "www.somewebsite.com/extractThisFolderName/leave/this/behind";
int startIndex = myStr.IndexOf('/') + 1;
int length = myStr.IndexOf('/', startIndex) - startIndex;
Console.WriteLine(myStr.Substring(startIndex, length));
At the same point I assume this is being done in ASP.Net if so I think there might be another way to get this without doign the querying.
folderName.Split('/')[1]

Categories