2011-12-06 11 views
13

Hej,निर्धारित wheteher एंड्रॉयड संपत्ति प्रविष्टि एक फ़ाइल या निर्देशिका

मैं कुछ डेटा एप्लिकेशन जो बाह्य भंडारण पर कॉपी किया जाएगा के साथ बाहर भेज दिया है। यह कुछ सबफ़ोल्डर में घिरा हुआ है और मैं पूरी संरचना की प्रतिलिपि बनाना चाहता हूं।

मुझे /assets में किसी भी रिसोर्स के लिए फ़ाइल ऑब्जेक्ट प्राप्त करने में कठिनाई हो रही है। लेकिन मुझे लगता है कि मैं उस पर निर्भर हूं क्योंकि मुझे फाइल.इस डायरेक्टरी() की तरह कुछ चाहिए ताकि यह निर्धारित किया जा सके कि मुझे सिस्टम में गहराई से नकल करना या डाइव करना है या नहीं।

मेरा पहला दृष्टिकोण Assets Manager का उपयोग कर रहा था, लेकिन ऐसा लगता है कि कक्षा मुझे आवश्यक जानकारी प्रदान नहीं कर रही है। सबसे अधिक आशाजनक क्यों AssetFileDescriptor प्राप्त करना था और [FileDescriptor][2] पर जाना था। हालांकि उनमें से कोई भी isDirectory -method लगता है।

तो मेरा दूसरा दृष्टिकोण सीधे आगे है: फ़ाइल ऑब्जेक्ट बनाना और खुश रहें। हालांकि ऐसा लगता है कि मैं फ़ाइल ऑब्जेक्ट को उदाहरण के लिए उचित पथ की कमी के इस समस्या में भाग रहा हूं। मुझे file://android_asset से अवगत है, लेकिन यह file कन्स्ट्रक्टर के लिए काम नहीं कर रहा है।

मेरा अंतिम विचार इनपुटस्ट्रीम (जिसे मुझे वैसे भी कॉपी करने की आवश्यकता है) का उपयोग करना होगा और किसी भी तरह बाइट को एक महत्वपूर्ण बिट के लिए फ़िल्टर करना होगा जो इस संसाधन को निर्देशिका के रूप में इंगित करता है। यह एक सुंदर हैकी समाधान है और शायद अप्रभावी नरक में सही है लेकिन मुझे इसके चारों ओर जाने का दूसरा तरीका नहीं दिख रहा है।

+0

आप https://stackoverflow.com/a/46827944/2179872 भी देख सकते हैं जो *** AssetManager.list() *** और *** AssetManager.open() *** विधियों दोनों का संयोजन बनाता है – Cosmin

उत्तर

4

list() एसेटमैनेजर पर शायद एक फ़ाइल पर सूची प्राप्त करने का प्रयास करते समय एक शून्य/शून्य लंबाई सरणी/IOException देगी, लेकिन निर्देशिका पर एक वैध प्रतिक्रिया।

लेकिन अन्यथा यह होना चाहिए file: /// android_asset

+0

मुझे सूची-हैक की तलाश होगी। हाँ लेकिन नई फ़ाइल (फ़ाइल: ///android_asset/foo.bar) का उपयोग करना प्रतीत नहीं होता है। मुझे वास्तव में पता नहीं है कि मैं किस प्रकार की वस्तु वापस प्राप्त करता हूं लेकिन यह दोनों परीक्षणों के लिए विफल रहता है: isDirectory() और (!) IsFile() है। – yoshi

+1

मेरी इच्छा है कि मैं इस उत्तर के लिए वोट दोगुना कर सकता हूं। फ़ाइल नाम फ़ाइल होने पर 'स्ट्रिंग [] s = am.list (फ़ाइल नाम) '' IOException' फेंक देगा। मुझे वास्तव में यह समाधान पसंद है, बहुत बहुत धन्यवाद! – yoshi

+0

हालांकि, सूची() वास्तव में धीमी है (अन्य उत्तर देखें) –

12

(3/के साथ) मैं एक ही समस्या थी। किसी बिंदु पर मुझे एहसास हुआ कि list() वास्तव में धीमा है (प्रत्येक कॉल पर 50ms), इसलिए मैं अब एक अलग दृष्टिकोण का उपयोग कर रहा हूं:

मेरे पास एक (ग्रहण) चींटी-निर्माता है जो हर बार मेरी संपत्ति- फ़ोल्डर में परिवर्तन फ़ाइल में केवल एक फ़ाइल-नाम प्रति पंक्ति है, इसलिए निर्देशिकाएं पूरी तरह से सूचीबद्ध हैं (यदि वे खाली नहीं हैं)।

बिल्डर:

<?xml version="1.0"?> 
<project default="createAssetIndex"> 
    <target name="createAssetIndex"> 
     <fileset id="assets.fileset" dir="assets/" includes="**" 
      excludes="asset.index" /> 
     <pathconvert pathsep="${line.separator}" property="assets" 
      refid="assets.fileset"> 
      <mapper> 
       <globmapper from="${basedir}/assets/*" to="*" 
        handledirsep="yes" /> 
      </mapper> 
     </pathconvert> 
     <echo file="assets/asset.index">${assets}</echo> 
    </target> 
</project> 

वर्ग जो स्ट्रिंग की एक सूची में asset.index लोड करता है, तो आप मनमाने ढंग से सामान इसके साथ तेजी से कर सकते हैं,: मेरे विशिष्ट मामले में, नियमित रूप से फ़ाइलों

import android.content.ContextWrapper; 

import com.google.common.collect.ImmutableList; 

import java.io.BufferedInputStream; 
import java.io.File; 
import java.io.IOException; 
import java.io.InputStream; 

import java.util.Scanner; 

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

/** 
* uses asset.index file (which is pregenerated) since asset-list()s take very long 
* 
*/ 
public final class AssetIndex { 

    //~ Static fields/initializers ------------------------------------------------------------------------------------- 

    private static final Logger L = LoggerFactory.getLogger(AssetIndex.class); 

    //~ Instance fields ------------------------------------------------------------------------------------------------ 

    private final ImmutableList<String> files; 

    //~ Constructors --------------------------------------------------------------------------------------------------- 

    public AssetIndex(final ContextWrapper contextWrapper) { 

     ImmutableList.Builder<String> ib = ImmutableList.builder(); 

     L.debug("creating index from assets"); 

     InputStream in = null; 
     Scanner scanner = null; 
     try { 
      in   = contextWrapper.getAssets().open("asset.index"); 
      scanner  = new Scanner(new BufferedInputStream(in)); 

      while (scanner.hasNextLine()) { 
       ib.add(scanner.nextLine()); 
      } 

      scanner.close(); 
      in.close(); 

     } catch (final IOException e) { 
      L.error(e.getMessage(), e); 
     } finally { 
      if (scanner != null) { 
       scanner.close(); 
      } 
      if (in != null) { 
       try { 
        in.close(); 
       } catch (final IOException e) { 
        L.error(e.getMessage(), e); 
       } 
      } 
     } 

     this.files = ib.build(); 
    } 

    //~ Methods -------------------------------------------------------------------------------------------------------- 

    /* returns the number of files in a directory */ 
    public int numFiles(final String dir) { 

     String directory = dir; 
     if (directory.endsWith(File.separator)) { 
      directory = directory.substring(0, directory.length() - 1); 
     } 

     int num = 0; 
     for (final String file : this.files) { 
      if (file.startsWith(directory)) { 

       String rest = file.substring(directory.length()); 
       if (rest.charAt(0) == File.separatorChar) { 
        if (rest.indexOf(File.separator, 1) == -1) { 
         num = num + 1; 
        } 
       } 
      } 
     } 

     return num; 
    } 
} 
+1

यह बहुत अच्छा और उपयोगी है, लेकिन मुझे पथदर्शी में 'dirsep = "/"' जोड़ने की आवश्यकता है। अन्यथा विंडोज़ जावा पर कहते हैं कि पथ विभाजक '\' है, जो एंड्रॉइड एसेट मैनेजर – Flynny75

+1

में काम नहीं करता है, इसके साथ संघर्ष करने वाले और ग्रैडल का उपयोग करने के लिए, http://stackoverflow.com/questions/18569983/androidgradle-list- निर्देशिकाएं देखें -इनटो-ए-फाइल –

2

filename.ext जैसे नाम हैं, जबकि निर्देशिकाओं के पास केवल एक नाम है, विस्तार के बिना, और उनके नाम में "।" (डॉट) चरित्र। तो एक नियमित रूप से फ़ाइल जैसा कि इसके नाम का परीक्षण इस प्रकार से एक निर्देशिका से प्रतिष्ठित किया जा सकता है:

filename.contains(".") 

इस अपने मामले भी एक ही समाधान के लिए काम चाहिए।

+0

शानदार! सामान्य लोडिंग समय के 80% तक मुझे बचाया। –

संबंधित मुद्दे