2

我需要编写一个 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。

我在这里读到我可以false 0 startjob pop在 PS 文件之间插入。但那会只有一份工作吗?

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

我没有找到有关该主题的帖子(在一项作业中将多个 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}")
        }

    }
}

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

4

2 回答 2

1

实际上,您不能只循环遍历循环内的文件以获取副本数吗?

IE:

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()

因为如果进程写入大量信息,这不会阻塞:-)

于 2013-08-08T10:57:35.713 回答
0

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

可能有效的一件事是从文件中删除所有注释,这样就不会有误导性的 DSC 信息。(DSC 注释总是以 开头的完整行%%,因此应该使用 RE 替换。s/^%[^$]*$//g

于 2013-08-09T22:11:17.637 回答