Fullmenu null

 

17 February 2018

JavaFX (y GroovyFX) nos permiten visualizar datos de forma muy cómoda. En este caso vamos a realizar un escaneo de nuestros ficheros y por cada extensión vamos a acumular el tamaño de los ficheros y su número, de tal forma que podamos visualizar la distribución de los mismos en tres gráficas:

  • distribución por tamaños (qué extensión ocupa más disco)

  • distribución por número (qué extensión tiene más ficheros)

  • relación entre ambos conceptos

Calculo

Dado un directorio como argumento, el script lo recorrera recursivamente generando 3 mapas con la extensión como clave:

  • por tamaño, bySize

  • por contador, byNumber

  • por ambos mediante un submapa con la unión de los 3 conceptos (extension, numero y tamaño)

bySize=[:]
byNumber=[:]
byBoth=[:]

void scanDir( File dir ){
    dir.eachFile FileType.FILES,{ f->
        split = f.name.split('\\.')
        ext = split.size() ? split.last() : '.'

        bySize."$ext" = (bySize."$ext" ?: 0)+f.size()
        byNumber."$ext" = (byNumber."$ext" ?: 0)+1

        both = byBoth."$ext" ?: [ext,0,0]
        both[1] +=f.size()
        both[2] +=1
        byBoth."$ext" = both
    }
    dir.eachDir{ d ->
        scanDir(d)
    }
}

scanDir(new File(args[0]))

bySize = bySize.sort{ a,b-> b.value<=>a.value }
byNumber = byNumber.sort{ a,b-> b.value<=>a.value }

La gestión de Groovy con mapas es tan potente que nos permite crear elementos en el mapa de una forma realmente simple

Vista

La vista utilizará 3 gráficas, una para cada mapa calculado previamente

    stage title: "My Files", visible: true, {
        scene {
            saveNode = stackPane {
                scrollPane {
                    tilePane(padding: 10, prefTileWidth: 480, prefColumns: 2) {

                        pieChart(data: bySize, title: "Size")

                        pieChart(data: byNumber, title: "Number")

                        scatterChart title:'Size vs Number', {
                            byBoth.values().each { bb->
                                series(name: bb[0], data: [bb[1],bb[2]])
                            }
                        }
                    }
                }
            }
        }
    }

Ejemplo

A continuación se muestra un ejemplo de cómo se representaría un directorio, en concreto el blog donde vemos que la extensión mayoritaria tanto en tamaño como en número es SVG.

myfiles

Script
//tag::dependencies[]

import groovy.io.FileType

@GrabConfig(systemClassLoader=true)
@Grab(group='org.groovyfx',module='groovyfx',version='8.0.0',transitive=false, noExceptions=true)

import static groovyx.javafx.GroovyFX.start
import javafx.application.Platform
import javafx.scene.SnapshotParameters
import javax.imageio.ImageIO
import java.awt.image.BufferedImage
//end::dependencies[]

//tag::calculating[]
bySize=[:]
byNumber=[:]
byBoth=[:]

void scanDir( File dir ){
    dir.eachFile FileType.FILES,{ f->
        split = f.name.split('\\.')
        ext = split.size() ? split.last() : '.'

        bySize."$ext" = (bySize."$ext" ?: 0)+f.size()
        byNumber."$ext" = (byNumber."$ext" ?: 0)+1

        both = byBoth."$ext" ?: [ext,0,0]
        both[1] +=f.size()
        both[2] +=1
        byBoth."$ext" = both
    }
    dir.eachDir{ d ->
        scanDir(d)
    }
}

scanDir(new File(args[0]))

bySize = bySize.sort{ a,b-> b.value<=>a.value }
byNumber = byNumber.sort{ a,b-> b.value<=>a.value }
//end::calculating[]

start { app ->
    //tag::view[]
    stage title: "My Files", visible: true, {
        scene {
            saveNode = stackPane {
                scrollPane {
                    tilePane(padding: 10, prefTileWidth: 480, prefColumns: 2) {

                        pieChart(data: bySize, title: "Size")

                        pieChart(data: byNumber, title: "Number")

                        scatterChart title:'Size vs Number', {
                            byBoth.values().each { bb->
                                series(name: bb[0], data: [bb[1],bb[2]])
                            }
                        }
                    }
                }
            }
        }
    }
    //end::view[]

    //tag::snapshot[]
    def snapshot = saveNode.snapshot(new SnapshotParameters(), null);
    BufferedImage bufferedImage = new BufferedImage(saveNode.width as int, saveNode.height as int, BufferedImage.TYPE_INT_ARGB);
    BufferedImage image = javafx.embed.swing.SwingFXUtils.fromFXImage(snapshot, bufferedImage)

    File file = new File('myfiles.png')
    ImageIO.write(image, "png", file )
    //end::snapshot[]
}