首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Ghost4J PDF到图像转换

Ghost4J PDF到图像转换
EN

Code Review用户
提问于 2014-02-21 16:18:07
回答 2查看 9.2K关注 0票数 6

此代码的主要目标是将PDF文件转换为图像。我还在C:/Media下创建了一个目录,该目录基于PDF名称和当前日期的组合,并将上传的PDF插入到与图像相同的目录中,以便安全保存。

我主要担心的是,我初始化了太多变量和将PDF移动到新创建的目录中的过程过于复杂。我正在寻找关于如何改进这个代码的指导或建议。

代码语言:javascript
复制
public class PdfService {   

public static void main(String[] args) {

    System.out.println("Test of Convert to PNG");
    convertPDFtoImage(args[0]);
 }  

public static void convertPDFtoImage(String PDFFileName) {

    try {

         // load PDF document
         PDFDocument document = new PDFDocument();
         File baseFile = new File(PDFFileName);
         document.load(baseFile);


         //Get todays date as a String so that you can append it to the directory
         String df = new SimpleDateFormat("MM-dd-yy").format(new Date());

         //Get the filename without extension so that you can create a directory based on the name
         Path path = Paths.get(PDFFileName);    
         String filenameWithExtension = path.getFileName().toString();
         String filename = FilenameUtils.removeExtension(filenameWithExtension);

         //add the current date to the filename to get the directory name
         String dirname = filename + "-" + df;        

         //Create the directory
         Path dir =  Paths.get("C:\\Media\\" + dirname);
         Files.createDirectory(dir);

         //Move the pdf to the newly created directory
         movePDFToDirectory(baseFile, dirname, filenameWithExtension);

         // create renderer
         SimpleRenderer renderer = new SimpleRenderer();

         // set resolution (in DPI)
         renderer.setResolution(150);

         // render
         List<Image> images = renderer.render(document);

         // write images to files to disk as JPEG
            try {

                System.out.println("Begin converting PDF...");

                for (int i = 0; i < images.size(); i++) {
                    ImageIO.write((RenderedImage) images.get(i), "jpeg", new File("C:\\Media\\" + dirname + "\\" + filename + "_" + (i + 1) + ".jpeg"));
                }

                System.out.println("PDF converted to image(s) successfully.");


            } catch (IOException e) {
                System.out.println("ERROR: " + e.getMessage());
            }

       } catch (Exception e) {
         System.out.println("ERROR: " + e.getMessage());
       }
}

public static void movePDFToDirectory(File originalFile, String directory, String filename) {
        InputStream inStream = null;
        OutputStream outStream = null;

        try{


            File newFile = new File("C:\\Media\\" + directory + "\\" + filename);

            inStream = new FileInputStream(originalFile);
            outStream = new FileOutputStream(newFile);

            byte[] buffer = new byte[1024];

            int length;
            //copy the file content in bytes 
            while ((length = inStream.read(buffer)) > 0){

                outStream.write(buffer, 0, length);

            }

            inStream.close();
            outStream.close();

            System.out.println("Original PDF has been copied successfully!");

        }catch(IOException e){
            e.printStackTrace();
        }

}
}

备注:

  • 最后,我计划将这段代码移动到一个web应用程序中,该应用程序接受图像作为上传。目前,我只是将文件位置作为main方法中的一个参数传递。
  • 我计划在移动目录时使基目录(C:/Media)成为一个动态变量。
EN

回答 2

Code Review用户

回答已采纳

发布于 2014-02-21 17:52:13

+1 @Marc-Andre和其他注释:

  1. movePDFToDirectory:Apache:FileUtils.copyFile(java.io.File, java.io.File)中有类似的方法。幸运的是,它是Ghost4J的一个依赖项,所以它已经在类路径上了,您只需要使用它并删除movePDFToDirectory。Commons是开源的。看到它处理的角落案例很有趣,比如比较destFile.length()srcFile.length(),以确保所有内容都被正确复制。有效Java,第二版,第47项:了解和使用库(作者只提到JDK的内置库,但我认为其他库也是如此。)
  2. 如果有人在没有任何参数的情况下调用该程序,它将抛出一个ArrayIndexOutOfBoundsException。一个正确的错误信息与预期的参数将是更友好的用户和专业。
  3. 我会将main方法移动到一个单独的类中。(例如,PdfConverterMain.)将类与其客户端分离通常是一个好主意。
  4. 下面的一行确实很难理解: ImageIO.write(( renderedImage ) images.get (i )、"jpeg“、新文件(”C:\Media\“+ dirname + "\”+ filename + "_“+(i+ 1) +”.jpeg“);一些说明性局部变量将使其更易读: RenderedImage RenderedImage= (RenderedImage) images.get(i);String formatName = "jpeg";字符串outputFilePath = "C:\Media\“+迪尔名+ "\”+文件名+ "_“+ (i + 1) + ".jpeg";outputFile =新文件(OutputFilePath);ImageIO.write(renderedImage、formatName、outputFile);如果您使用它们,读取器立即看到ImageIO.write有什么样的参数,他们不必熟悉它,也不必检查API以了解开发人员的意图。参考文献:第6章.编写方法,介绍重构中的解释变量:改进Martin的现有代码设计:将表达式的结果或表达式的一部分放入一个临时变量中,其中包含解释目的的名称。和清洁代码由RobertC.Martin,G19:使用解释性变量。
  5. 实际上,我会将前一个片段提取到一个命名方法(可能称为writePage)中,该方法的名称总结了该块的意图,以提高可读性和更容易维护。
  6. 我同意Marc,PDF中的变量和方法名称应该是camelCase,它更容易阅读.在“有效的Java”第二版第56项中有一个很好的段落:坚持普遍接受的命名惯例:大写可能更常见,但有力的论据可以支持只将第一个字母大写:即使连续出现多个首字母缩略词,您仍然可以分辨出一个单词的开头和下一个单词的结尾。您希望看到哪个类名,HTTPURL还是HttpUrl?
票数 4
EN

Code Review用户

发布于 2014-02-21 16:42:34

我看到您使用的是Java 7,您可以为所有的IO操作使用try-。它将关闭应用程序中使用的流。

代码语言:javascript
复制
 try{
            File newFile = new File("C:\\Media\\" + directory + "\\" + filename);

            inStream = new FileInputStream(originalFile);
            outStream = new FileOutputStream(newFile);

            byte[] buffer = new byte[1024];

            int length;
            //copy the file content in bytes 
            while ((length = inStream.read(buffer)) > 0){

                outStream.write(buffer, 0, length);

            }

            inStream.close();
            outStream.close();

            System.out.println("Original PDF has been copied successfully!");

        }catch(IOException e){
            e.printStackTrace();
        }

如果有一个IOException,就不会关闭您的流。这可能会在未来的应用中导致一些潜在的问题。要解决这个问题,您可以使用“用资源进行尝试”语法。您的代码看起来可能如下:

代码语言:javascript
复制
File newFile = new File("C:\\Media\\");
try ( InputStream inStream = new FileInputStream(newFile);
      OutputStream outStream = new FileOutputStream(newFile);) {

    byte[] buffer = new byte[1024];

    int length;
    // copy the file content in bytes
    while ((length = inStream.read(buffer)) > 0) {

        outStream.write(buffer, 0, length);

    }

    System.out.println("Original PDF has been copied successfully!");

} catch (IOException e) {
    e.printStackTrace();
}

参数名不应以大写字母:public static void convertPDFtoPNG(String PDFFileName)开头。您需要将pdf大写吗?

我会修改你们中的一些评论。注释应该是有帮助的,您不需要重复代码。例子:

代码语言:javascript
复制
 // load PDF document
 PDFDocument document = new PDFDocument();
 File baseFile = new File(PDFFileName);
 document.load(baseFile);

真的需要//load PDF document吗?您已经在使用document.load了。大多数情况下,一条线性注释只是重复代码中所做的操作。其他读者不需要知道你在做什么,而是知道你为什么要这么做。当我添加评论时,我总是在想:我的代码本身是否足够清晰?我是真的要添加注释,还是可以更改方法名称或变量以更好地表达自己。当代码发生变化时,很难维护注释。

我知道您还没有在生产环境中,但是不要忘记更改所有的e.printStackTrace来进行某种日志记录。

值得知道的是,您可以为您的所有路径使用/,而不是转义\。Java将管理您正在使用的操作系统所需的操作系统。

你是说你把一个PDF转换成一个图像,但这并不完全正确。实际上,您正在将PDF转换为jpeg,这与IMHO完全不同。您很难将创建的图像编码为jpeg,您可能希望在将来进行更改以支持更多的格式。您可能会将图像的编写代码提取到他自己的方法或接口中,以便为每种格式都有多个实现(如果需要的话,我一点也不擅长图像)。

票数 8
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/42431

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档