5

My Question: How do I open a file (in the system default [external] program for the file) without saving the file to disk?

My Situation: I have files in my resources and I want to display those without saving them to disk first. For example, I have an xml file and I want to open it on the user's machine in the default program for reading xml file without saving it to the disk first.

What I have been doing: So far I have just saved the file to a temporary location, but I have no way of knowing when they no longer need the file so I don't know when/if to delete it. Here's my SSCCE code for that (well, it's mostly sscce, except for the resource... You'll have to create that on your own):

package main;

import java.io.*;

public class SOQuestion {

  public static void main(String[] args) throws IOException {
    new SOQuestion().showTemplate();
  }

  /** Opens the temporary file */
  private void showTemplate() throws IOException {
    String tempDir = System.getProperty("java.io.tmpdir") + "\\BONotifier\\";
    File parentFile = new File(tempDir);
    if (!parentFile.exists()) {
      parentFile.mkdirs();
    }
    File outputFile = new File(parentFile, "template.xml");
    InputStream inputStream = getClass().getResourceAsStream("/resources/template.xml");
    int size = 4096;
    try (OutputStream out = new FileOutputStream(outputFile)) {
      byte[] buffer = new byte[size];
      int length;
      while ((length = inputStream.read(buffer)) > 0) {
        out.write(buffer, 0, length);
      }
      inputStream.close();
    }
    java.awt.Desktop.getDesktop().open(outputFile);
  }
}
kentcdodds
  • 27,113
  • 32
  • 108
  • 187
  • This depends on what the program is you are trying to load the file into. Does it have some API or listing on some port? Depending on your OS, you may be able to delete the file even while it is still in use by the program -- this way you can use your current approach without having to worry about when the user is done viewing it. – martinez314 Oct 18 '12 at 21:49
  • @whiskeyspider: Well, with the Desktop class it determines the default automatically. I'd love a multi-platform solution if it's possible :) – kentcdodds Oct 18 '12 at 22:00
  • http://superuser.com/questions/430466/in-windows-can-i-redirect-stdout-to-a-named-pipe-in-command-line – Blessed Geek Oct 18 '12 at 22:53

3 Answers3

4

Because of this line:

String tempDir = System.getProperty("java.io.tmpdir") + "\\BONotifier\\";

I deduce that you're working on Windows. You can easily make this code multiplatform, you know.

The answer to your question is: no. The Desktop class needs to know where the file is in order to invoke the correct program with a parameter. Note that there is no method in that class accepting an InputStream, which could be a solution.

Anyway, I don't see where the problem is: you create a temporary file, then open it in an editor or whatever. That's fine. In Linux, when the application is exited (normally) all its temporary files are deleted. In Windows, the user will need to trigger the temporary files deletion. However, provided you don't have security constraints, I can't understand where the problem is. After all, temporary files are the operating system's concern.

Baltasarq
  • 12,014
  • 3
  • 38
  • 57
  • Thanks for the tips. +1 if you can point me in a good direction to make this multi-platform :) Though I appreciate your answer and will probably upvote it anyway... – kentcdodds Oct 18 '12 at 21:58
  • That's very easy. Instead of using '\\' as the directory separator, use the char/String constant. This constant will let your program change from '\\' in Windows to '/' in Linux automatically, instead of relaying in one of them.http://docs.oracle.com/javase/1.4.2/docs/api/java/io/File.html#separatorChar – Baltasarq Oct 19 '12 at 08:16
1

Depending on how portable your application needs to be, there might be no "one fits all" solution to your problem. However, you can help yourself a bit:

At least under Linux, you can use a pipe (|) to direct the output of one program to the input of another. A simple example for that (using the gedit text editor) might be:

echo "hello world" | gedit

This will (for gedit) open up a new editor window and show the contents "hello world" in a new, unsaved document.


The problem with the above is, that this might not be a platform-independent solution. It will work for Linux and probably OS X, but I don't have a Windows installation here to test it.

Also, you'd need to find out the default editor by yourself. This older question and it's linked article give some ideas on how this might work.

Community
  • 1
  • 1
Lukas Knuth
  • 25,449
  • 15
  • 83
  • 111
0

I don't understand your question very well. I can see only two possibilities to your question.

  1. Open an existing file, and you wish to operate on its stream but do not want to save any modifications.

  2. Create a file, so that you could use file i/o to operate on the file stream, but you don't wish to save the stream to file.

In either case, your main motivation is to exploit file i/o existingly available to your discretion and programming pleasure, am I correct?

I have feeling that the question is not that simple and this my answer is probably not the answer you seek. However, if my understanding of the question does coincide with your question ...

If you wish to use Stream io, instead of using FileOutputStream or FileInputStream which are consequent to your opening a File object, why not use non-File InputStream or OutputStream? Your file i/o utilities will finally boil down to manipulating i/o streams anyway.

http://docs.oracle.com/javase/7/docs/api/java/io/OutputStream.html

http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html

No need to involve temp files.

Blessed Geek
  • 21,058
  • 23
  • 106
  • 176