2012-07-28 3 views
1

USB를 통해 많이 액세스되는 외부 메모리에서 작동하는 응용 프로그램을 개발 중입니다. 디스크에서 디렉토리를 찾아보기 위해 TreeModel을 구현했습니다. JAVA 파일 트리 모델 pendrive에 대한 속도가 느리다

  • 로컬 디스크
  • 윈도우 7에 우분투 Ubuntu에서

    • 로컬 디스크
    • 연결된 외부 기억하지만, Windows 7 및 I 돈에 연결된 외부 메모리에 대한 짜증 : 그것은 위대한 작품 이유를 모르겠습니다. pendrive를 루트로 사용하여이 모델로 JTree를 스크롤하는 것은 매우 이상합니다. 처음에는 필자가 생각하기에 java.io.File의 listFiles()은 pendrive에서 속도가 느리기 때문에 모델에 캐싱을 추가했으나 작동하지 않았습니다.

      나는 그저 Look & 느낌과 관련이 있다는 것을 알아 차렸습니다. Windows 용 시스템 L & F의 경우 NADUS L & F에 대해 BAD를 괴롭 혔지만 그다지 완벽하지는 않습니다.

      FileTreeModel :

      import java.io.File; 
      import java.io.FileFilter; 
      import java.io.Serializable; 
      import java.util.*; 
      import javax.swing.event.TreeModelEvent; 
      import javax.swing.event.TreeModelListener; 
      import javax.swing.tree.TreeModel; 
      import javax.swing.tree.TreePath; 
      
      public class FileTreeModel implements TreeModel { 
      
          private File root; 
          private boolean onlyFolders; 
          private boolean showHidden; 
          private final Object LEAF = new Serializable() { 
          }; 
          private Map<File, Object> map; 
          private LinkedList<TreeModelListener> listeners = new LinkedList<>(); 
          private FileFilter directoryFilter = new FileFilter() { 
      
           @Override 
           public boolean accept(java.io.File pathname) { 
            return pathname.isDirectory(); 
           } 
          }; 
      
          public FileTreeModel(File root, boolean onlyFolders, boolean showHidden) { 
           this.root = root; 
           this.onlyFolders = onlyFolders; 
           this.showHidden = showHidden; 
           this.map = new HashMap(); 
          } 
      
          public FileTreeModel() { 
          } 
      
          public boolean isShowHidden() { 
           return showHidden; 
          } 
      
          public void setShowHidden(boolean showHidden) { 
           this.showHidden = showHidden; 
          } 
      
          @Override 
          public Object getRoot() { 
           return root; 
          } 
      
          public void setRoot(File root) { 
           Object oldRoot = this.root; 
           this.root = root; 
           map.clear(); 
           TreeModelEvent event = new TreeModelEvent(root, new Object[]{root}); 
           for (TreeModelListener listener : listeners) { 
            listener.treeStructureChanged(event); 
           } 
          } 
      
          @Override 
          public boolean isLeaf(Object node) { 
           return ((File) node).isFile(); 
          } 
      
          @Override 
          public int getChildCount(Object parent) { 
           if (parent instanceof java.io.File && ((java.io.File) parent).canRead()) { 
            List<File> files = children(parent); 
            int result = 0; 
            for (java.io.File file : files) { 
             if (((file.isDirectory() && onlyFolders) || !onlyFolders) 
               && ((!file.isHidden() && !showHidden) || showHidden)) { 
              result++; 
             } 
            } 
            return result; 
           } 
           return 0; 
          } 
      
          @Override 
          public Object getChild(Object parent, int index) { 
           if (parent instanceof java.io.File) { 
            List<File> files = children(parent); 
            List<java.io.File> resultFiles = new LinkedList<>(); 
            for (java.io.File file : files) { 
             if (((file.isDirectory() && onlyFolders) || !onlyFolders) 
               && ((!file.isHidden() && !showHidden) || showHidden)) { 
              resultFiles.add(file); 
             } 
            } 
            return resultFiles.get(index); 
           } 
           return null; 
          } 
      
          @Override 
          public int getIndexOfChild(Object parent, Object child) { 
           if (parent instanceof java.io.File) { 
            List<File> files = children(parent); 
            List<java.io.File> resultFiles = new LinkedList<>(); 
            for (java.io.File file : files) { 
             if (((file.isDirectory() && onlyFolders) || !onlyFolders) 
               && ((!file.isHidden() && !showHidden) || showHidden)) { 
              resultFiles.add(file); 
             } 
            } 
            return resultFiles.indexOf(child); 
           } 
           return -1; 
          } 
      
          @Override 
          public void valueForPathChanged(TreePath path, Object newvalue) { 
          } 
      
          @Override 
          public void addTreeModelListener(TreeModelListener l) { 
           listeners.add(l); 
          } 
      
          @Override 
          public void removeTreeModelListener(TreeModelListener l) { 
           listeners.remove(l); 
          } 
      
          //============================PRIVATE METHODS=============================== 
          protected List<File> children(Object node) { 
           File f = (File) node; 
           Object value = map.get(f); 
           if (value == LEAF) { 
            return null; 
           } 
           List children = (List) value; 
           if (children == null) { 
            File[] c = f.listFiles(); 
            if (c != null) { 
             children = new ArrayList(c.length); 
             for (int len = c.length, i = 0; i < len; i++) { 
              children.add(c[i]); 
              if (!c[i].isDirectory()) { 
               map.put(c[i], LEAF); 
              } 
             } 
            } else { 
             children = new ArrayList(0); 
            } 
            map.put(f, children); 
           } 
           return children; 
          } 
      } 
      

      샘플 양식 :

      import folderlist.model.treemodels.FileTreeModel; 
      import java.io.File; 
      import java.util.Vector; 
      import javax.swing.DefaultComboBoxModel; 
      
      public class NewJFrame extends javax.swing.JFrame { 
      
          public NewJFrame() { 
           initComponents(); 
          } 
      
          @SuppressWarnings("unchecked") 
          // <editor-fold defaultstate="collapsed" desc="Generated Code"> 
          private void initComponents() { 
      
           jComboBox1 = new javax.swing.JComboBox(); 
           jButton1 = new javax.swing.JButton(); 
           jScrollPane1 = new javax.swing.JScrollPane(); 
           jTree1 = new javax.swing.JTree(); 
      
           setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 
      
           jComboBox1.addActionListener(new java.awt.event.ActionListener() { 
            public void actionPerformed(java.awt.event.ActionEvent evt) { 
             jComboBox1ActionPerformed(evt); 
            } 
           }); 
      
           jButton1.setText("Refresh"); 
           jButton1.addActionListener(new java.awt.event.ActionListener() { 
            public void actionPerformed(java.awt.event.ActionEvent evt) { 
             jButton1ActionPerformed(evt); 
            } 
           }); 
      
           jTree1.setModel(new FileTreeModel()); 
           jScrollPane1.setViewportView(jTree1); 
      
           javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); 
           getContentPane().setLayout(layout); 
           layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
            .addGroup(layout.createSequentialGroup() 
             .addContainerGap() 
             .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
              .addGroup(layout.createSequentialGroup() 
               .addComponent(jComboBox1, 0, 173, Short.MAX_VALUE) 
               .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 
               .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 87, javax.swing.GroupLayout.PREFERRED_SIZE)) 
              .addComponent(jScrollPane1)) 
             .addContainerGap()) 
           ); 
           layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
            .addGroup(layout.createSequentialGroup() 
             .addContainerGap() 
             .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 
              .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 
              .addComponent(jButton1)) 
             .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 
             .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 189, Short.MAX_VALUE) 
             .addContainerGap()) 
           ); 
      
           pack(); 
          }// </editor-fold> 
      
          private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { 
           DefaultComboBoxModel model = new DefaultComboBoxModel(getAvailableRoots()); 
           jComboBox1.setModel(model); 
          } 
      
          private void jComboBox1ActionPerformed(java.awt.event.ActionEvent evt) { 
           File choosenRoot = (File) jComboBox1.getSelectedItem(); 
           if (choosenRoot != null) { 
            FileTreeModel model = new FileTreeModel(choosenRoot, false, true); 
            jTree1.setModel(model); 
           } 
          } 
      
          public static void main(String args[]) { 
      
           try { 
      //   for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { 
      //    if ("Nimbus".equals(info.getName())) { 
      //     javax.swing.UIManager.setLookAndFeel(info.getClassName()); 
      //     break; 
      //    } 
      //   } 
            javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName()); 
           } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) { 
            java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
           } 
           //</editor-fold> 
      
           /* 
           * Create and display the form 
           */ 
           java.awt.EventQueue.invokeLater(new Runnable() { 
      
            public void run() { 
             new NewJFrame().setVisible(true); 
            } 
           }); 
          } 
      
          private Vector<File> getAvailableRoots() { 
           Vector<File> v = new Vector<File>(10, 1); 
           File userHome = new File(System.getProperty("user.home")); 
           if (userHome.isDirectory()) { 
            v.addElement(userHome); 
           } 
           File[] roots = File.listRoots(); 
           for (File root : roots) { 
            v.addElement(root); 
           } 
           String os = System.getProperty("os.name").toLowerCase(); 
           boolean isUnix = (os.indexOf("nix") >= 0 || os.indexOf("nux") >= 0); 
           if (isUnix) { 
            roots = new File("/media").listFiles(); 
            for (File root : roots) { 
             v.addElement(root); 
            } 
           } 
           return v; 
          } 
      
          // Variables declaration - do not modify 
          private javax.swing.JButton jButton1; 
          private javax.swing.JComboBox jComboBox1; 
          private javax.swing.JScrollPane jScrollPane1; 
          private javax.swing.JTree jTree1; 
          // End of variables declaration 
      } 
      

    답변

    1

    두 문제 (즉, 내가 할 수있는 자체가) 있습니다 : 당신이 당신의 결과를 캐시하지

    1. . 파일 목록은 비용이 많이 드는 작업이며 시간이 오래 걸립니다. 외부 장치에서 훨씬 그렇습니다. 디렉토리를 나열한 후에는 목록을 유지하십시오. Java 7을 사용하는 경우 Fie Watcher Service을 사용할 수 있습니다. 그렇지 않으면 새로 고침 옵션을 제공해야합니다.
    2. 노드 노드 로딩 작업을로드 해제해야합니다. http://www.jroller.com/Thierry/entry/swing_lazy_loading_in_a & http://www.jroller.com/Thierry/entry/swing_lazy_loading_in_jtree을 살펴보십시오. 완벽한 것은 아니지만, 당신은 코드를 살펴있을 때 좋은 생각을

    UPDATE

    를 제공하려고, 진행이 많이있다. 개별 노드의 경우 중요한 것은 아니지만 노드를 몇 개 시작하면 지연이 눈에 띄기 시작합니다.

    그래서 트리를 다시 칠할 필요가있을 때마다 각 개별 노드를 통해 getChildCount, getChildren 및/또는 getChildAt과 같은 호출이 발생합니다. 이 방법들 각각은 본질적으로 반복해서 똑같은 일을 반복합니다.

    @Override 
    public int getChildCount(Object parent) { 
        if (parent instanceof java.io.File && ((java.io.File) parent).canRead()) { 
         List<File> files = children(parent); 
         int result = 0; 
         for (java.io.File file : files) { 
          if (((file.isDirectory() && onlyFolders) || !onlyFolders) 
            && ((!file.isHidden() && !showHidden) || showHidden)) { 
           result++; 
          } 
         } 
         return result; 
        } 
        return 0; 
    } 
    
    @Override 
    public Object getChild(Object parent, int index) { 
        if (parent instanceof java.io.File) { 
         List<File> files = children(parent); 
         List<java.io.File> resultFiles = new LinkedList<>(); 
         for (java.io.File file : files) { 
          if (((file.isDirectory() && onlyFolders) || !onlyFolders) 
            && ((!file.isHidden() && !showHidden) || showHidden)) { 
           resultFiles.add(file); 
          } 
         } 
         return resultFiles.get(index); 
        } 
        return null; 
    } 
    

    속성 (showHidden & onlyFolders) 다음에서 결과를 생성하는 데 사용할 수있는 캐시 하위 모델을 생산을 기반으로 모든 파일의 목록을 포함하고 하위 모델이 더 나은 것 각 통화. 예를 단지 sugesstion의

    @Override 
    public int getChildCount(Object parent) { 
        int count = 0; 
        if (parent instanceof java.io.File && ((java.io.File) parent).canRead()) { 
         count = fileModel.getFilteredFiles().size(); 
        } 
        return count; 
    } 
    

    를 들어

    .P

    나는 결과를 캐싱하고
    +0

    1 :

    또한, 최근의 경험에서, File.canRead() & File.canWrite()는 Windows에서 UAC가 활성화되어 7 기계 오탐 (false positive)을 반환 할 수 있습니다. 가까이에서 - [code] (children()) 메소드를보세요. 또는 나는 무엇인가 놓치고 있냐?
    2. 게으른로드가 좋은 생각이지만, 그것은 당연한가요? 로딩 시간은 오래 걸리지 않습니다. 잠시만 기다려주십시오.하지만 아마도 당신 말이 맞아요. – Bladositto

    +0

    formating 미안 해요 - 내가 stackoverflow – Bladositto

    +0

    새로운 알았어, 내가 서서, 코드에서, 그것은 캐시 된 것으로 나타납니다. – MadProgrammer