Why is Java String indexOf failing? - java

this must be quite simple but I am having great difficulty. You see I am trying to find a string within another string as follows.
e = input.indexOf("-->");
s = input.indexOf("<!--");
input = input.replace(input.substring(s, e + 3), " ");
The integers e and s are returning -1 in that it was not found and this is causing the replace method to fail. The test string I am using is "Chartered Certified<!--lol--> Accountants (ACCA)". I tried to creat a new string object and pass in the string as an argument as follows
e=input.indexOf(new String("<!--"));
This yielded the same result.
Any ideas ?
This is a stand alone piece of code I wrote and it works perfectly.
public static void main(String[] args) {
int e = 0;
int s = 0;
while (e != -1) {
//input.replace("\"", "\'");
e = input.indexOf("-->");
s = input.indexOf("<!--");
input = input.replace(input.substring(s, e + 3), " ");
e = input.indexOf("-->");
System.out.println(input);
}
}
But I cannot seem to see why it fails when i use this logic in my action class.

System.out.println("!Chartered Certified<!--lol--> Accountants (ACCA)".indexOf("-->"));
prints 27
So your input string must not be what you expect

String input = "Chartered Certified<!--lol--> Accountants (ACCA)";
int e = input.indexOf("-->");
int s = input.indexOf("<!--");
System.out.println(e+" "+s);
yields
26 19
so I think that there's an error somewhere else, is there other code in the middle?

The string "Chartered Certified Accountants (ACCA)" does not contain "-->" or "<!--", so e and s will always be -1.

Maybe you are obtaining the string from a sort of xml parser and hides the commented string on rendering. Check that the input string just before the indexOf call really has the '<!--' and '-->' strings inside.

I ran the test real quick using a command-line argument. It worked just fine. Here's the code/results:
public static void main(String[] args) {
String input = args[0];
System.out.println(input);
int e = input.indexOf("-->");
int s = input.indexOf("<!--");
input = input.replace(input.substring(s, e + 3), "");
System.out.println(input);
}
Output:
Chartered Certified<!--lol--> Accountants (ACCA)
Chartered Certified Accountants (ACCA)
If you were passing input as a command-line argument, make sure it is in quotes, or else input will be set to Chartered because of the spaces.

This code should work, there is some other problem. You should code it for safety though as shown below.
e = input.indexOf("-->");
s = input.indexOf("<!--");
if (e > -1 && s > -1 && e > s + 4) {
input = input.replace(input.substring(s, e + "-->".length()), " ");
}

Your code seems OK. So if it fails. it may be that the string it parses is not what you think it is. Where does the string come from? Try printing the string just before parsing it to see what it actually is.

Related

How to print a substring with only the matching elements of a string?

Given a String that lists metadata about a book line by line, how do I print out only the lines that match the data I am looking for?
In order to do this, I've been trying to create substrings for each lines using indexes. The substring starts at the beginning of a line and ends before a "\n". I have not seen lists, arrays or bufferedReader yet.
For each substring that I parse through, I check if it contains my pattern. If it does, I add it to a string that only includes my results.
Here would be an example of my list (in french); I'd like to match, for say, all the books written in 2017.
Origine D. Brown 2017 Thriller Policier
Romance et de si belles fiancailles M. H. Clark 2018 thriller policier Romance
La fille du train P. Hawkins 2015 Policier
There is a flaw in how I am doing this and I am stuck with an IndexOutOfBounds exception that I can't figure out. Definitely new in creating algorithms like this.
public static String search() {
String list;
int indexLineStart = 0;
int indexLineEnd = list.indexOf("\n");
int indexFinal = list.length()-1;
String listToPrint = "";
while (indexLineStart <= indexFinal){
String listCheck = list.substring(indexLineStart, indexLineEnd);
if (listCheck.contains(dataToMatch)){
listToPrint = listToPrint + "\n" + listCheck;
}
indexLineStart = indexLineEnd +1 ;
indexLineEnd = list.indexOf("\n", indexLineStart);
}
return listeToPrint;
}
Regardless of the comments about using split() and String[], which do have merit :-)
The IndexOutOfBounds exception I believe is being caused by the second of these two lines:
indexLineStart = indexLineEnd +1 ;
indexLineEnd = list.indexOf("\n", indexLineStart);
You wan't them swapped around (I believe).
You don't have to make this much complex logic by using String.substring(), what you can use is String.split() and can make an array of your string. At each index is a book, then, you can search for you matching criteria, and add the book to the finalString if it matches your search.
Working Code:
public class stackString
{
public static void main(String[] args)
{
String list = "Origine D. Brown 2017 Thriller Policier\n Romance et de si belles fiancailles M. H. Clark 2018 thriller policier Romance\n La fille du train P. Hawkins 2015 Policier\n";
String[] listArray = list.split("\n"); // make a String Array on each index is new book
String finalString = ""; // final array to store the books that matches the search
String matchCondition = "2017";
for(int i =0; i<listArray.length;i++)
if(listArray[i].contains(matchCondition))
finalString += listArray[i]+"\n";
System.out.println(finalString);
}
}
Here is a solution using pattern matching
public static List<String> search(String input, String keyword)
{
Pattern pattern = Pattern.compile(".*" + keyword + ".*");
Matcher matcher = pattern.matcher(input);
List<String> linesContainingKeyword = new LinkedList<>();
while (matcher.find())
{
linesContainingKeyword.add(matcher.group());
}
return linesContainingKeyword;
}
Since I wasn't allowed to use lists and arrays, I got this to be functional this morning.
public static String linesWithPattern (String pattern){
String library;
library = library + "\n"; //Added and end of line at the end of the file to parse through it without problem.
String substring = "";
String substringWithPattern = "";
char endOfLine = '\n';
int nbrLines = countNbrLines(library, endOfLine); //Method to count number of '\n'
int lineStart = 0;
int lineEnd = 0;
for (int i = 0; i < nbrLines ; i++){
lineStart = lineEnd;
if (lineStart == 0){
lineEnd = library.indexOf('\n');
} else if (lineStart != 0){
lineEnd = library.indexOf('\n', (lineEnd + 1));
}
substring = library.substring(lineStart, lineEnd);
if (substring.toLowerCase().contains(motif.toLowerCase())){
substringWithPattern = substring + substringWithPattern + '\n';
}
if (!library.toLowerCase().contains(pattern.toLowerCase())){
substringWithPattern = "\nNO ENTRY FOUND \n";
}
}
if (library.toLowerCase().contains(pattern)){
substringWithPattern = "This or these books were found in the library \n" +
"--------------------------" + substringWithPattern;
}
return substringWithPattern;
The IndexOutOfBounds exception is thrown when the index you are searching for is not in the range of array length. When I went through the code, you are getting this exception because of below line execution where probably the indexLineEnd value is more than the actual length of List if the string variable list is not Null (Since your code doesn't show list variable to be initialized).
String listCheck = list.substring(indexLineStart, indexLineEnd);
Please run the application in debug mode to get the exact value that is getting passed to the method to understand why it throwing the exception.
you need to be careful at calculating the value of indexLineEnd.

masking of email address in java

I am trying to mask email address with "*" but I am bad at regex.
input : nileshxyzae#gmail.com
output : nil********#gmail.com
My code is
String maskedEmail = email.replaceAll("(?<=.{3}).(?=[^#]*?.#)", "*");
but its giving me output nil*******e#gmail.com I am not getting whats getting wrong here. Why last character is not converted?
Also can someone explain meaning all these regex
Your look-ahead (?=[^#]*?.#) requires at least 1 character to be there in front of # (see the dot before #).
If you remove it, you will get all the expected symbols replaced:
(?<=.{3}).(?=[^#]*?#)
Here is the regex demo (replace with *).
However, the regex is not a proper regex for the task. You need a regex that will match each character after the first 3 characters up to the first #:
(^[^#]{3}|(?!^)\G)[^#]
See another regex demo, replace with $1*. Here, [^#] matches any character that is not #, so we do not match addresses like abc#example.com. Only those emails will be masked that have 4+ characters in the username part.
See IDEONE demo:
String s = "nileshkemse#gmail.com";
System.out.println(s.replaceAll("(^[^#]{3}|(?!^)\\G)[^#]", "$1*"));
If you're bad at regular expressions, don't use them :) I don't know if you've ever heard the quote:
Some people, when confronted with a problem, think
"I know, I'll use regular expressions." Now they have two problems.
(source)
You might get a working regular expression here, but will you understand it today? tomorrow? in six months' time? And will your colleagues?
An easy alternative is using a StringBuilder, and I'd argue that it's a lot more straightforward to understand what is going on here:
StringBuilder sb = new StringBuilder(email);
for (int i = 3; i < sb.length() && sb.charAt(i) != '#'; ++i) {
sb.setCharAt(i, '*');
}
email = sb.toString();
"Starting at the third character, replace the characters with a * until you reach the end of the string or #."
(You don't even need to use StringBuilder: you could simply manipulate the elements of email.toCharArray(), then construct a new string at the end).
Of course, this doesn't work correctly for email addresses where the local part is shorter than 3 characters - it would actually then mask the domain.
Your Look-ahead is kind of complicated. Try this code :
public static void main(String... args) throws Exception {
String s = "nileshkemse#gmail.com";
s= s.replaceAll("(?<=.{3}).(?=.*#)", "*");
System.out.println(s);
}
O/P :
nil********#gmail.com
I like this one because I just want to hide 4 characters, it also dynamically decrease the hidden chars to 2 if the email address is too short:
public static String maskEmailAddress(final String email) {
final String mask = "*****";
final int at = email.indexOf("#");
if (at > 2) {
final int maskLen = Math.min(Math.max(at / 2, 2), 4);
final int start = (at - maskLen) / 2;
return email.substring(0, start) + mask.substring(0, maskLen) + email.substring(start + maskLen);
}
return email;
}
Sample outputs:
my.email#gmail.com > my****il#gmail.com
info#mail.com > i**o#mail.com
//In Kotlin
val email = "nileshkemse#gmail.com"
val maskedEmail = email.replace(Regex("(?<=.{3}).(?=.*#)"), "*")
public static string GetMaskedEmail(string emailAddress)
{
string _emailToMask = emailAddress;
try
{
if (!string.IsNullOrEmpty(emailAddress))
{
var _splitEmail = emailAddress.Split(Char.Parse("#"));
var _user = _splitEmail[0];
var _domain = _splitEmail[1];
if (_user.Length > 3)
{
var _maskedUser = _user.Substring(0, 3) + new String(Char.Parse("*"), _user.Length - 3);
_emailToMask = _maskedUser + "#" + _domain;
}
else
{
_emailToMask = new String(Char.Parse("*"), _user.Length) + "#" + _domain;
}
}
}
catch (Exception) { }
return _emailToMask;
}

Having an issue with formatting a String input

I'm trying to get the input that the user enters to go to lower-case and then put the first character in the input to upper-case. For example, If I enter aRseNAL for my first input, I want to format the input so that it will put "Arsenal" into the data.txt file, I'm also wondering if there's a way to put each first character to upper-case if there's more than one word for a team ie. mAN uNiTeD formatted to Man United to be written to the file.
The code I have below is what i tried and I cannot get it to work. Any advice or help would be appreciated.
import java.io.*;
import javax.swing.*;
public class write
{
public static void main(String[] args) throws IOException
{
FileWriter aFileWriter = new FileWriter("data.txt");
PrintWriter out = new PrintWriter(aFileWriter);
String team = "";
for(int i = 1; i <= 5; i++)
{
boolean isTeam = true;
while(isTeam)
{
team = JOptionPane.showInputDialog(null, "Enter a team: ");
if(team == null || team.equals(""))
JOptionPane.showMessageDialog(null, "Please enter a team.");
else
isTeam = false;
}
team.toLowerCase(); //Put everything to lower-case.
team.substring(0,1).toUpperCase(); //Put the first character to upper-case.
out.println(i + "," + team);
}
out.close();
aFileWriter.close();
}
}
In Java, strings are immutable (cannot be changed) so methods like substring and toLowerCase generate new strings - they don't modify your existing string.
So rather than:
team.toLowerCase();
team.substring(0,1).toUpperCase();
out.println(team);
You'd need something like:
String first = team.substring(0,1).toUpperCase();
String rest = team.substring(1,team.length()).toLowerCase();
out.println(first + rest);
Similar as #DNA suggested but that will throw Exception if String length is 1. So added a check for same.
String output = team.substring(0,1).toUpperCase();
// if team length is >1 then only put 2nd part
if (team.length()>1) {
output = output+ team.substring(1,team.length()).toLowerCase();
}
out.println(i + "," + output);

Erasing String that contains null

I have a null value in my message or println that i want to delete, all succeed when i just using code like this.
the message before :
message = 2014-06-02 14:53:37.103 null tes
Here is the code that delete the null word.
public static void main(String[] args) {
//final int month = Integer.parseInt(period[0]), year = Integer.parseInt(period[1]);
Date x = new Date();
Timestamp t = new Timestamp(x.getTime());
String a = "null";
String b = t+" " +a + " tes";
String tes = (b.trim()!= null && b.trim().length()>=23) ? b.trim().replaceFirst(b.trim().substring(0,28), ""+t) : b;
System.out.println("message = " + tes);
}
The printout is right. its like this :
message = 2014-06-02 14:53:37.103 tes
But when i insert this | the printout gone wrong. i'm using that as a separator.
This is the code that went wrong.
public static void main(String[] args) {
//final int month = Integer.parseInt(period[0]), year = Integer.parseInt(period[1]);
Date x = new Date();
Timestamp t = new Timestamp(x.getTime());
String a = "null";
String b = t+"| " +a + " tes";
String tes = (b.trim()!= null && b.trim().length()>=23) ? b.trim().replaceFirst(b.trim().substring(0,28), ""+t) : b;
System.out.println("message = " + tes);
}
And this is the print out :
message = 2014-06-02 14:58:03.148| null tes
What happen to the second code actually?
Thanks
As Boris said there are other ways, but the main problem is that replaceFirst takes a regex and pipe is a special character in regex.
Below with the introduction of Pattern.quote the code should work:
b.trim().replaceFirst(Pattern.quote(b.trim().substring(0,28)), ""+t)
If you want to simply strip out the 'null' text string without the regEx issues above, and quickly and cleanly, just replace the 'null' String directly.
b.replace("null", "")
What is exactly the main purpose of the program? if it is just to remove the null in the String, I would do as JamasA says. Otherwise if you want to get the timestamp and the "tes" string in two clean strings I would do it in this way:
String tes = b.replace("null", "");
String[] aux = tes.split("\\|");
for (int i = 0; i < aux.length; i++) {
System.out.println(aux[i].trim());
}
In this way you get both information separated.I hope it will helpful for you :)

How to convert a String into float inside a loop

I have to convert String into float I am doing it like this :
float[] iLongs = new float[mLongs.length];
for(int i = 0; i < iLongs.length ; i++){
iLongs[i] = Float.valueOf(mLongs[i]).floatValue();
}
But it throws numberformat exception
But if I use the same function outside any loop it works.
What to do ?
The code looks fine, which leads me to suspect that it's a data issue. You need to verify that every index for mLongs contains a String that is actually valid as a float, how you do that is up to you.
Alternative code :
class StringToFloat {
public static void main (String[] args) {
// String s = "hello"; // do this if you want an exception
String s = "100.00";
try {
float f = Float.valueOf(s.trim()).floatValue();
System.out.println("float f = " + f);
}
catch (NumberFormatException e) {
System.out.println("NumberFormatException: " + e.getMessage());
}
}
}
// Output :float f = 100.0
There is nothing wrong with your code.
Exception happend because String is not a Float and cannot be parsed. Most common mistake - , instead of .
You are correct syntactically. I think problem is in mLongs. It might contain some alphabetic character.

Categories

Resources