Two strings appear to be equal, but they are not - java

I want to open a file using the argument I get via a socket. When I extract the filename using split(), the file does not open. But when I hardcode the value, it does open.
What am I missing here? I would expect the strings to be equal.
String name = str.split(";")[2];
System.out.println("Filename: " + name);
String path1 = new String("Input_Blatt3/Sample.txt");
String path2 = new String("Input_Blatt3/" + name);
System.out.println("Path1: " + path1);
System.out.println("Path2: " + path2);
System.out.println("path1.equals(path2) = " + path1.equals(path2));
Output:
Path1: Input_Blatt3/Sample.txt
Path2: Input_Blatt3/Sample.txt
path1.equals(path2) = false

There could be unprintable characters hidden in the String.
Use getBytes to get all the characters of a String and print those. You'll probably find something you didn't expect.
You need to iterate over the byte array to print each byte individually, as in the following method:
private static void printBytes(String string) {
System.out.println("printing " + string);
for (byte aByte : string.getBytes()) {
System.out.println( aByte );
}
}
Alternatively you could also replace everything that isn't a printable character with nothing.

There could be some trailing white spaces, which you would not see at the console output.
You can try name.strip() (or trim() if your JDK version is lower 11) to ensure that there's nothing but the file name in the string.
Also, you can find the index of the first mismatching character of these two strings using Arrays.mismatch():
int indexOfMismatch = Arrays.mismatch(str1.toCharArray(), str2.toCharArray());
In case if the strings are equal, indexOfMismatch would be -1.

Related

String comparison resulting in incorrect result

I have a path URL written in a file. I use the Scanner class to record that URL and output it to string variable "s". I then use the .equals() method to compare it and the path URL in my "gameDataFile" File object. The result is false, despite them being the same string as recorded in my console. What is happening here?
Path URL in file:
src\gameData\character_data.csv
Code snippet:
String s = in.next(); // in is a java.util.Scanner object
System.out.println(gameDataFile.getPath()); // gameDataFile is a java.io.File object
System.out.println(s);
System.out.println(s.equals(gameDataFile.getPath()));
Console output:
src\gameData\character_data.csv
src\gameData\character_data.csv
false
EDIT: as per request of #MTilsted, the following code snippet
String s = in.next();
System.out.println("'" + gameDataFile.getPath() + "'");
System.out.println("'" + s + "'");
System.out.println(s.equals(gameDataFile.getPath()));
Results in the console output:
'src\gameData\character_data.csv'
'
false
It seems to have replaced the URL with one single quotation mark
Try this instead:
String s = in.next(); // in is a java.util.Scanner object
System.out.println("'" + gameDataFile.getPath() + "'"); // gameDataFile is a java.io.File object
System.out.println("'" + s + "'");
System.out.println(s.equals(gameDataFile.getPath()));
Thanks to #VGR, the problem was that the String "s" contains an addition "Carriage return" character (ascii code 13).
The utf8 file in windows has a BOM (byte order mark) at the start of the file by default. It is invisible, but it really exist. I think it cause two string different even if they look the same.
add a backslash before the single quote

Cleaning a file name in Java

I want to write a script that will clean my .mp3 files.
I was able to write a few line that change the name but I want to write an automatic script that will erase all the undesired characters $%_!?7 and etc. while changing the name in the next format Artist space dash Song.
File file = new File("C://Users//nikita//Desktop//$%#Artis8t_-_35&Son5g.mp3");
String Original = file.toString();
String New = "Code to change 'Original' to 'Artist - Song'";
File file2 = new File("C://Users//nikita//Desktop//" + New + ".mp3");
file.renameTo(file2);
I feel like I should make a list with all possible characters and then run the String through this list and erase all of the listed characters but I am not sure how to do it.
String test = "$%$#Arti56st_-_54^So65ng.mp3";
Edit 1:
When I try using the method remove, it still doesn't change the name.
String test = "$%$#Arti56st_-_54^So65ng.mp3";
System.out.println("Original: " + test);
test.replace( "[0-9]%#&\\$", "");
System.out.println("New: " + test);
The code above returns the following output
Original: $%$#Arti56st_-_54^So65ng.mp3
New: $%$#Arti56st_-_54^So65ng.mp3
I'd suggest something like this:
public static String santizeFilename(String original){
Pattern p = Pattern.compile("(.*)-(.*)\\.mp3");
Matcher m = p.matcher(original);
if (m.matches()){
String artist = m.group(1).replaceAll("[^a-zA-Z ]", "");
String song = m.group(2).replaceAll("[^a-zA-Z ]", "");
return String.format("%s - %s", artist, song);
}
else {
throw new IllegalArgumentException("Failed to match filename : "+original);
}
}
(Edit - changed whitelist regex to exclude digits and underscores)
Two points in particular - when sanitizing strings, it's a good idea to whitelist permitted characters, rather than blacklisting the ones you want to exclude, so you won't be surprised by edge cases later. (You may want a less restrictive whitelist than I've used here, but it's easy to vary)
It's also a good idea to handle the case that the filename doesn't match the expected pattern. If your code comes across something other than an MP3, how would you like it to respond? Here I've through an exception, so the calling code can catch and handle that appropriately.
String new = original.replace( "[0-9]%#&\\$", "")
this should replace almost all the characters you don't want
or you can come up with your own regex
https://docs.oracle.com/javase/tutorial/essential/regex/

how use RegEx in String.replaceAll for ignoring middle characters while searching and replacing

I have to search in testFile.xml every word "abc" + 7 numbers not important + "myOldWord" to change to some new without worring the numbers inside. There will a couple of "xxx9999999myOldWorld". How can I find "abc1234567myOldWorld" and replace only myOldWorld for newWorld using regular expression? I can't only exchange from myOldWorld to newWord because the first three caracters have to be used in the search criteria an the unknown 7 lengths between them must be ignored.
Other example. Let us say I have the new world "aaaOtherNewWord" to replace "aaa9999999OtherOldWord" (I don't know the number when searching and there are a couple of them with different numbers).
Let's say there are three old words in the testFile.xml: aaa1234567OTHEROLDWORD, aaa9876543otheroldword and bbb9876543otheroldword and I want to execute replaceAll and get the outcome: aaa1234567OtherNewWord and aaa9876543OtherNewWord respectvely but bbb9876543otheroldword will not change because the first 3 digits didn't match the search criteria.
I coded below and successfully I am ignoring the case when searching but I must ignore the numbers and I don't know how to do this with regular expression.
Path path = Paths.get("C:\\testFolder\\testFile.xml");
Charset charset = StandardCharsets.UTF_8;
String content = new String(Files.readAllBytes(path), charset);
content = content.replaceAll("(?i)" + oldWord, newWord);
Note: I am using Java 8.
The entire test is:
// C:\test.xml
<?xml version="1.0" encoding="UTF-8"?>
<c:bps xmlns:c="CertainApp">
<c:bp name="ProductPortfolio" id="myProdPort">
<!-- must result in ABC1234567MyCompanyWORDProductSubproduct-->
<c:message type="ABC1234567MyCompanyWorDProductSubproduct" />
<!-- must result in ABC0987654MyCompanyWORDProductSubproduct-->
<c:message type="ABC0987654MyCompanyWoRdProductSubproduct" />
<!-- must result in XYZ1234567MyCompanywordproductSubproduct-->
<c:message type="XYZ1234567MyCompanywOrdproductSubproduct" />
<!-- nothing changed in next two-->
<c:message type="XYZ1234567MyCompanyAnyThingproductSubproduct" />
<c:message type="XYZ0987654MyCompanyAnyThingproductSubproduct" />
</c:bps>
//C:\defaults_test contains two files
ABCMyCompanyWORDproductSubproduct.xml //here the “word” is uppercase and starts with ABC
XYZMyCompanywordproductSubproduct.xml //here the “word” is lowercase and starts with XYZ
public class ReadICTTDefaultFolder {
public static void replaceFileString(String first3letters, String word) {
Path path = Paths.get("C:\\test.xml");
Charset charset = StandardCharsets.UTF_8;
try{
String content = new String(Files.readAllBytes(path), charset);
content = content.replaceAll("((?i)" + first3letters + "\\d{7})" + word, "$1"+word);
Files.write(path, content.getBytes(charset));
}
catch(Exception e){
}
}
public static void main(String[] args) {
File actual = new File("C:\\ defaults_test");
File list[] = actual.listFiles();
for(int i=0; i<list.length; i++){
String substring = list[i].getName().substring(0, list[i].getName().indexOf("."));
if(list[i].isFile() && substring.toUpperCase().contains("WORD")){
replaceFileString(substring.substring(0,3), substring.substring(3));
}
}
}
content = content.replaceAll("(abc\\d{7})" + oldWord, "$1"+newWord);
You can, in the replacement string, refer to a group via $n where n is the group number.
The regex part \\d{7} matches exactly seven digits (don't confuse this with numbers).
It would also be possible to pick the correct oldWord using a positive lookbehind assertion:
replaceAll( "(?<=abc\\d{7})" + oldWord, newWord )
and then you don't need the $1.
Later
Now that I see the whole mess, where the "(?i)" is essential, I should have added that an option string must be written at the proper nesting level of parentheses:
...replaceAll("(?i)(" + prefix + "\\d{7})" + oldWord, "$1"+newWord);
and not
...replaceAll("((?i)" + prefix + "\\d{7})" + oldWord, "$1"+newWord);
which would restrict the case-ignoring match to the prefix. Since the prefix should, perhaps, match exactly, it would be best to write
...replaceAll("(" + prefix + "\\d{7})(?i)" + oldWord, "$1"+newWord);
As it seems, oldWord and newWord are identical except for case, you can also use
...replaceAll("(" + prefix + "\\d{7})(?i)" + word, "$1" + word);

How to get the string before .(dot) and after /(last) slash in Java

I have a string like this:
"core/pages/viewemployee.jsff"
From this code, I need to get "viewemployee". How do I get this using Java?
Suppose that you have that string saved in a variable named myString.
String myString = "core/pages/viewemployee.jsff";
String newString = myString.substring(myString.lastIndexOf("/")+1, myString.indexOf("."));
But you need to make the same control before doing substring in this one, because if there aren't those characters you will get a "-1" from lastIndexOf(), or indexOf(), and it will break your substring invocation.
I suggest looking for the Javadoc documentation.
You can solve this with regex (given you only need a group of word characters between the last "/" and "."):
String str="core/pages/viewemployee.jsff";
str=str.replaceFirst(".*/(\\w+).*","$1");
System.out.println(str); //prints viewemployee
You can split the string first with "/" so that you can have each folder and the file name got separated. For this example, you will have "core", "pages" and "viewemployee.jsff". I assume you need the file name without the extension, so just apply same split action with "." seperator to the last token. You will have filename without extension.
String myStr = "core/pages/viewemployee.bak.jsff";
String[] tokens = myStr.split("/");
String[] fileNameTokens = tokens[tokens.length - 1].split("\\.");
String fileNameStr = "";
for(int i = 0; i < fileNameTokens.length - 1; i++) {
fileNameStr += fileNameTokens[i] + ".";
}
fileNameStr = fileNameStr.substring(0, fileNameStr.length() - 1);
System.out.print(fileNameStr) //--> "viewemployee.bak"
These are file paths. Consider using File.getName(), especially if you already have the File object:
File file = new File("core/pages/viewemployee.jsff");
String name = file.getName(); // --> "viewemployee.jsff"
And to remove the extension:
String res = name.split("\\.[^\\.]*$")[0]; // --> "viewemployee"
With this we can handle strings like "../viewemployee.2.jsff".
The regex matches the last dot, zero or more non-dots, and the end of the string. Then String.split() treats these as a delimiter, and ignores them. The array will always have one element, unless the original string is ..
The below will get you viewemployee.jsff:
int idx = fileName.replaceAll("\\", "/").lastIndexOf("/");
String fileNameWithExtn = idx >= 0 ? fileName.substring(idx + 1) : fileName;
To remove the file Extension and get only viewemployee, similarly:
idx = fileNameWithExtn.lastIndexOf(".");
String filename = idx >= 0 ? fileNameWithExtn.substring(0,idx) : fileNameWithExtn;

Java add chars to a string

I have two strings in a java program, which I want to mix in a certain way to form two new strings. To do this I have to pick up some constituent chars from each string and add them to form the new strings. I have a code like this(this.eka and this.toka are the original strings):
String muutettu1 = new String();
String muutettu2 = new String();
muutettu1 += this.toka.charAt(0) + this.toka.charAt(1) + this.eka.substring(2);
muutettu2 += this.eka.charAt(0) + this.eka.charAt(1) + this.toka.substring(2);
System.out.println(muutettu1 + " " + muutettu2);
I'm getting numbers for the .charAt(x) parts, so how do I convert the chars to string?
StringBuilder builder = new StringBuilder();
builder
.append(this.toka.charAt(0))
.append(this.toka.charAt(1))
.append(this.toka.charAt(2))
.append(' ')
.append(this.eka.charAt(0))
.append(this.eka.charAt(1))
.append(this.eka.charAt(2));
System.out.println (builder.toString());
Just use always use substring() instead of charAt()
In this particular case, the values are mutable, consequently, we can use the built in String class method substring() to solve this problem (#see the example below):
Example specific to the OP's use case:
muutettu1 += toka.substring(0,1) + toka.substring(1,2) + eka.substring(2);
muutettu2 += eka.substring(0,1) + eka.substring(1,2) + toka.substring(2);
Concept Example, (i.e Example showing the generalized approach to take when attempting to solve a problem using this concept)
muutettu1 += toka.substring(x,x+1) + toka.substring(y,y+1) + eka.substring(z);
muutettu2 += eka.substring(x,x+1) + eka.substring(y,y+1) + toka.substring(z);
"...Where x,y,z are the variables holding the positions from where to extract."
The obvious conversion method is Character.toString.
A better solution is:
String muutettu1 = toka.substring(0,2) + eka.substring(2);
String muutettu2 = eka.substring(0,2) + toka.substring(2);
You should create a method for this operation as it is redundant.
The string object instatiantiation new String() is unnecessary. When you append something to an empty string the result will be the appended content.
You can also convert an integer into a String representation in two ways: 1) String.valueOf(a) with a denoting an integer 2) Integer.toString(a)
This thing can adding a chars to the end of a string
StringBuilder strBind = new StringBuilder("Abcd");
strBind.append('E');
System.out.println("string = " + str);
//Output => AbcdE
str.append('f');
//Output => AbcdEf

Categories

Resources