Передача данных через внешнее приложение в Windows с использованием Java - PullRequest
3 голосов
/ 20 января 2011

У меня есть Java-приложение с InputStream, которое копирует данные в OutputStream.Я хочу сжать данные из InputStream с помощью FreeArc, прежде чем записать их в OutputStream.

Проблема в том, что нет Java-API против FreeArc.Поэтому мне нужно как-то передать его через командную строку exe.Т.е. мне нужно обмануть FreeArc тем, что он читает и записывает два файла, когда фактически читает из моего InputStream и записывает в мой OutputStream.В Unix это довольно просто, но я должен заставить эту работу работать в Windows.

Как вы предлагаете мне это сделать?Есть ли способ получить доступ к именованным каналам Windows в Java или я могу сделать это через сокеты?Что-то другое?Это будет сделано ~ 1 / сек, поэтому накладные расходы не могут быть слишком высокими.

Ответы [ 3 ]

2 голосов
/ 20 января 2011

Если freearc может принимать входные данные из стандартного входа и отправлять выходные данные в стандартный выходной сигнал, тогда для вызова команды можно использовать ProcessBuilder, а возвращенный экземпляр Process будет представлять стандартный ввод внешнего процессаи вывод.

1 голос
/ 27 октября 2011

Вот пример, взятый из кода, предназначенного для преобразования EPS в PDF с помощью GhostScript:

  // Start the script as OS process.
  ProcessBuilder pb = new ProcessBuilder(gsExecutable, pdfFileName, epsFile.getName());
  pb.directory(gsDir);
  pb.redirectErrorStream(true);
  Process proc = pb.start();
  final InputStream stdErrInStream = proc.getErrorStream();
  final InputStream stdOutInStream = proc.getInputStream();

  // Read the STDERR-Stream.
  String className = EpsToJpegConverter.class.getName();
  final ByteArrayOutputStream stdErrOutStream = new ByteArrayOutputStream();
  new Thread(new Runnable() {
    @Override
    public void run() {
      try {
        byte[] buf = new byte[16];
        int len = -1;
        while ((len = stdErrInStream.read(buf)) != -1) {
          stdErrOutStream.write(buf, 0, len);
        }
        stdErrFertig = true;
      } catch (IOException e) {
        log.error(e.getLocalizedMessage(), e);
      }
    }
  }, className + " Script STDERR Reader").start();

  // Read the STDOUT-Stream.
  final ByteArrayOutputStream stdOutOutStream = new ByteArrayOutputStream();
  new Thread(new Runnable() {
    @Override
    public void run() {
      try {
        byte[] buf = new byte[4096];
        int len = -1;
        while ((len = stdOutInStream.read(buf)) != -1) {
          stdOutOutStream.write(buf, 0, len);
        }
        stdOutFertig = true;
      } catch (IOException e) {
        log.error(e.getLocalizedMessage(), e);
      }
    }
  }, className + " Script STDOUT Reader").start();

  // Wait for the process to finish.
  int waitFor = proc.waitFor();
  if (waitFor != 0) {
    // If an error occured, the return code is != 0.
    // In this case wait for the reading threads to finish.
    while (!stdOutFertig || !stdErrFertig) {
      Thread.sleep(100);
    }
    throw new EpsConverterException("Das Konvertierungsscript " + gsExecutable
        + " wurde nicht erfolgreich ausgeführt.\nStandardausgabe:\n" + new String(stdOutOutStream.toByteArray())
        + "\nFehlerausgabe:\n" + new String(stdErrOutStream.toByteArray()));
  }

НТН.

Edit: Возможно, код, который читает преобразованные байты изображения назад, также представляет интерес:

  // If everything worked out ok, read the PDF.
  pdfFile = new File(gsDir, pdfFileName);
  FileInputStream pdfInStream = new FileInputStream(pdfFile);
  int len = -1;
  byte[] buf = new byte[4096];
  ByteArrayOutputStream pdfBAOS = new ByteArrayOutputStream(65535);
  while ((len = pdfInStream.read(buf)) != -1) {
    pdfBAOS.write(buf, 0, len);
  }
  pdfInStream.close();

  byte[] res = pdfBAOS.toByteArray();
  return res;
0 голосов
/ 02 ноября 2011

Я бы предложил использовать сжатие ZIP, являющееся частью библиотеки J2SE (см. java.util.zip документы), если только использование FreeArc не дает огромных преимуществ в производительности (скажем, 1 секунда против 10 секунд), или ZIP не обеспечивает хорошего достаточно сжатия. Если вы заинтересованы в использовании FreeArc, есть несколько вариантов различной сложности:

  1. Скопируйте ваш ввод в файл, запустите утилиту для него, используя ProcessBuilder, затем перенесите сжатый файл на выход. Вы должны использовать каналы NIO вместо потоков - это может немного снизить издержки ввода-вывода (особенно для отправки). Это единственное, что вы можете сделать с чистой Java, и явно не лучшим с точки зрения производительности.
  2. Используйте JNI + собственный API FreeArc (если есть, и он позволяет работать с потоками / байтовыми буферами).
  3. Используйте JNI + собственный Windows API для создания именованного канала, который соединит ваше приложение и FreeArc, и вы сможете работать с этим почти так же, как с обычным файлом.

Наконец, вы можете уменьшить файловый ввод-вывод, если входной или выходной файл является файлом. Например. если вы читаете из файла - просто запустите FreeArc непосредственно для него, а затем отправьте сжатый файл на выход. Также это может не стоить всех этих проблем, если: а) размер данных относительно мал - возможно, до нескольких мегабайт; или б) сжатие не уменьшает его резко

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...