How do I trim a file extension from a String in Java? - java

What's the most efficient way to trim the suffix in Java, like this:
title part1.txt
title part2.html
=>
title part1
title part2

This is the sort of code that we shouldn't be doing ourselves. Use libraries for the mundane stuff, save your brain for the hard stuff.
In this case, I recommend using FilenameUtils.removeExtension() from Apache Commons IO

str.substring(0, str.lastIndexOf('.'))

As using the String.substring and String.lastIndex in a one-liner is good, there are some issues in terms of being able to cope with certain file paths.
Take for example the following path:
a.b/c
Using the one-liner will result in:
a
That's incorrect.
The result should have been c, but since the file lacked an extension, but the path had a directory with a . in the name, the one-liner method was tricked into giving part of the path as the filename, which is not correct.
Need for checks
Inspired by skaffman's answer, I took a look at the FilenameUtils.removeExtension method of the Apache Commons IO.
In order to recreate its behavior, I wrote a few tests the new method should fulfill, which are the following:
Path Filename
-------------- --------
a/b/c c
a/b/c.jpg c
a/b/c.jpg.jpg c.jpg
a.b/c c
a.b/c.jpg c
a.b/c.jpg.jpg c.jpg
c c
c.jpg c
c.jpg.jpg c.jpg
(And that's all I've checked for -- there probably are other checks that should be in place that I've overlooked.)
The implementation
The following is my implementation for the removeExtension method:
public static String removeExtension(String s) {
String separator = System.getProperty("file.separator");
String filename;
// Remove the path upto the filename.
int lastSeparatorIndex = s.lastIndexOf(separator);
if (lastSeparatorIndex == -1) {
filename = s;
} else {
filename = s.substring(lastSeparatorIndex + 1);
}
// Remove the extension.
int extensionIndex = filename.lastIndexOf(".");
if (extensionIndex == -1)
return filename;
return filename.substring(0, extensionIndex);
}
Running this removeExtension method with the above tests yield the results listed above.
The method was tested with the following code. As this was run on Windows, the path separator is a \ which must be escaped with a \ when used as part of a String literal.
System.out.println(removeExtension("a\\b\\c"));
System.out.println(removeExtension("a\\b\\c.jpg"));
System.out.println(removeExtension("a\\b\\c.jpg.jpg"));
System.out.println(removeExtension("a.b\\c"));
System.out.println(removeExtension("a.b\\c.jpg"));
System.out.println(removeExtension("a.b\\c.jpg.jpg"));
System.out.println(removeExtension("c"));
System.out.println(removeExtension("c.jpg"));
System.out.println(removeExtension("c.jpg.jpg"));
The results were:
c
c
c.jpg
c
c
c.jpg
c
c
c.jpg
The results are the desired results outlined in the test the method should fulfill.

String foo = "title part1.txt";
foo = foo.substring(0, foo.lastIndexOf('.'));

BTW, in my case, when I wanted a quick solution to remove a specific extension, this is approximately what I did:
if (filename.endsWith(ext))
return filename.substring(0,filename.length() - ext.length());
else
return filename;

Use a method in com.google.common.io.Files class if your project is already dependent on Google core library. The method you need is getNameWithoutExtension.

you can try this function , very basic
public String getWithoutExtension(String fileFullPath){
return fileFullPath.substring(0, fileFullPath.lastIndexOf('.'));
}

String fileName="foo.bar";
int dotIndex=fileName.lastIndexOf('.');
if(dotIndex>=0) { // to prevent exception if there is no dot
fileName=fileName.substring(0,dotIndex);
}
Is this a trick question? :p
I can't think of a faster way atm.

I found coolbird's answer particularly useful.
But I changed the last result statements to:
if (extensionIndex == -1)
return s;
return s.substring(0, lastSeparatorIndex+1)
+ filename.substring(0, extensionIndex);
as I wanted the full path name to be returned.
So "C:\Users\mroh004.COM\Documents\Test\Test.xml" becomes
"C:\Users\mroh004.COM\Documents\Test\Test" and not
"Test"

filename.substring(filename.lastIndexOf('.'), filename.length()).toLowerCase();

Use a regex. This one replaces the last dot, and everything after it.
String baseName = fileName.replaceAll("\\.[^.]*$", "");
You can also create a Pattern object if you want to precompile the regex.

If you use Spring you could use
org.springframework.util.StringUtils.stripFilenameExtension(String path)
Strip the filename extension from the given Java resource path, e.g.
"mypath/myfile.txt" -> "mypath/myfile".
Params: path – the file path
Returns: the path with stripped filename extension

private String trimFileExtension(String fileName)
{
String[] splits = fileName.split( "\\." );
return StringUtils.remove( fileName, "." + splits[splits.length - 1] );
}

String[] splitted = fileName.split(".");
String fileNameWithoutExtension = fileName.replace("." + splitted[splitted.length - 1], "");

create a new file with string image path
String imagePath;
File test = new File(imagePath);
test.getName();
test.getPath();
getExtension(test.getName());
public static String getExtension(String uri) {
if (uri == null) {
return null;
}
int dot = uri.lastIndexOf(".");
if (dot >= 0) {
return uri.substring(dot);
} else {
// No extension.
return "";
}
}

org.apache.commons.io.FilenameUtils version 2.4 gives the following answer
public static String removeExtension(String filename) {
if (filename == null) {
return null;
}
int index = indexOfExtension(filename);
if (index == -1) {
return filename;
} else {
return filename.substring(0, index);
}
}
public static int indexOfExtension(String filename) {
if (filename == null) {
return -1;
}
int extensionPos = filename.lastIndexOf(EXTENSION_SEPARATOR);
int lastSeparator = indexOfLastSeparator(filename);
return lastSeparator > extensionPos ? -1 : extensionPos;
}
public static int indexOfLastSeparator(String filename) {
if (filename == null) {
return -1;
}
int lastUnixPos = filename.lastIndexOf(UNIX_SEPARATOR);
int lastWindowsPos = filename.lastIndexOf(WINDOWS_SEPARATOR);
return Math.max(lastUnixPos, lastWindowsPos);
}
public static final char EXTENSION_SEPARATOR = '.';
private static final char UNIX_SEPARATOR = '/';
private static final char WINDOWS_SEPARATOR = '\\';

The best what I can write trying to stick to the Path class:
Path removeExtension(Path path) {
return path.resolveSibling(path.getFileName().toString().replaceFirst("\\.[^.]*$", ""));
}

dont do stress on mind guys. i did already many times. just copy paste this public static method in your staticUtils library for future uses ;-)
static String removeExtension(String path){
String filename;
String foldrpath;
String filenameWithoutExtension;
if(path.equals("")){return "";}
if(path.contains("\\")){ // direct substring method give wrong result for "a.b.c.d\e.f.g\supersu"
filename = path.substring(path.lastIndexOf("\\"));
foldrpath = path.substring(0, path.lastIndexOf('\\'));;
if(filename.contains(".")){
filenameWithoutExtension = filename.substring(0, filename.lastIndexOf('.'));
}else{
filenameWithoutExtension = filename;
}
return foldrpath + filenameWithoutExtension;
}else{
return path.substring(0, path.lastIndexOf('.'));
}
}

I would do like this:
String title_part = "title part1.txt";
int i;
for(i=title_part.length()-1 ; i>=0 && title_part.charAt(i)!='.' ; i--);
title_part = title_part.substring(0,i);
Starting to the end till the '.' then call substring.
Edit:
Might not be a golf but it's effective :)

Keeping in mind the scenarios where there is no file extension or there is more than one file extension
example Filename : file | file.txt | file.tar.bz2
/**
*
* #param fileName
* #return file extension
* example file.fastq.gz => fastq.gz
*/
private String extractFileExtension(String fileName) {
String type = "undefined";
if (FilenameUtils.indexOfExtension(fileName) != -1) {
String fileBaseName = FilenameUtils.getBaseName(fileName);
int indexOfExtension = -1;
while (fileBaseName.contains(".")) {
indexOfExtension = FilenameUtils.indexOfExtension(fileBaseName);
fileBaseName = FilenameUtils.getBaseName(fileBaseName);
}
type = fileName.substring(indexOfExtension + 1, fileName.length());
}
return type;
}

String img = "example.jpg";
// String imgLink = "http://www.example.com/example.jpg";
URI uri = null;
try {
uri = new URI(img);
String[] segments = uri.getPath().split("/");
System.out.println(segments[segments.length-1].split("\\.")[0]);
} catch (Exception e) {
e.printStackTrace();
}
This will output example for both img and imgLink

private String trimFileName(String fileName)
{
String[] ext;
ext = fileName.split("\\.");
return fileName.replace(ext[ext.length - 1], "");
}
This code will spilt the file name into parts where ever it has " . ", For eg. If the file name is file-name.hello.txt then it will be spilted into string array as , { "file-name", "hello", "txt" }. So anyhow the last element in this string array will be the file extension of that particular file , so we can simply find the last element of any arrays with arrayname.length - 1, so after we get to know the last element, we can just replace the file extension with an empty string in that file name. Finally this will return file-name.hello. , if you want to remove also the last period then you can add the string with only period to the last element of string array in the return line. Which should look like,
return fileName.replace("." + ext[ext.length - 1], "");

public static String removeExtension(String file) {
if(file != null && file.length() > 0) {
while(file.contains(".")) {
file = file.substring(0, file.lastIndexOf('.'));
}
}
return file;
}

Related

Groovy/Java - Issue copying files with parentheses in its path

I currently have a script that copies files from a source directory to a target directory through regex inclusions and exclusions, however when the path contains parentheses the file will not copy.
My initial thought was that the issue was with how source and target were being read since ( is a special character, to combat that I've tried to replace the ( with an escaped (, but I may have been doing that portion wrong.
import groovy.io.FileType
import java.nio.file.*
String Source = 'C:/temp/file(s)'
String Target = 'C:/newTemp/file(s)'
String InclusionsRegexes = "garbage.txt"
String ExclusionsRegexes = ""
class RegexInfo
{
private String AllRegexes = "";
public RegexInfo(String RegexString, String RegexType, String Source)
{
if(RegexString != null)
{
def RegexArray = RegexString.split(",");
for(item in RegexArray)
{
String fullRegexPath = Source + "/" + item;
if(AllRegexes != null && !AllRegexes.isAllWhitespace())
{
//Add regex value for Or
AllRegexes += "|";
}
AllRegexes += fullRegexPath;
}
}
}
public String getAllRegexes() { return this.AllRegexes; }
}
IncludesRegexInfo = new RegexInfo(InclusionsRegexes, "inclusion", Source);
ExcludesRegexInfo = new RegexInfo(ExclusionsRegexes, "exclusion", Source);
File SourceDirToCopy = new File(Source);
SourceDirToCopy.eachFileRecurse()
{
SourceFile ->
String SourceFilePath = SourceFile.toString().replaceAll("\\\\","/");
if(SourceFile.isDirectory())
{
SourceFilePath += "/"
}
if(SourceFilePath.matches(IncludesRegexInfo.getAllRegexes()) && !SourceFilePath.matches(ExcludesRegexInfo.getAllRegexes()))
{
File TargetFile = new File(SourceFilePath.replace(Source, Target))
String TargetFilePath = TargetFile.toString().replaceAll("\\\\", "/");
if(!TargetFile.getParentFile().exists())
{
TargetFile.getParentFile().mkdirs()
}
Files.copy(SourceFile.toPath(), TargetFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
}
}
The errors I've been receiving have been either unexpected characters or the file not moving without an error.
In order to solve the issue of the script not copying, there was an issue with if(SourceFilePath.matches(IncludesRegexInfo.getAllRegexes() && !SourceFilePath.matches(ExcludesRegexInfo.getAllRegexes())) when "matching" the two strings.
The strings read as the same lines however did not match in terms of regex. To fix this you must escape the ( and ) in the ExcludesRegexInfo.getAllRegexes(). This was done with an .replaceAll("\\(","\\\\(").replaceAll("\\)","\\\\)")

Generic code generation in Java

I am learning Java (and Swing), and am developing a small code generator that generates Java classes after asking you some information.
The first window asks the class name (mandatory), mother-class name, and asks if you wish to generate a default constructor. Once you press Generate, a JDialog opens up with the generated class.
But my issue comes to the generic side of my code generation.
Once the information about the class is saved, I call my generateCode function that looks like such:
private String generateCode(Information info) {
String code = "";
// info contains all the information inputed by the user
if (info.motherClass.equals("") && info.generateDefaultConstructor == false) {
code = "public class " + info.name + "{\n\n}";
} else {
}
return code;
}
As you can see, I only handle the case where only the class name is given.
How should I code it in order to handle other options? Should it be with a block of conditions handling everything one by one? I truly want to make my code as generic as possible in order to add more features later on.
Thank you.
First of all I would recommend making all the none static fields of Information private or protected add getters and setters.
Then add a few methods that can check and / or manipulate Strings like:
public static String removeSpaces(String input) {
if (input == null) {
return "";
}
String enter = (char) (13) + (char) (10) + "";
String tab = (char) (9) + "";
String space = (char) (32) + "";
String empty = "";
return input.replace(enter, empty).replace(tab, empty).replace(space, empty);
}
public static String newLine(){
return (char) (13) + (char) (10) + "";
}
public static String tab(){
return (char) (9) + "";
}
Then split the generateCode method into something like:
private String generateCode(Information info) {
StringBuilder code = new StringBuilder();
code.append(getClassCode(info.getMotherClass()));
code.append(newLine());
code.append(tab());
code.append(getConstructor(info));
return code.toString();
}
public static String getClassCode(String className){
StringBuilder code = new StringBuilder();
code.append("public class ");
if (!removeSpaces(className).isEmpty()){
code.append(className);
} else {
code.append(Information.getDefaultClass());//have a default static name for a class like "Application"
}
code.append("{");
code.append(newLine());
return code.toString();
}
public static String getConstructor(Information info){
StringBuilder code = new StringBuilder();
if(!info.isGenerateDefaultConstructor()) {
code.append("public ");
code.append(info.getMotherClass());
code.append("(){");
code.append(newLine());
code.append(tab());
code.append(info.getConstructorContent());//what will be in the constructor
code.append(newLine());
code.append(tab());
code.append("}");
}
code.append(newLine());
return code.toString();
}
And then you can keep going by adding bits and pieces here and there.
You could make info as a string list and iterate through it skipping code generation where the list is an empty string.

Splitting a String without spaces

I have the following string which is generated by an external program (OpenVAS) and returned to my program successfully as a string.
<create_target_response id="b4c8de55-94d8-4e08-b20e-955f97a714f1" status_text="OK, resource created" status="201"></create_target_response>
I am trying to split the string to give me the "b4c8d....14f1" without the inverted commas. I have tried all sorts of escape methods and keep getting the else method "String does not contain a Target ID". I have tried removing the IF statement checking for the string, but continue to have the same issue. The goal is to get my id string into jTextField6. String Lob contains the full string as above.
if (Lob.contains("id=\"")){
// put the split here
String[] parts = Lob.split("id=\"");
String cut1 = parts[1];
String[] part2 = cut1.split("\"");
String TaskFinal = part2[0];
jTextField6.setText(TaskFinal);
}
else {
throw new IllegalArgumentException("String does not contain a Target ID");
}
} catch (IOException e) {
e.printStackTrace();
}
It seems I only need to escape the " and not the = (Java kicks up an error if i do)
Thanks in advance
EDIT: Code as it stands now using jSoup lib - The 'id' string won't display. Any ideas?
Thanks
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
String TargIP = jTextField1.getText(); // Get IP Address
String TargName = jTextField5.getText(); // Get Target Name
String Vag = "8d32ad99-ac84-4fdc-b196-2b379f861def";
String Lob = "";
final String dosCommand = "cmd /c omp -u admin -w admin --xml=\"<create_target><name>" + TargName + "</name><hosts>" + TargIP + "</hosts></create_target>\"";
3</comment><config id='daba56c8-73ec-11df-a475-002264764cea'/><target id='" + Vag + "'/></create_task>\"";
final String location = "C:\\";
try {
final Process process = Runtime.getRuntime().exec(
dosCommand + " " + location);
final InputStream in = process.getInputStream();
int ch;
while((ch = in.read()) != -1) {
System.out.print((char)ch);
Lob = String.valueOf((char)ch);
jTextArea2.append(Lob);
}
} catch (IOException e) {
e.printStackTrace();
}
String id = Jsoup.parse(Lob).getAllElements().attr("id");
System.out.println(id); // This doesn't output?
}
Split on the basis of ". You can get all the key values.
String str = "<create_target_response id=\"b4c8de55-94d8-4e08-b20e-955f97a714f1\" status_text=\"OK, resource created\" status=\"201\"></create_target_response>";
String[] tokens = str.split("\\\"");
System.out.println(tokens[1]);
System.out.println(tokens[5]);
output:
b4c8de55-94d8-4e08-b20e-955f97a714f1
201
This will get you your job id more easily:
int idStart = Lob.indexOf("id=")+("id=\"").length();
System.out.println(Lob.substring(idStart,Lob.indexOf("\"",idStart)));
Everyone's telling you to use an XML parser (and they're right) but noone's showing you how.
Here goes:
String lob = ...
Using Jsoup from http://jsoup.org, actually an HTML parser but also handles XML neatly:
String id = Jsoup.parse(lob).getAllElements().attr("id");
// b4c8de55-94d8-4e08-b20e-955f97a714f1
With built-in Java XML APIs, less concise but no addtional libraries:
Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder()
.parse(new InputSource(new StringReader(lob)));
String id = dom.getDocumentElement().getAttribute("id");
// b4c8de55-94d8-4e08-b20e-955f97a714f1
This is a lot simpler than you're making it, to my mind. First, split on space, then check if an = is present. If it is, split on the =, and finally remove the " from the second token.
The tricky bit is the spaces inside of the "". This will require some regular expressions, which you can work out from this question.
Example
String input; // Assume this contains the whole string.
String pattern; // Have fun working out the regex.
String[] values = input.split(pattern);
for(String value : values)
{
if(value.contains("=")) {
String[] pair = value.split("=");
String key = pair[0];
String value = pair[1].replaceAll("\"");
// Do something with the values.
}
}
Advantage of my approach
Is that provided the input follows the format of key="value" key="value", you can parse anything that comes through, rather than hard coding the name of the attributes.
And if this is XML..
Then use an XML parser. There is a good (awesome) answer that explains why you shouldn't be using Stringmanipulation to parse XML/HTML. Here is the answer.
You can use a regex to extract what is needed; what is more, it looks like the value of id is a UUID. Therefore:
private static final Pattern PATTERN
= Pattern.compile("\\bid=\"([^\"]+)\"");
// In code...
public String getId(final String input)
{
final Matcher m = PATTERN.matcher(input);
if (!m.find())
throw new IllegalArgumentException("String does not contain a Target ID");
final String uuid = m.group(1);
try {
UUID.fromString(uuid);
} catch (IllegalArgumentException ignored) {
throw new IllegalArgumentException("String does not contain a Target ID");
}
return uuid;
}

replace string with string in j2me

i'm getting error cannot find symbol in netbeans while using the below code for replacing the string with string.
public String urlEncode(String msg) {
if (msg != null) {
msg=msg.replaceAll(" ","%20");
}
return msg;
}
Need help !!
I have created following method for replacing String with another String.
private String replace( String str, String pattern, String replace )
{
int s = 0;
int e = 0;
StringBuffer result = new StringBuffer();
while ( (e = str.indexOf( pattern, s ) ) >= 0 )
{
result.append(str.substring( s, e ) );
result.append( replace );
s = e+pattern.length();
}
result.append( str.substring( s ) );
return result.toString();
}
use the following code
private String replace(String needle, String replacement, String haystack) {
String result = "";
int index = haystack.indexOf(needle);
if(index==0) {
result = replacement+haystack.substring(needle.length());
return replace(needle, replacement, result);
}else if(index>0) {
result = haystack.substring(0,index)+ replacement +haystack.substring(index+needle.length());
return replace(needle, replacement, result);
}else {
return haystack;
}
}
Try an adapted version of URLEncoder for JavaMe published on code.google.com under the project JibLib mobile client.
Do you need for sure use your own method for handling URL encoding?
Just use URLEncoder.encode(String s, String enc)
#param s String to be translated.
#param enc The name of a supported
#return the translated String.
replaceAll was introduced in Java 1.4 and I think J2ME is limited to 1.3. You must be compiling with a later JDK which is why you are getting a symbol error at runtime.
URLEncoder.encode (String s) might be your best bet. Unfortunately the URLEncoder.encode(String s, String enc), as suggested by Xeon, is also a JDK1.4 API call.

Does Java have a path joining method? [duplicate]

This question already has answers here:
Closed 13 years ago.
Exact Duplicate:
combine paths in java
I would like to know if there is such a method in Java. Take this snippet as example :
// this will output a/b
System.out.println(path_join("a","b"));
// a/b
System.out.println(path_join("a","/b");
This concerns Java versions 7 and earlier.
To quote a good answer to the same question:
If you want it back as a string later, you can call getPath(). Indeed, if you really wanted to mimic Path.Combine, you could just write something like:
public static String combine (String path1, String path2) {
File file1 = new File(path1);
File file2 = new File(file1, path2);
return file2.getPath();
}
Try:
String path1 = "path1";
String path2 = "path2";
String joinedPath = new File(path1, path2).toString();
One way is to get system properties that give you the path separator for the operating system, this tutorial explains how. You can then use a standard string join using the file.separator.
This is a start, I don't think it works exactly as you intend, but it at least produces a consistent result.
import java.io.File;
public class Main
{
public static void main(final String[] argv)
throws Exception
{
System.out.println(pathJoin());
System.out.println(pathJoin(""));
System.out.println(pathJoin("a"));
System.out.println(pathJoin("a", "b"));
System.out.println(pathJoin("a", "b", "c"));
System.out.println(pathJoin("a", "b", "", "def"));
}
public static String pathJoin(final String ... pathElements)
{
final String path;
if(pathElements == null || pathElements.length == 0)
{
path = File.separator;
}
else
{
final StringBuilder builder;
builder = new StringBuilder();
for(final String pathElement : pathElements)
{
final String sanitizedPathElement;
// the "\\" is for Windows... you will need to come up with the
// appropriate regex for this to be portable
sanitizedPathElement = pathElement.replaceAll("\\" + File.separator, "");
if(sanitizedPathElement.length() > 0)
{
builder.append(sanitizedPathElement);
builder.append(File.separator);
}
}
path = builder.toString();
}
return (path);
}
}

Categories

Resources