I developp a Java application using Windows Desktop Search from which I can retrieve some information about files on my computer such as urls (System.ItemUrl). An example of such url is
file://c:/users/ausername/documents/aninterestingfile.txt
for "normal" files. This field give also urls of mail items indexed from Outlook or Thunderbird. Thunderbird's items (only available using vista and seven) are also files (.wdseml). But outlook's items urls start with "mapi://" like :
mapi://{S-1-5-21-1626573300-1364474481-487586288-1001}/toto#mycompany.com($b423dcd5)/0/Inbox/가가가가곕갘객겒갨겑곓걌게겻겨곹곒갓곅갩갤가갠가
The problem I have is opening the real item from Java in Outlook using this url. If I copy/paste it in the run dialog of Windows, it works ; it also works if I use "start" followed by the copied/pasted url in command line.
The url seems to be encoded in UTF-16. I want to be able to write such code :
String url = "mapi://{S-1-5-21-1626573300-1364474481-487586288-1001}/toto#mycompany.com($b423dcd5)/0/Inbox/가가가가곕갘객겒갨겑곓걌게겻겨곹곒갓곅갩갤가갠가";
Runtime.getRuntime().exec("cmd.exe /C start " + url);
I doesn't work and I've tried other solutions like :
String start = "start";
String url = "mapi://{S-1-5-21-1626573300-1364474481-487586288-1001}/toto#mycompany.com($b423dcd5)/0/Inbox/가가가가곕갘객겒갨겑곓걌게겻겨곹곒갓곅갩갤가갠가";
FileOutputStream fos = new FileOutputStream(new File("test.bat");
fos.write(start.getBytes("UTF16");
fos.write(url.getBytes("UTF16"));
fos.close();
Runtime.getRuntime().exec("cmd.exe /C test.bat");
without any success. Using the solution above, the file "test.bat" contains the correct url and the "start" command, but the run of "test.bat" results in the well known error message :
'■' is not recognized as an internal or external command, operable program or batch file.
Has anybody an idea to be able to open "mapi://" items from Java ?
Well, my question was a little bit tricky. But I finally found an answer and will share it here.
What I suspected was true : Windows uses UTF-16 (little endian) urls. It makes no differences working in UTF-8 when we only use paths to files such as images, text, etc. But to be able to access Outlook items, we must use UTF-16LE. If I were coding in C#, there wouldn't have been any problem. But in Java, you have to be more inventive.
From Windows Desktop Search, I retrieve this:
mapi://{S-1-5-21-1626573300-1364474481-487586288-1001}/toto#mycompany.com($b423dcd5)/0/Inbox/가가가가곕갘객겒갨겑곓걌게겻겨곹곒갓곅갩갤가갠가
And what I did is creating a temporary VB script and run it like this:
/**
* Opens a set of items using the given set of paths.
*/
public static void openItems(List<String> urls) {
try {
// Create VB script
String script =
"Sub Run(ByVal sFile)\n" +
"Dim shell\n" +
"Set shell = CreateObject(\"WScript.Shell\")\n" +
"shell.Run Chr(34) & sFile & Chr(34), 1, False\n" +
"Set shell = Nothing\n" +
"End Sub\n";
File file = new File("openitems.vbs");
// Format all urls before writing and add a line for each given url
String urlsString = "";
for (String url : urls) {
if (url.startsWith("file:")) {
url = url.substring(5);
}
urlsString += "Run \"" + url + "\"\n";
}
// Write UTF-16LE bytes in openitems.vbs
FileOutputStream fos = new FileOutputStream(file);
fos.write(script.getBytes("UTF-16LE"));
fos.write(urlsString.getBytes("UTF-16LE"));
fos.close();
// Run vbs file
Runtime.getRuntime().exec("cmd.exe /C openitems.vbs");
} catch(Exception e){}
}
Related
I am trying to open a file on a Grails server but the problem is that my path contains special characters such as Ç
It worked fine on my OSX environment, but since I uploaded it to the linux production environment, the error "No such file or directory" pops out
The locale is set to fr_FR.UTF-8
EDIT:
Here is the code I am using to reach the file
def reportSystemPath = (pathPrefix + "/${report.cluster.name}" + report.path).replaceAll("//", "/")
Path path = Paths.get(reportSystemPath)
def bytes = byte[]
path.toFile().withInputStream() {
bytes = it.getBytes()
}
I am new to perl but have done some programming in java facing a problem in running the perl script present in the jar file .
I am using windows and I have written a perl script to convert one type of file to another type .
I have checked the perl script with the java program using the Runtime and I am able to run the same as required and i am getting the output converted files as well (using the cmd line)
I have created a GUI in java to get the files to convert to the target files . I am able to run the file from netbeans IDE as will .
But when I am trying to run the jar file .
I am using URL to get the URL to the perl script .
URL url = this.getClass().getResource("/com/MyProject/FileConverter/fileconverter.pl");
and Runtime for Executing the script :
String[] cmd = {"perl",path,input_file,output_file};
process = Runtime.getRuntime().exec(cmd);
Please help in resolving the issue . Basically i do need to know how we can run the perl script present in the same jar file that we are executing.
You will have to read that perl file as resource and write it somewhere on file system as File (like this) and then pass that path to your command
See Also
Extract and load DLL from JAR
I'm assuming you have your perl script file in you jar and you don't want to extract it, just execute it "from inside".
One solution is to get the "stream" of your "resource" (your perl script), and then execute "perl" writing your script in the process' standard input.
This is better explained with a piece of code:
IMPORTANT CAVEAT: the path to your script in getResourceAsStream shouldn't start with /
// Start the process "perl"
Process process = Runtime.getRuntime().exec("perl");
// get the script as an InputStream to "inject" it to perl's standard input
try (
InputStream script = ClassLoader.getSystemClassLoader()
.getResourceAsStream("com/MyProject/FileConverter/fileconverter.pl");
OutputStream output = process.getOutputStream()
) {
// This is to "inject" your input and output file,
// as there is no other easy way ot specify command line arguments
// for your script
String firstArgs = "$ARGV[0] = \"" + input_file + "\";\n" +
"$ARGV[1] = \"" + output_file + "\";\n";
output.write(firstArgs.getBytes());
// send the rest of your cript to perl
byte[] buffer = new byte[2048];
int size;
while((size = script.read(buffer)) != -1) {
output.write(buffer, 0, size);
}
output.flush();
}
// just in case... wait for perl to finish
process.waitFor();
I'm trying to convert files from png's to pdf using imagemagick and Java. I've got everything working to a place when I'm executing imagemagick command to actually merge multiple png's into one pdf. The command itself looks properly, and it works fine when executed in the terminal but my application gives me error showing that imgck can't open the file (even though it exists and I've set permissions to the folder to 777 :
line: convert: unable to open image `"/Users/mk/Documents/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/sch-java/print-1357784001005.png"': No such file or directory # error/blob.c/OpenBlob/2642.
This is my command :
/opt/local/bin/convert "/Users/mk/Documents/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/sch-java/print-1357784001005.png" "/Users/mk/Documents/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/sch-java/print-1357784001219.png" "/Users/mk/Documents/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/sch-java/complete-exportedPanel2013-01-1003:13:17.212.pdf"
And my Java code :
String filesString = "";
for (String s : pdfs){
filesString += "\""+ s + "\" ";
}
Process imgkProcess = null;
BufferedReader br = null;
File f1 = new File(pdfs[0]);
//returns true
System.out.println("OE: "+f1.exists());
String cmd = imgkPath+"convert "+ filesString+ " \""+outputPath+outName+"\"";
try {
imgkProcess = Runtime.getRuntime().exec(cmd);
InputStream stderr = imgkProcess.getErrorStream();
InputStreamReader isr = new InputStreamReader(stderr);
br = new BufferedReader(isr);
} catch (IOException e1) {
msg = e1.getMessage();
}
imgkProcess.waitFor();
while( (line=br.readLine() ) != null){
System.out.println("line: "+line);
}
The whole code is executed from a java servlet controller after getting request from a form. Any ideas what can cause this ? I'm using latest imgck, jdk, and osx 10.7 .
A few things:
When spawning anything but really trivial processes, it's usually better to use ProcessBuilder than Runtime.exec() - it gives you much better control
Even with ProcessBuilder, it often works better to write a shell script that does what you need. Then spawn a process to run the script. You get a lot more control in shell script than you do in ProcessBuilder
Remember that a spawned process is not a shell. It can't, for instance, evaluate expressions, or expand shell variables. If you need that, then you must execute a shell (like sh or bash). Better yet, write a shell script as described above
If all you need to do is to execute some ImageMagick commands, it would probably be easier to jmagick, a Java interface to ImageMagick - see http://www.jmagick.org/
Actually, since the you're assembling images into a PDF, the iText library - http://itextpdf.com is probably the best tool for the job, as it is native Java code, does not require spawning a native process, and will therefore be much more portable.
Solved it by adding all arguments to an arrayList and then casting it to String array.
ArrayList<String> cmd = new ArrayList<String>();
cmd.add(imgkPath+"convert");
for (int i=0, l=pdfs.length; i<l; i++){
cmd.add(pdfs[i]);
}
cmd.add(outputPath+outName);
imgkProcess = Runtime.getRuntime().exec(cmd.toArray(new String[cmd.size()]));
The issue I am struggling with now is the following. I have a zip archive on a remote server. The eclipse plug-in I have developed downloads this archive using the suggestion from this forum:
//Connect readable channel to the URL
ReadableByteChannel rbc = Channels.newChannel(libraryUrl.openStream());
//Create local file
FileOutputStream fos = new FileOutputStream(libraryZipPath);
//Download the remote archive to the local file
fos.getChannel().transferFrom(rbc, 0, libraryUrl.openConnection().getContentLength());
//Close channel
fos.close();
I have an html file at the server that counts visit statistics for the web-page. The javascript that does counting is as follows:
var data = '&r=' + escape(document.referrer) + '&n=' + escape(navigator.userAgent)
+ '&p=' + escape(navigator.userAgent) + '&g=' + escape(document.location.href);
if (navigator.userAgent.substring(0,1)>'3')
data = data + '&sd=' + screen.colorDepth + '&sw=' + escape(screen.width+'x'+screen.height);
document.write('<a href="http://www.1freecounter.com/stats.php?i=89959" target=\"_blank\">');
document.write('<img alt="Free Counter" border=0 hspace=0 '+'vspace=0 src="http://www.1freecounter.com/counter.php?i=89959' + data + '">');
document.write('</a>');
The question is: Is it somehow possible to use this javascript or html file with it to count the download statistics for the archive file?
You are using a third party webcounter which is embedded as a graphic in your website. When the users browser loads this graphic, the third party server notices the access and increments the counter.
This doesn't work for binary downloads, because when a binary file is downloaded, the webcounter graphic isn't requested.
What you could try is to make your Java program also download the counter graphic when it downloads the binary file. Make sure to pass the URL of the zip archive as Referrer HTTP header to the image download so that the script on the server counts it as access to it. You will have to use the URLConnection class in order to set custom HTTP headers like Referrer.
Thank you for the reply, Philipp!
I have figured out how to make it work in a very simple way. Let us consider a counter in the example above ("http://www.1freecounter.com/stats.php?i=89959"). The counter by that address takes 6 parameters in total:
r - document referrer,
n and p are user agent, which consists of a browser name, OS name, OS ver, browser ver etc.,
g is the location,
sd and sw are the colour depth and the screen size (we can skip these two for a binary file).
Then, we form a string for a counting request. For instance,
String cntURL = "http://www.1freecounter.com/counter.php?i=89959&r="+
URLEncoder.encode("some string for a referrer","UTF-8") + "&n="+
URLEncoder.encode("browser name (OS name OS version) browser version", "UTF-8")+"&p="+
URLEncoder.encode("the same as above", "UTF-8")+"&g=<location string>";
Notice that the parameters are encoded into utf-8 character set. Otherwise, the counter will not count the access properly.
Then, simply using URL class, we create an URL object and open a steam:
URL statsUrl = new URL(cntURL);
statsUrl.openStream();
That is it! There is no need to research what parameters are in http header. It is simply a matter of forming a proper string to which to open a connection.
I have written a simple method that retrieves all info required for the request and have inserted a call to it in a method where I download the file from a server.
I need to find out default file opener for a given file on Windows so that I can customize the command arguments and open the file with the default opener/viewer.
My real usage scenario is opening multiple multimedia files with user's default media player so that all the files will be added to user's playlist (For the players that can open multiple files on the same intance). For operating system other than Windows I use Desktop.open(File file) method (I simply does not concern opening multiple files feature for OSs other than Windows), I cannot find any method which I can open multiple files other than customizing command arguments and running it using exec() method of the Runtime class. I use somethig similar to this:
private void playItems2(List<File> fileList, String playerBinary) {
String args = " ";
for (File file : fileList) {
args += "\"" + file.getAbsolutePath() + "\" ";
}
try {
String command = playerBinary + args;
Runtime rt = Runtime.getRuntime();
Process p = rt.exec(command);
} catch (Exception exc) {/*handle exception*/
System.err.println("Run Player Exc:" + exc.getMessage());
}
}
I am using user specified path for the playerBinary, what I need to is automatically detecting default player for the first item of fileList and use it as playerBinary.
I have also looked at Rundll32.exe and cmd.exe /start solutions but they did not work for my usage scenario.
This question should not be confused with this and this.
Use this approach to call default opener and enjoy!
public void playItems2(...) throws Exception {
...
Process p = Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler c:/mp3/myfile.mp3");
p.waitFor();
...
}
Cannot do with pure Java alone.
In case of Windows, you need to read registry. Suppose you need to find out file association for .mp3
In the windows registry, look the default value for
HKEY_CLASSES_ROOT\.mp3. Usually its
"mp3file".
Now look for
HKEY_CLASSES_ROOT\mp3file\shell\open\command.
The value in there is a string
pointing to an executable to open
.mp3 files with.
Now this cant be done in Java, you need to choose appropriate 3rd party lib to do this for you.