पढ़ने/लिखने के लिए बाइट्स और एक फ़ाइल से का उपयोग कर केवल जावा.कब

0

सवाल

हम कैसे लिख सकते हैं एक बाइट सरणी के लिए एक फ़ाइल (और इसे वापस पढ़ा है कि फ़ाइल से) जावा में?

हाँ, हम सभी जानते हैं कि वहाँ रहे हैं पहले से ही बहुत सारे सवाल की तरह है कि है, लेकिन वे बहुत ही गंदा और व्यक्तिपरक कारण के लिए तथ्य यह है कि वहाँ रहे हैं तो कई मायनों में इस कार्य को पूरा करने.

तो चलो की गुंजाइश कम सवाल:

डोमेन:

  • एंड्रॉयड / जावा

हम क्या चाहते हैं:

  • तेजी से (संभव के रूप में)
  • बग-मुक्त (एक सख्ती से सूक्ष्म तरीके)

क्या हम नहीं कर रहे हैं:

  • तीसरे पक्ष के पुस्तकालयों
  • किसी भी पुस्तकालयों की आवश्यकता है कि Android एपीआई के बाद से 23 (Marshmallow)

(तो, कि नियमों के बाहर अपाचे कॉमन्स, गूगल अमरूद, जावा.एनआईओ, और पत्तियों के साथ हमें अच्छा राजभाषा' जावा.io)

क्या हम की जरूरत है:

  • बाइट सरणी वास्तव में हमेशा होता है (एक ही सामग्री और आकार) के माध्यम से जाने के बाद लिखने-तो-पढ़ने की प्रक्रिया
  • लिखने की विधि के केवल दो तर्क की आवश्यकता है: फ़ाइल, और बाइट[] डेटा
  • पढ़ें विधि रिटर्न एक बाइट[] और केवल आवश्यकता है एक तर्क: फ़ाइल फ़ाइल

मेरी खास मामले में, इन तरीकों में निजी रहे हैं (नहीं एक लाइब्रेरी) और कर रहे हैं के लिए जिम्मेदार नहीं बाद, (लेकिन अगर आप चाहते हैं बनाने के लिए एक और अधिक सार्वभौमिक समाधान लागू होता है कि एक व्यापक दर्शकों के लिए, इसके लिए जाना है):

  • धागे की सुरक्षा (फ़ाइल द्वारा पहुँचा जा नहीं होगा एक से अधिक प्रक्रिया में एक बार)
  • फाइल किया जा रहा शून्य
  • फ़ाइल की ओर इशारा करते हुए करने के लिए न के बराबर स्थान
  • की कमी permissions पर फ़ाइल स्थान
  • बाइट सरणी में बहुत बड़ा होने के नाते
  • बाइट सरणी में अशक्त होने के नाते
  • किसी के साथ निपटने "सूचकांक," "लंबाई," या "संलग्न" तर्क/क्षमताओं

... तो हम कर रहे हैं की तरह की तलाश में निश्चित बुलेट प्रूफ कोड है कि लोगों को भविष्य में मान सकते हैं सुरक्षित है, क्योंकि उपयोग करने के लिए अपने जवाब के बहुत सारे है अप-वोट और वहाँ रहे हैं कोई टिप्पणी नहीं है कि कहते हैं, "हो सकता है कि दुर्घटना अगर..."

यह है कि क्या मैं इतनी दूर है:

लिखने बाइट्स फाइल करने के लिए:

private void writeBytesToFile(final File file, final byte[] data) {
        try {
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(data);
            fos.close();
        } catch (Exception e) {
            Log.i("XXX", "BUG: " + e);
        }
    }

पढ़ें बाइट्स से फ़ाइल:

private byte[] readBytesFromFile(final File file) {
        RandomAccessFile raf;
        byte[] bytesToReturn = new byte[(int) file.length()];
        try {
            raf = new RandomAccessFile(file, "r");
            raf.readFully(bytesToReturn);
        } catch (Exception e) {
            Log.i("XXX", "BUG: " + e);
        }
        return bytesToReturn;
}

से मैं क्या पढ़ा है, संभव अपवाद हैं:

FileNotFoundException : मैं कर रहा हूँ सही है कि यह नहीं होना चाहिए, के रूप में लंबे समय के रूप में फ़ाइल पथ की आपूर्ति की जा रही थी व्युत्पन्न का उपयोग कर Android के स्वयं के आंतरिक उपकरण और/या एप्लिकेशन को परीक्षण किया गया था ठीक से?

IOException : मैं वास्तव में नहीं पता है क्या इस का कारण बन सकता... लेकिन मैं मान रहा हूँ कि वहाँ के आसपास कोई रास्ता नहीं अगर यह होता है यह.

तो के साथ कि मन में... कर सकते हैं इन तरीकों में सुधार किया जा सकता है या बदल दिया है, और यदि हां, तो क्या?

android arrays file java
2021-11-23 02:58:43
2

सबसे अच्छा जवाब

6

यह की तरह लग रहा है, इन कर रहे हैं करने के लिए जा कोर उपयोगिता/पुस्तकालय तरीकों जो होना चाहिए पर चलाने के लिए Android एपीआई 23 या बाद में.

के विषय में लाइब्रेरी के तरीकों, मैं इसे का सबसे अच्छा बनाने के लिए कोई मान्यताओं पर कैसे अनुप्रयोगों का उपयोग करेगा इन तरीकों में है. कुछ मामलों में आवेदन चाहते हो सकता प्राप्त करने के लिए जाँच की IOExceptionएस (क्योंकि एक फ़ाइल से डेटा मौजूद होना चाहिए के लिए आवेदन करने के लिए काम), अन्य मामलों में आवेदन भी नहीं परवाह है, तो डेटा उपलब्ध नहीं है, क्योंकि (एक फ़ाइल से डेटा केवल कैश भी उपलब्ध है कि एक प्राथमिक स्रोत).

जब यह आता है करने के लिए मैं/हे कार्यों, वहाँ कभी नहीं है एक गारंटी है कि आपरेशन सफल होगा (जैसे उपयोगकर्ता फोन छोड़ने में शौचालय). पुस्तकालय को प्रतिबिंबित करना चाहिए कि और आवेदन देने के एक विकल्प पर संभाल करने के लिए कैसे त्रुटियों.

अनुकूलन करने के लिए मैं/हे प्रदर्शन हमेशा मान खुश "पथ" और त्रुटियों को पकड़ने के लिए पता लगाने की क्या गलत हो गया था. इस काउंटर सहज ज्ञान युक्त करने के लिए सामान्य प्रोग्रामिंग, लेकिन आवश्यक के साथ निपटने में भंडारण पर मैं/ओ के लिए उदाहरण के लिए, सिर्फ अगर जाँच फ़ाइल मौजूद है पढ़ने से पहले एक फ़ाइल से कर सकते हैं अपने आवेदन में दो बार के रूप में धीमी गति से, इन सभी की तरह मैं/हे कार्यों को जोड़ने के लिए तेजी से धीमी गति से अपने आवेदन नीचे. मान लेते हैं कि फ़ाइल मौजूद है और यदि आप एक त्रुटि मिलती है, तो केवल यदि फ़ाइल मौजूद है.

तो दिए गए उन विचारों, मुख्य कार्य की तरह लग सकता है:

public static void writeFile(File f, byte[] data) throws FileNotFoundException, IOException {
    try (FileOutputStream out = new FileOutputStream(f)) {
        out.write(data);
    }
}

public static int readFile(File f, byte[] data) throws FileNotFoundException, IOException {
    try (FileInputStream in = new FileInputStream(f)) {
        return in.read(data); 
    }
}

नोट कार्यान्वयन के बारे में:

  • के तरीकों में भी फेंक क्रम-अपवाद की तरह NullPointerExceptions - इन तरीकों में कभी नहीं जा रहे हैं होना करने के लिए "बग मुक्त".
  • मुझे नहीं लगता कि बफ़रिंग आवश्यक है/में चाहता था इसके बाद के संस्करण तरीकों के बाद से केवल एक देशी कॉल किया जाता है (यह भी देखें यहाँ).
  • आवेदन अब भी विकल्प है करने के लिए केवल पढ़ने के लिए शुरुआत के एक फ़ाइल.

करने के लिए यह आसान बनाने के लिए एक आवेदन पत्र पढ़ने के लिए एक फ़ाइल, एक अतिरिक्त विधि के साथ जोड़ा जा सकता है । लेकिन ध्यान दें कि यह अप करने के लिए पुस्तकालय का पता लगाने के लिए किसी भी त्रुटि की रिपोर्ट करने और उन्हें आवेदन करने के लिए आवेदन के बाद से ही कर सकते हैं अब का पता लगाने उन त्रुटियों.

public static byte[] readFile(File f) throws FileNotFoundException, IOException {
    int fsize = verifyFileSize(f);
    byte[] data = new byte[fsize];
    int read = readFile(f, data);
    verifyAllDataRead(f, data, read);
    return data;
}

private static int verifyFileSize(File f) throws IOException {
    long fsize = f.length();
    if (fsize > Integer.MAX_VALUE) {
        throw new IOException("File size (" + fsize + " bytes) for " + f.getName() + " too large.");
    }
    return (int) fsize;
}

public static void verifyAllDataRead(File f, byte[] data, int read) throws IOException {
    if (read != data.length) {
        throw new IOException("Expected to read " + data.length 
                + " bytes from file " + f.getName() + " but got only " + read + " bytes from file.");
    }
}

इस कार्यान्वयन के लिए कहते हैं एक बिंदु की विफलता: OutOfMemory है, जहां बिंदु पर नए डेटा सरणी बनाई गई है.

को समायोजित करने के लिए आवेदन इसके अलावा, अतिरिक्त तरीकों जोड़ा जा सकता है के साथ मदद के लिए अलग अलग परिदृश्य है. उदाहरण के लिए, चलो का कहना है कि आवेदन वास्तव में नहीं चाहते हैं के साथ सौदा करने के लिए जाँच अपवाद:

public static void writeFileData(File f, byte[] data) {
    try {
        writeFile(f, data);
    } catch (Exception e) {
        fileExceptionToRuntime(e);
    }
}

public static byte[] readFileData(File f) {
    try {
        return readFile(f);
    } catch (Exception e) {
        fileExceptionToRuntime(e);
    }
    return null;
}

public static int readFileData(File f, byte[] data) {
    try {
        return readFile(f, data);
    } catch (Exception e) {
        fileExceptionToRuntime(e);
    }
    return -1;
}

private static void fileExceptionToRuntime(Exception e) {
    if (e instanceof RuntimeException) { // e.g. NullPointerException
        throw (RuntimeException)e;
    }
    RuntimeException re = new RuntimeException(e.toString());
    re.setStackTrace(e.getStackTrace());
    throw re;
}

विधि fileExceptionToRuntime एक न्यूनतम कार्यान्वयन, लेकिन यह पता चलता है यहाँ पर विचार.

पुस्तकालय भी मदद कर सकता है एक आवेदन का निवारण करने के लिए जब एक त्रुटि होती है. उदाहरण के लिए, एक विधि canReadFile(File f) की जांच कर सकता है यदि फ़ाइल मौजूद है और पठनीय है और बहुत बड़ा नहीं है । आवेदन फोन कर सकता है इस तरह के एक समारोह के बाद एक फ़ाइल को पढ़ने में विफल रहता है, और जाँच के लिए आम कारणों से क्यों एक फ़ाइल को पढ़ा नहीं जा सकता. एक ही किया जा सकता है लिखने के लिए एक फाइल करने के लिए.

2021-11-28 22:59:55

की सराहना करते हैं, उपयोगी और जानकारीपूर्ण जवाब. मैं कर रहा हूँ यह डाल एक साथ एक परियोजना में देखने के लिए अगर मैं बेहतर समझ सकते हैं,. क्या कारण है को बदलने के लिए readBytes विधि हस्ताक्षर से मैं क्या था? (तुम्हारा एक बाइट[] के रूप में एक args और रिटर्न पूर्णांक). यह भी अपने अंतिम कोड के ब्लॉक का इरादा का हिस्सा बनने के लिए पुस्तकालय या आवेदन?
Nerdy Bunz

यह भी नहीं होंगे लाइन "वापसी (पूर्णांक) एफ.length();" दुर्घटना के बाद से एफ.की लंबाई की तुलना में बड़ा है पूर्णांक है.MAX_VALUE?
Nerdy Bunz

@NerdyBunz के बारे में आखिरी सवाल: नहीं, "downcasting नहीं करता है" एक त्रुटि दे और इस मामले में, एक IOException फेंक दिया जाता है जब fsize मूल्य बहुत बड़ा है. इसके अलावा, मैं होना चाहिए फिर से इस्तेमाल किया fsize वहाँ (के बाद से f.length() परिणाम में एक I/O कार्रवाई).
vanOekel

के बारे में पहला सवाल: यह सब करने का इरादा है का हिस्सा हो सकता है पुस्तकालय. मेरे byte[] readFile(File f) इसी तरह की है करने के लिए अपने byte[] readBytesFromFile(final File file). मेरे byte[] readFileData(File f) विधि का एक उदाहरण है कि कैसे अनुकूलित कर सकते हैं, इन कार्यों के लिए आगे. मैं परेशान था पता लगाना है जो तरीकों का पर्दाफाश करने के लिए (public) रखने के लिए और छिपा (private) और मुझे लगता है कि एक सवाल है, केवल आप का जवाब कर सकते हैं: तरीकों जो आप चाहते हैं आवेदन का उपयोग करने के लिए होने के बिना करने के लिए प्रतिबंधात्मक आवेदन करने के लिए?
vanOekel
3

हालांकि आप का उपयोग नहीं कर सकते तीसरे पक्ष के पुस्तकालयों के साथ, आप पढ़ सकते हैं अभी भी अपने कोड और उनके अनुभव से सीखना. गूगल में अमरूद उदाहरण के लिए, आप आमतौर पर पढ़ने के एक फ़ाइल बाइट्स में इस तरह:

FileInputStream reader = new FileInputStream("test.txt");
byte[] result = ByteStreams.toByteArray(reader);

कोर के कार्यान्वयन यह है toByteArrayInternal. फोन करने से पहले, आप की जाँच करनी चाहिए:

  • एक नहीं null फ़ाइल को पारित कर दिया है (NullPointerException)
  • फ़ाइल मौजूद है (FileNotFoundException)

उसके बाद, यह कम है से निपटने के लिए एक InputStream और इस जहां IOExceptions से आते हैं. जब पढ़ने धाराओं चीजों की एक बहुत कुछ के नियंत्रण से बाहर अपने आवेदन में गलत जा सकते हैं (बुरा क्षेत्रों और अन्य हार्डवेयर मुद्दों, मल-कामकाज ड्राइवरों, ओएस अधिकारों का उपयोग) और स्वयं को प्रकट के साथ एक IOException.

मैं हूँ यहाँ नकल कार्यान्वयन:

private static final int BUFFER_SIZE = 8192;

/** Max array length on JVM. */
private static final int MAX_ARRAY_LEN = Integer.MAX_VALUE - 8;

private static byte[] toByteArrayInternal(InputStream in, Queue<byte[]> bufs, int totalLen)
      throws IOException {
    // Starting with an 8k buffer, double the size of each successive buffer. Buffers are retained
    // in a deque so that there's no copying between buffers while reading and so all of the bytes
    // in each new allocated buffer are available for reading from the stream.
    for (int bufSize = BUFFER_SIZE;
        totalLen < MAX_ARRAY_LEN;
        bufSize = IntMath.saturatedMultiply(bufSize, 2)) {
      byte[] buf = new byte[Math.min(bufSize, MAX_ARRAY_LEN - totalLen)];
      bufs.add(buf);
      int off = 0;
      while (off < buf.length) {
        // always OK to fill buf; its size plus the rest of bufs is never more than MAX_ARRAY_LEN
        int r = in.read(buf, off, buf.length - off);
        if (r == -1) {
          return combineBuffers(bufs, totalLen);
        }
        off += r;
        totalLen += r;
      }
    }

    // read MAX_ARRAY_LEN bytes without seeing end of stream
    if (in.read() == -1) {
      // oh, there's the end of the stream
      return combineBuffers(bufs, MAX_ARRAY_LEN);
    } else {
      throw new OutOfMemoryError("input is too large to fit in a byte array");
    }
  }

के रूप में आप कर सकते हैं के तर्क के साथ करने के लिए फ़ाइल पढ़ने में हिस्सा । यह स्थितियों को संभालने के लिए है, जहां आप नहीं जानते का आकार InputStream शुरू करने से पहले, पढ़ने के लिए है । आपके मामले में, आप केवल करने की जरूरत फ़ाइलों को पढ़ने और आप में सक्षम होना चाहिए लंबाई पता करने के लिए पहले से है, तो यह जटिलता से बचा जा सकता है.

अन्य की जांच OutOfMemoryException. में मानक जावा की सीमा बहुत बड़ी है, लेकिन एंड्रॉयड में, यह हो जाएगा एक बहुत छोटा मान । आप की जाँच करनी चाहिए, कोशिश कर रहा से पहले फ़ाइल को पढ़ने के लिए है कि वहाँ है पर्याप्त स्मृति उपलब्ध है.

2021-11-26 13:42:23

अन्य भाषाओं में

यह पृष्ठ अन्य भाषाओं में है

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................

इस श्रेणी में लोकप्रिय

लोकप्रिय सवाल इस श्रेणी में