Java - second last occurrence of char in string - java

Suppose I've the string
String path = "the/quick/brown/fox/jumped/over/the/lazy/dog/";
I would like the following output
String output = "the/quick/brown/fox/jumped/over/the/lazy/";
I was thinking the following would do
output = path.substring(0, path.lastIndexOf("/", 1));
given how the doc says
Returns the index of the first (last) occurrence of the specified character, searching forward (backward) from the specified index.
but that doesn't seem to work.
Any help would be appreciated.

It seems like every single answer is assuming that you already know the input string and the exact position of the last occurrence of "/" in it, when that is usually not the case...
Here's a more general method to obtain the nth-last (second-last, third-last, etc.) occurrence of a character inside a string:
static int nthLastIndexOf(int nth, String ch, String string) {
if (nth <= 0) return string.length();
return nthLastIndexOf(--nth, ch, string.substring(0, string.lastIndexOf(ch)));
}
Usage:
String s = "the/quick/brown/fox/jumped/over/the/lazy/dog/";
System.out.println(s.substring(0, nthLastIndexOf(2, "/", s)+1)); // substring up to 2nd last included
System.out.println(s.substring(0, nthLastIndexOf(3, "/", s)+1)); // up to 3rd last inc.
System.out.println(s.substring(0, nthLastIndexOf(7, "/", s)+1)); // 7th last inc.
System.out.println(s.substring(0, nthLastIndexOf(2, "/", s))); // 2nd last, char itself excluded
Output:
the/quick/brown/fox/jumped/over/the/lazy/
the/quick/brown/fox/jumped/over/the/
the/quick/brown/
the/quick/brown/fox/jumped/over/the/lazy

This works, given path length >2
final String path = "the/quick/brown/fox/jumped/over/the/lazy/dog/";
final int secondLast = path.length()-2;
final String output = path.substring(0, path.lastIndexOf("/",secondLast)+1);
System.out.println(output);

The lastIndexOf method's second parameter specifies the maximum index upto where the method should search the string. This means, that in your case
path.lastIndexOf("/", 1)
returns the first index of "/" whose index is smaller than 1.

First of all, lastIndexOf will return an index, not a string. It also searches backwards from the specified index 1, so it will only look at everything before and including the character at index 1. This means that it only checks t and h. Expectedly, it finds nothing and returns -1.
You should just omit the second argument if you want to search the whole string.
In addition, to achieve your desired output string (I assume you want the last path component removed?), you can use replaceAll with a regex:
String output = path.replaceAll("[^/]+/$", "");

Using Apache Commons IO
String output = org.apache.commons.io.FilenameUtils.getPath(path);
Not using Apache
public static String removeLastPart(String str) {
int pos = str.length() - 1;
while (str.charAt(pos) != '/' || pos + 1 == str.length()) {
pos--;
}
return str.substring(0, pos + 1);
}

If you are dealing with paths and files why not use the built in classes? Something like below seems to me easier than string manipulation:
Path path = Paths.get("the/quick/brown/fox/jumped/over/the/lazy/dog/");
System.out.println(path.getParent());
// prints: the\quick\brown\fox\jumped\over\the\lazy
System.out.println(path.getParent().getParent());
// prints: the\quick\brown\fox\jumped\over\the

For example,
String key = "aaa/bbb/ccc/ddd" ;
and i need my result string as "ccc/ddd". which is, sub-string of second last index of "/", The following code helps ::
String key="aaa/bbb/ccc/ddd";
key=key.substring(key.substring(0, key.lastIndexOf("/")).lastIndexOf("/")+1);
The final value of key will be "ccc/ddd".

Here's an use case:
String url = "http://localhost:4000/app/getPTVars";
int secondLastIndexOf = url.substring(0, url.lastIndexOf('/')).lastIndexOf('/');
System.out.println(secondLastIndexOf);
System.out.println(url.substring(secondLastIndexOf, url.length()));
and the output:
21
/app/getPTVars

Try - 1 approach:
int j = path.lastIndexOf("/");
int i = path.lastIndexOf("/", j - 1); // the 2nd last index from the last index
String output = path.substring(0, i + 1); // inclusive

String path = "the/quick/brown/fox/jumped/over/the/lazy/dog/";
String output = path.substring(0, path.lastIndexOf("/",path.lastIndexOf("/")-1)+1);

Related

StringIndexOutOfBoundsException when trying to get string from long string

I tried to get string from long string which is Firebase URL
"https://firebasestorage.googleapis.com/v0/b/No-manworld-3577.appspot.com/o/Contacts%2F1510361061636_Julien_Vcf?alt=media&token=c0bff20d-d115-4fef-b58c-4c7ffaef4296"
Now if you notice there is under score before and after name Julien in above string. I am trying to get that name but i am getting
java.lang.StringIndexOutOfBoundsException: String index out of range: -1
Here is my piece of code
String s="https://firebasestorage.googleapis.com/v0/b/No-manworld-3577.appspot.com/o/Contacts%2F1510361061636_Julien_Vcf?alt=media&token=c0bff20d-d115-4fef-b58c-4c7ffaef4296";
String newName=s.substring(s.indexOf("_")+1, s.indexOf("_"));
System.out.println(newName);
As said in my comment, when using substring, the first number has to be smaller than the second one.
In your case, you are calling substring with x + 1 and x. x + 1 > x thus substring fails, with x being s.indexOf("_").
I understand that you are trying to get the second indexOf of _.
Here is code that would in your case yield Julien:
String s = "...";
int start = s.indexOf("_") + 1;
int end = s.indexOf("_", start);
// name will hold the content of s between the first two `_`s, assuming they exist.
String name = s.substring(start, end);
If requirements are not clear on which 2 _ to select then here is Java 8 Stream way of doing it ..
public class Check {
public static void main(String[] args) {
String s = "https://firebasestorage.googleapis.com/v0/b/No-manworld-3577.appspot.com/o/Contacts%2F1510361061636_Julien_Vcf?alt=media&token=c0bff20d-d115-4fef-b58c-4c7ffaef4296";
long count = s.chars().filter(ch -> ch == '_').count();
if (count == 2) {
System.out.println(s.substring(s.indexOf('_') + 1, s.lastIndexOf('_')));
} else {
System.out.println("More than 2 underscores");
}
}
}
Why your code didn't work?
Let assume s.indexOf("_") gets some positive number say 10 then below translates to ...
String newName=s.substring(s.indexOf("_")+1, s.indexOf("_"));
String newName=s.substring(11, 10);
This will give StringIndexOutOfBoundsException as endIndex < beginIndex for subString method.

How to get real end index of string found in another string

I am trying to get a range of chars found in another string using Java:
String input = "test test2 Test3";
String substring = "test2";
int diffStart = StringUtils.indexOf(input, substring);
int diffEnd = StringUtils.lastIndexOf(input, substring);
I want to get
diffStart = 5
diffEnd = 10
But I am getting
diffStart = 5
diffEnd = 5
Based on Apache's Commons lastIndexOf function it should work:
public static int lastIndexOf(CharSequence seq,
CharSequence searchSeq)
Finds the last index within a CharSequence, handling null. This method
uses String.lastIndexOf(String) if possible.
StringUtils.lastIndexOf("aabaabaa", "ab") = 4
What am I doing wrong?
you probably want
diffStart = String.valueOf(StringUtils.indexOf(strInputString02, strOutputDiff));
diffEnd = diffStart + strOutputDiff.length();
lastIndexOf finds the matching string, but the last instance of it.
E.g. ab1 ab2 ab3 ab4
lastindexof("ab") finds the 4th ab
indexof("ab") finds the 1st ab (position 0)
However, they always return the location of the first character.
If there is only one instance of a substring lastindexof and indexof will give the same index.
(To enhance your example more, you may also want to do some -1 checks in case the substring is not there at all)

How to escape special characters from JSON when assign it to Java String

im tring to assign value from json to java String. but JSON value is including some special charactor ("\"). when i was try to assigen it to the string it gives error.
this is the JSON value,
"ValueDate":"\/Date(1440959400000+0530)\/"
this is how i trying to use it.
HistoryVO.setValueDate(DataUtil.getDateForUnixDate(historyJson.getString("ValueDate")));
or
Given that
I want ... to get [the] Date(1440959400000+0530) part,
I would use
String value = "/Date(1440959400000+0530)/";
int pos1 = value.indexOf("Date(");
if (pos1 > -1) {
int pos2 = value.indexOf(")", pos1);
if (pos2 > pos1) {
value = value.substring(pos1, pos2 + 1);
System.out.println(value);
}
}
Output is
Date(1440959400000+0530)
Note: This works by looking for "Date(" and then the next ")", and it removes everything not between those two patterns.
If you have specific character, ( and ), use substring method to get the value.
String value = "\\/Date(1440959400000+0530)\\/";
int start = value.indexOf("(");
int last = value.lastIndexOf("0");
value = value.substring(start + 1, last + 1);
System.out.println(value); <--- 1440959400000+0530
DataUtil.getDateForUnixDate(value);
I don't know DataUtil.getDateForUnixDate() method, but take care of + character because of it is not number string.
Update
To remove / character use replace method.
String value = "/Date(1440959400000+0530)/";
value = value.replace("/", "");
System.out.println(value);
output
Date(1440959400000+0530)
Mac,
As you asked for something like
String ValueDate = "\/Date(1440959400000+0530)\/";
The above one is not possible in java string, As it shows as invalid escape sequence, So replace the slash '\' as double slash '\' as below,
String ValueDate = "\\/Date(1440959400000+0530)\\/";
If am not clear of our question, pls describe it clearly
Regards,
Hari
i found the answer for my own question.
historyJson.getString("ValueDate");
this return the String like /Date(1440959400000+0530)/
now i can split it. thank you all for the help.
regards, macdaddy

How to replace a single char at an index by a string?

I have a String "speed,7,red,fast". I want to replace the 7 by a String "Seven". How do I do that ?
More details -
7 can be replaced by ANY string and not just "Seven". It could also be "SevenIsHeaven".
I don't want to replace all occurrences of 7. Only 7 at the specified index, ie use the index of 7 to replace 7 by some string.
replaceAll("7", "Seven") //simple as that
EDIT
Then you should look for the specified index.
String input = "test 7 speed,7,red,fast yup 7 tr";
int indexInteresdIn = 13;
if(input.charAt(indexInteresdIn) == '7'){
StringBuilder builder = new StringBuilder(input);
builder.replace(indexInteresdIn, indexInteresdIn+1, "Seven");
System.out.println(builder.toString());
}
Because String is immutable you should use StringBuilder for better performance.
http://docs.oracle.com/javase/7/docs/api/java/lang/StringBuilder.html
yourStringBuiler.replace(
yourStringBuiler.indexOf(oldString),
yourStringBuiler.indexOf(oldString) + oldString.length(),
newString);`
If you want to replace a whole String like the String.replaceAll() does you could create an own function like this:
public static void replaceAll(StringBuilder builder, String from, String to)
{
int index = builder.indexOf(from);
while (index != -1)
{
builder.replace(index, index + from.length(), to);
index += to.length(); // Move to the end of the replacement
index = builder.indexOf(from, index);
}
}
Source:
Replace all occurrences of a String using StringBuilder?
However if you doesn't need it frequently and performance is not that important a simple String.replaceAll() will do the trick, too.
How about simply like below ?
String str = "speed,7,red,fast";
str = str.replace("7", "Seven");
7 can be replaced by ANY string and not just "Seven". It could also be
"SevenIsHeaven". I don't want to replace all occurrences of 7. Only 7
at the specified index.
Or if you wanna use regex to replace the first numeric to a meaningful String.
String str = "speed,7,red,fast";
str = str.replaceFirst("\\d", "Seven");
better way is to store the string itself in an array, spiting it at a space.
String s[];
static int index;
s = in.readLine().spilt(" ");
Now scan the array for the specified word, at the specified index and replace that with the String you desire.
for(int i =0;i<s.length; i++)
{
if((s[i] == "7")&&(i==index))
{
s[i]= "Seven";
}
}

Split by first found String in Java

is ist possible to tell String.split("(") function that it has to split only by the first found string "("?
Example:
String test = "A*B(A+B)+A*(A+B)";
test.split("(") should result to ["A*B" ,"A+B)+A*(A+B)"]
test.split(")") should result to ["A*B(A+B" ,"+A*(A+B)"]
Yes, absolutely:
test.split("\\(", 2);
As the documentation for String.split(String,int) explains:
The limit parameter controls the number of times the
pattern is applied and therefore affects the length of the resulting
array. If the limit n is greater than zero then the pattern
will be applied at most n - 1 times, the array's
length will be no greater than n, and the array's last entry
will contain all input beyond the last matched delimiter.
test.split("\\(",2);
See javadoc for more info
EDIT: Escaped bracket, as per #Pedro's comment below.
Try with this solution, it's generic, faster and simpler than using a regular expression:
public static String[] splitOnFirst(String str, char c) {
int idx = str.indexOf(c);
String head = str.substring(0, idx);
String tail = str.substring(idx + 1);
return new String[] { head, tail} ;
}
Test it like this:
String test = "A*B(A+B)+A*(A+B)";
System.out.println(Arrays.toString(splitOnFirst(test, '(')));
System.out.println(Arrays.toString(splitOnFirst(test, ')')));

Categories