代码之家  ›  专栏  ›  技术社区  ›  Tim Visher

如何确定文件是否是JVM上的映像?

  •  2
  • Tim Visher  · 技术社区  · 14 年前

    我想获取包含任意文件(典型的“下载”目录)的目录的内容,并以编程方式确定给定文件是否是任何类型的图像。

    我在Clojure工作,但在JVM上任何可用的东西都是公平的。

    事先谢谢!

    3 回复  |  直到 14 年前
        1
  •  2
  •   Community WizardZ    7 年前

    最后我把对你问题的评论和我之前的回答结合起来解决了这个问题。 here . 对代码的微小更改使其可以处理非图像的图像。

    我没有将其更改为递归到子目录。很容易做到。

    (defn files-in-dir [dir]                                                                                                               
      (filter #(not (.isDirectory %))                                                                                                      
              (.listFiles (java.io.File. dir))))                                                                                           
    
    (defn figure-out-height-width                                                                                                          
      [files]                                                                                                                              
      (remove nil?                                                                                                                         
              (map (fn [file]                                                                                                               
                     (with-open [r (java.io.FileInputStream. file)]                                                                        
                       (if-let [img (javax.imageio.ImageIO/read r)]                                                                        
                         [file (.getWidth img) (.getHeight img)])))                                                                        
                   files)))                                                                                                                
    
    user> (pprint (files-in-dir "/home/jmccrary/Downloads/"))                                                                              
    (#<File /home/jmccrary/Downloads/Girl_Talk_-_All_Day_(IA123)_mp3s.zip>                                                                 
     #<File /home/jmccrary/Downloads/CSS3-for-Web-Designers.zip>                                                                           
     #<File /home/jmccrary/Downloads/manual.pdf>                                                                                           
     #<File /home/jmccrary/Downloads/test.jpeg>                                                                                            
     #<File /home/jmccrary/Downloads/nautilus-dropbox_0.6.7_amd64.deb>                                                                     
     #<File /home/jmccrary/Downloads/rubygems-1.3.7.tgz>                                                                                   
     #<File /home/jmccrary/Downloads/HTML5-FOR-WEB-DESIGNERS.zip>                                                                          
     #<File /home/jmccrary/Downloads/bcompare-3.1.11.12238.tar.gz>                                                                         
     #<File /home/jmccrary/Downloads/shared_ptr_example.cpp>)                                                                              
    nil                                                                                                                                    
    user> (figure-out-height-width (files-in-dir "/home/jmccrary/Downloads"))                                                              
    ([#<File /home/jmccrary/Downloads/test.jpeg> 32 32])
    

    在考虑了一会儿之后,把检查文件是否是图像和拉出宽度和高度结合起来会觉得很脏。或者,您可以定义一个函数,该函数单独进行过滤,并为您提供一系列图像。

    (defn filter-images                                                                                                                    
      [files]                                                                                                                              
      (reduce (fn [res file]                                                                                                                
                (if-let [img (javax.imageio.ImageIO/read file)]                                                                            
                  (conj res img)                                                                                                           
                  res))                                                                                                                    
              []                                                                                                                           
              files))
    
    user> (filter-images (files-in-dir "/home/jmccrary/Downloads"))                                                                        
    [#<BufferedImage BufferedImage@24753433: type = 5 ColorModel: #pixelBits = 24 numComponents = 3 color space = java.awt.color.ICC_Color\
    Space@43036651 transparency = 1 has alpha = false isAlphaPre = false ByteInterleavedRaster: width = 32 height = 32 #numDataElements 3 \
    dataOff[0] = 2>
    

    ]

        2
  •  2
  •   eaj    14 年前

    显然,最简单的事情就是查看文件扩展名。当然,它不一定可靠,但在某些情况下可能就足够了。

    除了读取整个图像,您还可以读取文件的前几个字节,以通过其“幻数”来识别它。例如,jpeg文件总是以两个字节0xffd8开头,以0xffd9结尾;pdfs总是以字符串“%pdf”开头。

    这样可以节省在内存中创建映像的开销,也可以加快I/O的速度(因为您只需要文件的几个字节)。

    如果你不想自己研究所有这些魔法数字,你可以尝试一个图书馆,比如 jMimeMagic . 我从未使用过它,所以我不能保证它的质量或完整性,但它是LGPL。我相信你也能找到其他的选择。

        3
  •  2
  •   Alex Ott    14 年前

    你可以使用 Tika library 它能够检测多种类型的文件,并从其中许多文件中提取元数据。我有很简单的 Clojure wrapper 为它