2009-03-07 8 views
35

अर्थात्, आप टेक्स्ट (xml/txt, एन्कोडिंग-स्वतंत्र) से एक संग्रह (जार/रार/आदि) फ़ाइल कैसे बताएंगे?जावा में बाइनरी/टेक्स्ट फ़ाइल प्रकार निर्धारित करना?

+1

चाल सवाल का उपयोग करना - वे सब बाइनरी फ़ाइलें कर रहे हैं। – duffymo

उत्तर

16

कोई गारंटीयुक्त तरीका नहीं है, लेकिन यहां संभावनाओं की एक जोड़ी हैं:

1) फ़ाइल पर एक हैडर के लिए देखो। दुर्भाग्यवश, हेडर फ़ाइल-विशिष्ट हैं, इसलिए जब आप यह पता लगाने में सक्षम हो सकते हैं कि यह एक आरएआर फ़ाइल है, तो आपको टेक्स्ट या बाइनरी का अधिक सामान्य जवाब नहीं मिलेगा।

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

3) न्यूलाइन के नियमित रूप से दोहराने वाले पैटर्न की तलाश करें।

1

आप DROID उपकरण को आजमा सकते हैं।

3

देखें फ़ाइल बाइट्स 0x09 (टैब) के होते हैं, तो 0x0A (लाइन फ़ीड), 0x0C (फार्म फ़ीड), 0x0D (गाड़ी वापसी), या 0x20 0x7E के माध्यम से है, तो यह शायद ASCII पाठ है ।

यदि फ़ाइल में ऊपर दिए गए तीन को छोड़कर 0x00 से 0x1F कोई अन्य ASCII नियंत्रण वर्ण है, तो यह शायद बाइनरी डेटा है।

यूटीएफ -8 टेक्स्ट हाई ऑर्डर बिट के साथ किसी बाइट के लिए एक बहुत ही विशिष्ट पैटर्न का पालन करता है, लेकिन आईएसओ -885 9 -1 जैसी निश्चित लंबाई वाली एन्कोडिंग नहीं होती है। यूटीएफ -16 में अक्सर शून्य बाइट (0x00) हो सकता है, लेकिन केवल हर दूसरे स्थिति में।

आपको किसी और चीज़ के लिए कमजोर ह्युरिस्टिक की आवश्यकता होगी।

9

JMimeMagic लाइब्रेरी पर एक नज़र डालें।

jMimeMagic फाइल या धाराओं के MIME प्रकार का निर्धारण करने के लिए एक जावा पुस्तकालय है।

+0

दिलचस्प पुस्तकालय, लेकिन यह कैसे मदद करने जा रहा है? यह आपको माइम प्रकार बताता है, लेकिन यह बाइनरी या टेक्स्ट नहीं है। – Adam

+0

@Adam मुझे आपका प्रश्न नहीं समझ रहा है? आप एमआईएम प्रकार से खुद को घटा सकते हैं कि फ़ाइल द्विआधारी है या नहीं, है ना? अर्थात। यदि प्रकार 'टेक्स्ट/सादा' है तो यह एक पाठ फ़ाइल होना चाहिए। – dhiller

+0

ठीक है, मैं ब्लंट था। मेरा मतलब यह था कि आपको अभी भी बाइनरी या टेक्स्ट के रूप में माइम प्रकार की व्याख्या करने के लिए अतिरिक्त तर्क लिखना है। 'टेक्स्ट/सादा' एकमात्र पाठ-आधारित माइम प्रकार नहीं है। – Adam

3

बस आपको बताने के लिए, मैंने काफी अलग रास्ता चुना है। मैं अपने मामले में, केवल 2 प्रकार की फाइलें हैं, संभावना है कि किसी दिए गए फ़ाइल को बाइनरी एक उच्च होगा। तो

  1. उस फ़ाइल बाइनरी है, कर क्या किया जाना चाहिए था की कोशिश अनुमान (जैसे deserialize)
  2. पकड़ अपवाद शाब्दिक रूप
  3. इलाज फ़ाइल
  4. कि अगर विफल रहता है, कुछ फ़ाइल स्वयं
  5. साथ कुछ गड़बड़ है
+0

मुझे लगता है कि यह सबसे अच्छा तरीका है। क्या आपको सचमुच परवाह है कि फ़ाइल का प्रकार क्या है? या आप परवाह है कि आप इसके साथ कुछ चीजें कर सकते हैं या नहीं। कई मामलों में, यदि आप उन चीजों को कर सकते हैं, तो आपको वास्तव में यह जानने की आवश्यकता नहीं है कि प्रकार क्या है। – stackexchanger

10

रन file -bi {filename}। यदि जो कुछ भी लौटाता है वह 'टेक्स्ट /' से शुरू होता है, तो यह गैर-बाइनरी है, अन्यथा यह है। ;-)

+1

ऐसा लगता है कि "एप्लिकेशन/जावास्क्रिप्ट" और "एप्लिकेशन/एक्सएमएल" भी है। यहां देख रहे हैं http://en.wikipedia.org/wiki/Internet_media_type सुझाव देता है कि यह इतना आसान नहीं है। – Aaron

+1

आप 'file -i {filename}' के साथ जांच सकते हैं और जांच सकते हैं कि 'charset = binary' नहीं है। –

+0

मुझे कहना है कि जब मैंने उपर्युक्त उत्तर दिया तो मैं पूरी तरह से गंभीर नहीं था। टेक्स्ट फाइलें एक विशेष तरीके से व्याख्या की गई बाइनरी फाइलें हैं। यदि आपका मतलब है कि कुछ यूएस-एएससीआईआईआई है, तो आप प्रत्येक बाइट की जांच कर सकते हैं और देख सकते हैं कि यह टेक्स्ट की आपकी परिभाषा को फिट करता है या नहीं। लेकिन शायद आप * किसी * प्रकार के चरित्र एन्कोडिंग का मतलब था। यह बहुत कठिन होगा। विशेष रूप से यदि आप उन लोगों में कारक हैं जो एंट्रॉपी आधारित एन्कोडिंग का उपयोग कर रहे हैं (वर्णों को अक्सर कम बिट्स की आवश्यकता होती है)। दूसरी तरफ, यदि आप सब कुछ यूएस-एएससीआईआईआई मतलब था, तो बेस 64 एन्कोडेड छवि भी टेक्स्ट होगी? –

5

मैं इस कोड का इस्तेमाल किया और यह बहुत अच्छी तरह से अंग्रेजी और जर्मन पाठ के लिए काम करता है:

private boolean isTextFile(String filePath) throws Exception { 
    File f = new File(filePath); 
    if(!f.exists()) 
     return false; 
    FileInputStream in = new FileInputStream(f); 
    int size = in.available(); 
    if(size > 1000) 
     size = 1000; 
    byte[] data = new byte[size]; 
    in.read(data); 
    in.close(); 
    String s = new String(data, "ISO-8859-1"); 
    String s2 = s.replaceAll(
      "[a-zA-Z0-9ßöäü\\.\\*!\"§\\$\\%&/()=\\[email protected]~'#:,;\\"+ 
      "+><\\|\\[\\]\\{\\}\\^°²³\\\\ \\n\\r\\t_\\-`´âêîô"+ 
      "ÂÊÔÎáéíóàèìòÁÉÍÓÀÈÌÒ©‰¢£¥€±¿»«¼½¾™ª]", ""); 
    // will delete all text signs 

    double d = (double)(s.length() - s2.length())/(double)(s.length()); 
    // percentage of text signs in the text 
    return d > 0.95; 
} 
+2

विचार दिलचस्प है, लेकिन प्रतिस्थापित करने की बजाय सभी, जो अनावश्यकता एक नई स्ट्रिंग बनाता है, मैं बस टेक्स्ट बनाम गैर-पाठ वर्णों को गिनने के लिए लूप का उपयोग करता हूं। 1000 अक्षरों पर सीमा डालने का मतलब है कि यह * भी * महंगा नहीं होगा, लेकिन यह अभी भी एक बेकार लागत – miniBill

8

मैं इस एक बना दिया। थोड़ा सा सरल, लेकिन लैटिन-आधारित भाषाओं के लिए, अनुपात समायोजन के साथ इसे ठीक काम करना चाहिए।

/** 
* Guess whether given file is binary. Just checks for anything under 0x09. 
*/ 
public static boolean isBinaryFile(File f) throws FileNotFoundException, IOException { 
    FileInputStream in = new FileInputStream(f); 
    int size = in.available(); 
    if(size > 1024) size = 1024; 
    byte[] data = new byte[size]; 
    in.read(data); 
    in.close(); 

    int ascii = 0; 
    int other = 0; 

    for(int i = 0; i < data.length; i++) { 
     byte b = data[i]; 
     if(b < 0x09) return true; 

     if(b == 0x09 || b == 0x0A || b == 0x0C || b == 0x0D) ascii++; 
     else if(b >= 0x20 && b <= 0x7E) ascii++; 
     else other++; 
    } 

    if(other == 0) return false; 

    return 100 * other/(ascii + other) > 95; 
} 
+1

इस फ़ंक्शन के लिए धन्यवाद। एक बात मुझे परेशानी हो रही है कि वापसी मूल्य के साथ क्या चल रहा है: 'वापसी (एएससीआई + अन्य) * 100/अन्य> 95;' जो, जब तक कि मैं कुछ याद नहीं कर रहा हूं, हमेशा सत्य वापस आ जाएगा: अधिकतर, आकार '1024' होगा, जैसा कि 'डेटा। लम्बाई' होगा और इसलिए' (ascii + other) '। तो यदि '(ascii + other) * 100 == 102400' फिर' 102400/अन्य> 95' => '102400> 95 * अन्य' =>' अन्य <1078' जिसका अर्थ है कि 1078 से अधिक होने की आवश्यकता है (1024 में से) "अन्य" इसके लिए झूठी वापसी, स्पष्ट रूप से असंभव है। क्या आपका मतलब था ?: '(अन्य/आकार * 100> 95)' या क्या मुझे कुछ याद आ रही है? – Inversus

+0

मुझे लगता है कि आप सही हैं। कोड फिक्स्ड –

+0

कूल शांत। हां, मैं भी उसके साथ जा रहा था। धन्यवाद फिर से :) – Inversus

5

जावा 7 फ़ाइलें वर्ग http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#probeContentType(java.nio.file.Path)

boolean isBinaryFile(File f) throws IOException { 
     String type = Files.probeContentType(f.toPath()); 
     if (type == null) { 
      //type couldn't be determined, assume binary 
      return true; 
     } else if (type.startsWith("text")) { 
      return false; 
     } else { 
      //type isn't text 
      return true; 
     } 
    } 
+3

यह सिर्फ फ़ाइल एक्सटेंशन पर जांचता है, न कि फ़ाइल सामग्री और इसलिए बेकार। – ares

+1

यह दस्तावेज़ों के मुताबिक स्थापित होने पर निर्भर है। – Adam

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