I have an array list defined as
List<String> cmd = new ArrayList<String>();
I am adding other strings to this List this way
cmd.add("/c");
cmd.add(command);
However if command contains " " or ' ' and a white space in between them the quotes are truncated.
How do I workaround this behaviour?
For example, if the command is
grep "Hello world" /sratch/temp
the cmd contains these Strings /c grep Hello World /scratch/temp
However if the command is grep "Hello\ world" /sratch/temp
the strings in cmd are
/c grep " Hello World " /scratch/temp
How do I program it such that the " " are not truncated?
So you want your String object to contain quotes? Try escaping them with backslash:
cmd.add("some string with \"quotes\"");
This problem is not related to ArrayList, you simple have to escape your single and double quotes when you assign them to the String object or retrieve them from user input. For more information on escape sequences in Java, have a look at this tutorial on the Oracle web site, for example.
This is actually not about Java, but about the shell you're using.
On the shell (i.e. bash, command prompt, etc.) arguments are generally broken up using spaces.
For instance,
java my.class The quick brown fox
would result in an argument list of
String[] { "The", "quick", "brown", "fox" }
However, the shell usually allows the user to make multiple spaced strings a single argument by surrounding them with double quotes - the behavior you're seeing.
For instance,
java my.class The quick "brown fox"
would result in an argument list of
String[] { "The", "quick", "brown fox" }
This means double quotes are removed from the argument list and are not literally inserted into the string.
If my assumption is correct, and you're running shell commands via your program given some sort of other command system, then you can simply surround every piece of the command in double quotes.
You can escape the quotes, just write:
"grep \"Hello world\" /sratch/temp"
You can take a look at this, for more information
EDIT
If you're parsing the user input Java will escape this special characters automatically. For example, with this code:
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.nextLine();
System.out.println("Input:"+s);
}
}
And the input: Testing "Quotes"
You will get this String:
Related
Does anyone have a good recipe for escaping all of the special characters (',%,\,:,{,}) from a String in java, that will be used in an ffmpeg drawtext filter chain? Trying to use replaceAll with different combinations of escaping has been an exercise in frustration!
String myTextString = "Bob's special\cool mix:stuff # 40% off";
Runtime.getRuntime().exec(new String[] { "ffmpeg",...., "filter_complex", "drawtext=enable='between(t,0,10)':x=10:y=10:fontfile=Roboto-Black.ttf:text='" + myTextString + "':fontcolor=#a43ddb:fontsize=14", ... });
ffmpeg drawtext filter: https://ffmpeg.org/ffmpeg-filters.html#drawtext-1
Alright...after banging my head against a wall for getting the right escape patterns to satisfy both java and ffmpeg I came up with this:
MyDrawTextString.replaceAll("\\\\", "\\\\\\\\\\\\\\\\").replaceAll("'", "'\\\\\\\\\\\\\''").replaceAll("%", "\\\\\\\\\\\\%").replaceAll(":", "\\\\\\\\\\\\:");
Looks insane, but it works! Note: I had to double my backslashes in my answer here to get this to display correctly too :-P Dang those backslashes.
The key is ffmpeg drawtext needs 3 backslashes to escape (',%,:) and single quotes need to also be wrapped in a second pair of single quotes. Java String needs 2 backslashes to make one and java replaceAll regex needs to have 2 backslashes to make a single one in a string. Therefore you need (2+2)*3 backslashes to escape things in drawtext filter string!
Just put your text into a text file (e.g. myText.txt) and use the textfile option:
-> myText.txt:
This is my text with special characters: ,(,),'
Then instead of using:
ffmpeg -i test.mpg -vf drawtext="This is my text with special characters :,(,),'"
Use the following command:
ffmpeg -i test.mpg -vf drawtext=textfile=textFile.txt
for Python (in Colab)
Hi, I ran into the same issue using Google Colab and Python. For those looking for a solution, this might help.
I execute the ffmpeg commandline as follows:
!ffmpeg ... -filter_complex "$texts" ...
... where texts refers to a string variable containing the mentioned filteres with drawtext option.
For me worked:
texts = ... # init
def normalize_text(t):
return t\
.replace("\\", "\\\\")\
.replace('"', '""')\
.replace("'", "''")\
.replace("%", "\\%")\
.replace(":", "\\:")
texts = normalize_text(texts) #normalize
!ffmpeg ... #execute
As you can see, escaping it once has worked for me. Note: this function might be extended to include certain other characters which will result in an error message being displayed upon execution, something along the lines of "filter could not be parsed" or "no option XXX" and more.
Thanks guys
I am writing a Java program in which a tab separated values (TSV) file containing two columns of information is read by a BufferedReader and then split into two components (which will serve as [key,value] pairs in a HashMap later in the program) using String.split("\t"). Let's say the first line of the TSV file is as follows:
Key1\tHello world\nProgramming is cool\nGoodbye
The code shown below would separate this line into "Key1" and "Hello world\nProgramming is cool\nGoodbye":
File file = new File("sample.tsv");
BufferedReader br = new BufferedReader(new FileReader(file));
String s = br.readLine();
String[] tokens = new String[2];
tokens = s.split("\t");
The problem now comes in trying to print the second string (i.e. tokens[1]).
System.out.println(tokens[1]);
The line of code above results in the second string being printed with the newline characters (\n) being ignored. In other words, this is printed...
Hello world\nProgramming is cool\nGoodbye
...instead of this...
Hello worldProgramming is coolGoodbye
If I create a new string with the same text as above and use the String.equals() method to compare the two, it returns false.
String str = "Hello world\nProgramming is cool\nGoodbye";
boolean sameString = str.equals(tokens[1]); // false
Why can't special characters in the strings returned by String.split() be printed properly?
BufferedReader.readLine() read your string as one line, as that's how it's represented in the file. Buffered reader didn't read "\n" as ASCII(10) 0x0A, it read "ASCII(92) 0x9C ASCII(110) 0x6E".
If you type the input file the way you expect to see it with your text editor, it will print the way you expect.
on a unix like system:
echo -e "Hello world\nProgramming is cool\nGoodbye" > InputFile.result_you_want
echo "Hello world\nProgramming is cool\nGoodbye" > InputFile.result_you_get
You could use a program like echo to convert your TSV, but then you will need to split on the "\t" character, ASCII(9) 0x09, and not a literal "\t".
Split takes a regular expression. Escaping that tab character may be interesting.
"\t" or "\\t" may do the trick there.
If this is for work, you may want to use a tool or library to work around having to convert your file with echo.
String parsing in Java with delimeter tab "\t" using split has some suggestions there.
Searching for CSV java API's could be very useful. Most will let you set the delimiter character and information on line ending formats.
because in computer aspect, the text '\n' is not like the binary '\n'.
the first line of ur file, i think is like key1 Hello world\nProgramming\ncool
so it's the it can split the \t,but when it comes to print, it only show the text
'\n' but not the binary '\n' which will make the new Line
What should I see when I use the following?
System.out.println("LineSeperator1: "+System.getProperty("line.separator"));
System.out.println("LineSeperator2: "+System.lineSeparator());
I get the following back:
LineSeperator1:
LineSeperator2:
Is it empty? invisible? shouldn there be something like \r or \n?
I use windows 7, eclipse and jdk 1.8.
As you expect, the line separator contains special characters such as '\r' or '\n' that denote the end of a line. However, although they would be written in Java source code with those backslash escape sequences, they do not appear that way when printed. The purpose of a line separator is to separate lines, so, for example, the output of
System.out.println("Hello"+System.lineSeparator()+"World");
is
Hello
World
rather than, say
Hello\nWorld
You can even see this in the output of your code: the output of
System.out.println("LineSeperator1: "+System.getProperty("line.separator"));
had an extra blank line before the output of the next statement, because there was a line separator from System.getProperty("line.separator") and another from the use of println.
If you really want to see what the escaped versions of the line separators look like, you can use escapeJava from Apache Commons. For example:
import org.apache.commons.lang3.StringEscapeUtils;
public class LineSeparators {
public static void main(String[] args) {
String ls1 = StringEscapeUtils.escapeJava(System.getProperty("line.separator"));
System.out.println("LineSeperator1: "+ls1);
String ls2 = StringEscapeUtils.escapeJava(System.lineSeparator());
System.out.println("LineSeperator2: "+ls2);
}
}
On my system, this outputs
LineSeparator1: \n
LineSeparator2: \n
Note that I had to run it in the same folder as the .jar file from the Apache download, compiling and running with these commands
javac -cp commons-lang3-3.4.jar LineSeparators.java
java -cp commons-lang3-3.4.jar:. LineSeparators
Printing something afterwards will show the effect:
System.out.println("a" + System.lineSeparator() + "b");
Gives
a
b
This question already has answers here:
Java Runtime exec() fails to escape characters properly
(4 answers)
Closed 7 years ago.
I am new to Java and trying to convert one of my project from C to Java in order to combine it with another Java program. I'm having difficulty to get correct result when I use Runtime.exec(). I have the following program segment and Java ignores to process the given command.
command1 = "mv output/tsk/dir1/metabolic\\ waste.txt output/converted/file16.txt";
r2 = Runtime.getRuntime();
p2 = r2.exec(command1);
p2.waitFor();
The problem here is the filename "metabolic waste.txt". The same command work when there is no space. I know I have to use escape char for space and I do it. I'm working on Ubuntu btw.
I also tried using
String[] command1 = new String[] {"mv output/tsk/dir1/metabolic\ waste.txt", "output/converted/file16.txt";
but it didn't work.
p.s. the given code is just an example. I don't only use linux mv command. I also run some of the command line tools such as pdf2txt. I still have the same problem of running commands if there is any space in the filename.
SOLVED: I've solved my problem. It's ridiculous that I had to remove escape character and use string array. So, NO ESCAPE CHARACTER for space. The following code just worked for this example and for more general.
source_filepath = "output/tsk/dir1/metabolic waste.txt";
dest_filepath = "output/converted/file16.txt";
String[] str2= {"mv", source_filepath, dest_filepath};
r2 = Runtime.getRuntime().exec(str2);
p2.waitFor();
You have to escape the escape, or enclose the path in quotes:
String[] command1 = new String[] {"mv output/tsk/dir1/metabolic\\ waste.txt", "output/converted/file16.txt"};
String[] command1 = new String[] {"mv \"output/tsk/dir1/metabolic waste.txt\"", "output/converted/file16.txt"};
You have to use \\ because java also uses \ as an escape character, so "\\" really just contains one \
You can enclose the filename in double quotes as follows :
String srcFile = "output/tsk/dir1/metabolic\\ waste.txt"
command1 = "mv " + srcFile +" output/converted/file16.txt";
On OS X, I am trying to .exec something, but when a path contains a space, it doesn't work. I've tried surrounding the path with quotes, escaping the space, and even using \u0020.
For example, this works:
Runtime.getRuntime().exec("open /foldername/toast.sh");
But if there's a space, none of these work:
Runtime.getRuntime().exec("open /folder name/toast.sh");
Runtime.getRuntime().exec("open \"/folder name/toast.sh\"");
Runtime.getRuntime().exec("open /folder\\ name/toast.sh");
Runtime.getRuntime().exec("open /folder\u0020name/toast.sh");
Ideas?
Edit: Escaped backslash... still no worky.
There's a summary of this problem on Sun's forums... seems to be a pretty common issue not restricted to OS X.
The last post in the thread summarizes the proposed solution. In essence, use the form of Runtime.exec that takes a String[] array:
String[] args = new String[] { "open", "\"/folder name/toast.sh\"" };
or (the forum suggests this will work too)
String[] args = new String[] { "open", "folder name/toast.sh" };
Try this:
Runtime.getRuntime().exec("open /folder\\ name/toast.sh");
"\ " will just put a space in the string, but "\ " will put a "\ " in the string, which will be passed to the shell, and the shell will escape the space.
If that doesn't work, pass in the arguments as an array, one element for each argument. That way the shell doesn't get involved and you don't need bizarre escapes.
Runtime.getRuntime().exec(new String[]{"open", "/folder name/toast.sh"});
Paul's option works, but you still must escape the spaces like so:
Runtime.getRuntime().exec(new String[]{"open", "/folder\\ name/toast.sh"});
The thing that sucks about using a String array is that each param and its option must be in their own element. For instance you cannot do this:
Runtime.getRuntime().exec(new String[]{"executable", "-r -x 1", "/folder\\ name/somefile"});
But instead must specify it like so:
Runtime.getRuntime().exec(new String[]{"executable", "-r", "-x", "1", "/folder\\ name/somefile"});
In Kotlin, I was able to escape white spaces using templated strings.
private const val chromeExec = "/Applications/Google
Chrome.app/Contents/MacOS/Google Chrome"
Runtime.getRuntime().exec(arrayOf("$browserExec", url))