Принтер Ghostscript прекращает печать на определенном количестве страниц - PullRequest
0 голосов
/ 21 февраля 2019

Я настроил PDF-принтер, который использует Ghostscript для преобразования документа в PDF, который затем обрабатывается и используется моим настольным Java-приложением.Он перенаправляет данные принтера через порт RedMon.Для большинства документов, которые я печатаю, он работает нормально и выдает файл PDF, как и ожидалось.Однако с документами с определенным количеством страниц процесс просто останавливается: ошибки не выдается, процесс просто выполняется.Кажется, он не зависит от размера файла или свойств принтера (хотя последний, кажется, влияет на количество печатаемых страниц).

После остановки приложения Java у меня остается документ с фиксированным количеством страниц(обычно 265 страниц, но также заканчивалось 263 страницами или 247 страницами).Вторая до последней страницы неполная (как в частично напечатанных таблицах и текстах), тогда как последняя страница печатается с ошибкой:

ERROR: syntaxerror
OFFENDING COMMAND: --nostringval--

STACK:

/[NUMBER]

Где [NUMBER] - любое заданное однозначное число.

Вот мой класс интегратора Ghostscript:

public class GhostScriptIntegrator {
    public static void createPDF(String[] args, String filename) {
        if (args.length > 0) {
            try {
                Process process = Runtime.getRuntime().exec(
                        args[0] + " -sOutputFile=\"" + filename
                        + "\" -c save pop -f -");

                OutputStream os = process.getOutputStream();
                BufferedReader sc = null;
                try (PrintWriter writer = new PrintWriter(os)) {
                    sc = new BufferedReader(new InputStreamReader(System.in));
                    String line;
                    while ((line = sc.readLine()) != null) {
                        writer.println(line);
                    }
                    writer.flush();
                } catch (Exception ex) {
                    Logger.getLogger(GhostScriptIntegrator.class.getName()).log(Level.SEVERE, null, ex);
                } finally {
                    if (sc != null) {
                        sc.close();
                    }
                }

                process.waitFor();
            } catch (InterruptedException | IOException ex) {
                Logger.getLogger(GhostScriptIntegrator.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}

Параметр args обрабатывается моим виртуальным принтером (аналогично тому, как он был представлен в моем предыдущем посте ):

Полный аргумент:

-jar "C:\Program Files (x86)\Impressora SPE\ImpressoraSPE.jar" "C:\Program Files (x86)\gs\gs9.21\bin\gswin32c -I\"C:\Program Files (x86)\gs\gs9.21\lib\" -dSAFER -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sPAPERSIZE=a4 -q -dPDFA=2 -dPDFACompatibilityPolicy=1 -dSimulateOverprint=true -dCompatibilityLevel=1.3 -dPDFSETTINGS=/screen -dEmbedAllFonts=true -dSubsetFonts=true -dAutoRotatePages=/None -dColorImageDownsampleType=/Bicubic -dColorImageResolution=150"

У меня есть второй виртуальный принтер, который отлично работает, и между ними, похоже, нет существенной разницы: тот жедрайверы, те же аргументы порта, та же настройка, очень похожий код.Тем не менее, он не останавливается после определенного количества страниц, и выходной файл соответствует ожидаемому.

Что заставляет мой принтер перестать отвечать?

1 Ответ

0 голосов
/ 21 февраля 2019

Оказывается, нет проблем с вашим принтером, а скорее с вашим кодом.Более конкретно, как вы [не] обрабатываете потоки времени выполнения.Ваш процесс отсутствует StreamGobbler .

StreamGobbler - это InputStream, который использует внутренний рабочий поток для постоянного потребления ввода из другого InputStream.Он использует буфер для хранения потребляемых данных.Размер буфера автоматически корректируется, если необходимо.

Ваш процесс зависает, потому что не может полностью прочитать входной поток.В следующих статьях дано очень подробное объяснение того, почему это происходит и как это исправить:

Когда Runtime.exec () не будет - Часть 1
Когда Runtime.exec () не будет - Часть 2

Но процитировать саму статью (которая, в свою очередь, цитирует Javadoc JDK):

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

Решение состоит в том, чтобы просто исчерпать каждый входной поток из вашего процесса путем реализации класса StreamGobbler:

public class GhostScriptIntegrator {
    public static void createPDF(String[] args, String filename) throws FileNotFoundException {
        if (args.length > 0) {
            try {
                Process process = Runtime.getRuntime().exec(
                        args[0] + " -sOutputFile=\"" + filename
                        + "\" -c save pop -f -");

                OutputStream os = process.getOutputStream();
                BufferedReader sc = null;
                InputStreamReader ir = new InputStreamReader(System.in);
                try (PrintWriter writer = new PrintWriter(os)) {

                    StreamGobbler errorGobbler = new StreamGobbler(
                            process.getErrorStream(), "ERROR");
                    StreamGobbler outputGobbler = new StreamGobbler(
                            process.getInputStream(), "OUTPUT");

                    errorGobbler.start();
                    outputGobbler.start();

                    sc = new BufferedReader(ir);
                    String line;
                    while ((line = sc.readLine()) != null) {
                        writer.println(line);
                        writer.flush();
                    }
                } catch (IOException ex) {
                    Logger.getLogger(GhostScriptIntegrator.class.getName()).log(Level.SEVERE, null, ex);
                } finally {
                    if (sc != null) {
                        sc.close();
                    }
                    ir.close();
                    if (os != null) {
                        os.close();
                    }
                }

                process.waitFor();
            } catch (InterruptedException | IOException ex) {
                Logger.getLogger(GhostScriptIntegrator.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}

class StreamGobbler extends Thread {

    InputStream is;
    String type;

    StreamGobbler(InputStream is, String type) {
        this.is = is;
        this.type = type;
    }

    public void run() {
        try {
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            long contador = 0;
            while (br.readLine() != null) {
                //Do nothing
            }

        } catch (IOException ex) {
            Logger.getLogger(StreamGobbler.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...