Как открыть файл, не сохраняя его на диск

Мой вопрос: как открыть файл (в системной [внешней] программе по умолчанию для файла) без сохранения файла на диск?

Моя ситуация: у меня есть файлы в моих ресурсах, и я хочу отобразить их без предварительного сохранения на диск. Например, у меня есть файл xml, и я хочу открыть его на машине пользователя в программе по умолчанию для чтения файла xml без предварительного сохранения на диск.

Что я делал: до сих пор я просто сохранял файл во временном расположении, но я не могу знать, когда им больше не нужен файл, поэтому я не знаю, когда и если удали это. Вот мой код SSCCE для этого (ну, в основном это sscce, за исключением ресурса... Вам придется создайте это самостоятельно):

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);
  }
}

person kentcdodds    schedule 18.10.2012    source источник
comment
Это зависит от того, в какую программу вы пытаетесь загрузить файл. Есть ли у него какой-то API или список на каком-то порту? В зависимости от вашей ОС вы можете удалить файл, даже если он все еще используется программой — таким образом вы можете использовать свой текущий подход, не беспокоясь о том, когда пользователь закончит его просмотр.   -  person martinez314    schedule 19.10.2012
comment
@whiskeyspider: Ну, с классом Desktop он автоматически определяет значение по умолчанию. Я бы хотел мультиплатформенное решение, если это возможно :)   -  person kentcdodds    schedule 19.10.2012
comment
superuser.com/questions/430466/   -  person Blessed Geek    schedule 19.10.2012


Ответы (3)


Из-за этой строки:

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

Я делаю вывод, что вы работаете в Windows. Знаете, вы можете легко сделать этот код мультиплатформенным.

Ответ на ваш вопрос: нет. Класс Desktop должен знать, где находится файл, чтобы вызвать правильную программу с параметром. Обратите внимание, что в этом классе нет метода, принимающего InputStream, что может быть решением.

Во всяком случае, я не вижу, в чем проблема: вы создаете временный файл, а затем открываете его в редакторе или где-то еще. Это нормально. В Linux при выходе из приложения (обычно) все его временные файлы удаляются. В Windows пользователю необходимо инициировать удаление временных файлов. Однако, если у вас нет ограничений безопасности, я не могу понять, в чем проблема. В конце концов, временные файлы — это забота операционной системы.

person Baltasarq    schedule 18.10.2012
comment
Спасибо за советы. +1, если вы можете указать мне хорошее направление, чтобы сделать эту мультиплатформенную :) Хотя я ценю ваш ответ и, вероятно, все равно поддержу его... - person kentcdodds; 19.10.2012
comment
Это очень легко. Вместо использования '\\' в качестве разделителя каталогов используйте константу char/String. Эта константа позволит вашей программе автоматически измениться с '\\' в Windows на '/' в Linux, вместо ретрансляции в одном из них.docs.oracle.com/javase/1.4.2/docs/api/java/io/ - person Baltasarq; 19.10.2012

В зависимости от того, насколько переносимым должно быть ваше приложение, для вашей проблемы может не быть универсального решения. Однако вы можете немного помочь себе:

По крайней мере, под Linux вы можете использовать канал (|), чтобы направить вывод одной программы на ввод другой. Простым примером для этого (с использованием текстового редактора gedit) может быть:

echo "hello world" | gedit

Это (для gedit) откроет новое окно редактора и покажет содержимое «hello world» в новом несохраненном документе.


Проблема с вышеизложенным заключается в том, что это может быть решение, не зависящее от платформы. Он будет работать для Linux и, возможно, для OS X, но у меня нет установки Windows, чтобы протестировать его.

Кроме того, вам нужно будет самостоятельно найти редактор по умолчанию. Этот старый вопрос и его < href="http://www.javaworld.com/javaworld/javatips/jw-javatip66.html" rel="nofollow noreferrer">связанная статья дает некоторые идеи о том, как это может работать.

person Lukas Knuth    schedule 18.10.2012

Я не очень хорошо понимаю ваш вопрос. Я вижу только два варианта ответа на ваш вопрос.

  1. Откройте существующий файл, и вы хотите работать с его потоком, но не хотите сохранять какие-либо изменения.

  2. Создайте файл, чтобы можно было использовать файловый ввод-вывод для работы с файловым потоком, но вы не хотите сохранять поток в файл.

В любом случае, ваша основная мотивация состоит в том, чтобы использовать файловый ввод-вывод, доступный на ваше усмотрение, и удовольствие от программирования, я прав?

У меня такое чувство, что вопрос не так прост, и мой ответ, вероятно, не тот ответ, который вы ищете. Однако, если мое понимание вопроса действительно совпадает с вашим вопросом...

Если вы хотите использовать Stream io вместо использования FileOutputStream или FileInputStream, которые являются следствием открытия вами объекта File, почему бы не использовать нефайловый InputStream или OutputStream? Ваши утилиты файлового ввода-вывода в конечном итоге сведутся к манипулированию потоками ввода-вывода.

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

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

Не нужно задействовать временные файлы.

person Blessed Geek    schedule 18.10.2012
comment
Я отредактировал свой вопрос. Надеюсь, это поможет вам понять, о чем я прошу. - person kentcdodds; 19.10.2012