在一个作业中打印多个poscripts

时间:2013-08-08 09:34:34

标签: printing groovy jobs postscript

我需要编写一个Java方法,以便在一个作业中将postscript文件发送到打印机。换句话说,我需要重现以下Unix命令的效果:

lp -d printer file1.ps file2.ps file3.ps

首先我认为我可以连接PS文件(使用ConcatInputStreamPrintJobWatcher等类)。但由此产生的合并PS文件并不总是有效。

如果有帮助,这是我当前的代码(我被要求在Groovy中执行):

/**
 * Prints the {@code files} {@code copyCount} times using 
 * {@code printService}.
 * <p>
 * Exceptions may be thrown.
 * @param printService Print service
 * @param files Groovy array of {@code File} objects
 * @param copyCount Number of copies to print
 */
private static void printJob(
        PrintService printService, 
        def files, 
        int copyCount) {

    // No multiple copy support for PS file, must do it manually
    copyCount.times { i ->

        InputStream inputStream = null
        try {

            log.debug("Create stream for copy #${i}")
            inputStream = new ConcatInputStream()
            for (def file in files) {
                if (file != null) {
                    log.debug("Add '${file.absolutePath}' to the stream")
                    ((ConcatInputStream)inputStream).addInputStream(
                            new FileInputStream(file))
                }
            }

            log.debug("Create document")
            Doc doc = new SimpleDoc(
                    inputStream, DocFlavor.INPUT_STREAM.AUTOSENSE, null)

            log.debug("Create print job")
            DocPrintJob docPrintJob = printService.createPrintJob()

            log.debug("Create watcher")
            PrintJobWatcher watcher = new PrintJobWatcher(docPrintJob)

            log.debug("Print copy #${i}")
            docPrintJob.print(doc, null)

            log.debug("Wait for completion")
            watcher.waitForDone()

        } finally {
            if (inputStream) log.debug("Close the stream")
            inputStream?.close()
        }
    }
}

我不允许将PS转换为PDF格式。

我读了here我可以在PS文件之间插入false 0 startjob pop。但那么只有一份工作吗?

我可能会混淆“工作”的概念......

我没有找到关于该主题的帖子(在一个作业中向打印机发送多个PS文件)。解决方案可能非常明显,它使我失明,这就是我发布这个问题的原因。

我的下一次尝试是从课堂上执行lp,即使它看起来很脏我知道我可以让它以这种方式工作......如果你知道一种更简单的方法,请告诉我。

修改

执行lp(如下所示)效果很好:

/**
 * Prints the {@code files} {@code copyCount} times using an executable.
 * <p>
 * Exceptions may be thrown.
 * @param config ConfigObject containing closures for building the
 *      command line to the printing executable, and to analyze the
 *      return code. Example of config file:
 * 
 * print {
 *      commandClosure = { printerName, files -> 
 *          [
 *              'lp', 
 *              '-d', printerName, 
 *              files.collect{ it.absolutePath }
 *          ].flatten()
 *      }
 *      errorClosure = { returnCode, stdout, stderr -> returnCode != 0 }
 *      warnClosure = { returnCode, stdout, stderr -> 
 *          !stderr?.isAllWhitespace() }
 *  }
 * 
 * @param printerName Printer name
 * @param files Groovy array of {@code File} objects
 * @param copyCount Number of copies to print
 */
private static void printJob(
        ConfigObject config,
        String printerName, 
        def files, 
        int copyCount) {

    files.removeAll([null])

    Integer copyCount = job.copyCountString.toInteger()
    copyCount.times { i ->

        def command = config.print.commandClosure(printerName, files)
        log.debug("Command: `" + command.join(' ') + "`")

        def proc = command.execute()
        proc.waitFor()

        def returnCode = proc.exitValue()
        def stdout = proc.in.text
        def stderr = proc.err.text
        def debugString = "`" + command.join(' ') + 
                    "`\nReturn code: " + returnCode + 
                    "\nSTDOUT:\n" + stdout + "\nSTDERR:\n" + stderr

        if (config.print.errorClosure(returnCode, stdout, stderr)) {
            log.error("Error while calling ${debugString}")
            throw new PrintException("Error while calling ${debugString}")
        } else if (config.print.warnClosure(returnCode, stdout, stderr)) {
            log.warn("Warnings while calling ${debugString}")
        } else {
            log.debug("Command successful ${debugString}")
        }

    }
}

即使我不想使用外部可执行文件......这个问题对我来说不再重要。如果它不需要调用外部可执行文件,我会接受答案。

2 个答案:

答案 0 :(得分:1)

实际上,你不能只循环遍历循环中的文件以获得拷贝数吗?

即:

private static void printJob( PrintService printService, def files, int copyCount) {
    // No multiple copy support for PS file, must do it manually
    copyCount.times { i ->
        log.debug( "Printing Copy $i" )
        files.each { file ->
            log.debug( "Printing $file" )
            file.withInputStream { fis ->
                Doc doc = new SimpleDoc( fis, DocFlavor.INPUT_STREAM.AUTOSENSE, null )
                DocPrintJob docPrintJob = printService.createPrintJob()
                PrintJobWatcher watcher = new PrintJobWatcher( docPrintJob )
                docPrintJob.print( doc, null )
                watcher.waitForDone()
            }
        }
    }
}

(未测试的)

修改

作为上述解决方法的更新,而不是:

    def proc = command.execute()
    proc.waitFor()

    def returnCode = proc.exitValue()
    def stdout = proc.in.text
    def stderr = proc.err.text

你可能会更好:

    def proc = command.execute()
    def out = new StringWriter()
    def err = new StringWriter()
    ps.consumeProcessOutput( out, err )
    ps.waitFor()

    def returnCode = proc.exitValue()
    def stdout = out.toString()
    def stderr = err.toString()

如果进程写入大量信息,则不会阻止: - )

答案 1 :(得分:0)

其中一个问题可能与文件结构公约(DSC)评论有关。这些注释提供有关文件中包含的文档的元数据。像ghostscript这样的工具应该能够处理生成的连接文件,因为它完全忽略了DSC注释,只是处理postscript。但是,当第一个文件结束时(由End注释标记)并且文件中有更多数据,期望在符合DSC的文件上工作的工具将会混淆。

可能有用的一件事是从文件中删除所有注释,因此没有误导性的DSC信息。 (DSC评论将始终是以%%开头的整行,因此RE替换应该这样做。s/^%[^$]*$//g