我需要编写一个Java方法,以便在一个作业中将postscript文件发送到打印机。换句话说,我需要重现以下Unix命令的效果:
lp -d printer file1.ps file2.ps file3.ps
首先我认为我可以连接PS文件(使用ConcatInputStream和PrintJobWatcher等类)。但由此产生的合并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}")
}
}
}
即使我不想使用外部可执行文件......这个问题对我来说不再重要。如果它不需要调用外部可执行文件,我会接受答案。
答案 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
)