क्या किसी फाइल को कच्ची बाइट्स लिखने में कोई खतरा है? [बन्द है]


12

मैं प्रोग्रामिंग पर्ल में एक समस्या के माध्यम से काम कर रहा हूं - विशेष रूप से, एक प्रोग्राम का कार्यान्वयन जो एक फ़ाइल को सॉर्ट करता है, अधिकतम 10,000,000 पूर्णांक (कॉलम 1, समस्या 3)। चूंकि पुस्तक निर्दिष्ट नहीं करती है कि डेटा को फ़ाइल में कैसे संग्रहीत किया जाना चाहिए, इसलिए मैं पूर्णांक को कच्चे बाइट के रूप में संग्रहीत करने पर विचार कर रहा हूं (कुछ अन्य बाधाएं हैं जो कच्चे बाइट्स को एक अच्छा विकल्प बनाते हैं)। मैंने पहले कभी भी इस स्तर पर काम नहीं किया है, इसलिए मैं जानना चाहता हूं कि क्या कुछ खतरनाक है जिसे मुझे देखना चाहिए। उदाहरण के लिए, जब मैं किसी फ़ाइल को कच्चे बाइट्स लिख रहा हूँ, तो क्या मुझे किसी प्रकार के एंड-ऑफ़-सीक्वेंस सीक्वेंस का उपयोग करने की चिंता है?

संपादित करें:

मुझे अब एहसास हुआ कि मेरा सवाल कितना व्यापक था। मुझे वास्तव में अधिक भयावह प्रकार की समस्याओं का मतलब था, जैसे गलती से डिस्क पर अन्य फ़ाइलों को ओवरराइट करना। क्षमा करें, मैं मूल रूप से स्पष्ट नहीं था।


6
ध्यान दें कि प्रोग्रामिंग मोती एक बहुत पुरानी पुस्तक है; आप आसानी से एक आधुनिक डेस्कटॉप मशीन पर मेमोरी में पूरे 10 ^ 7 पूर्णांक को पढ़ सकते हैं, सॉर्ट कर सकते हैं और इसे फिर से लिख सकते हैं। उस अध्याय के मूल बिंदु को प्राप्त करने के लिए, आप किसी भी समय पढ़ी गई राशि को कुल संख्या के एक अंश तक सीमित करें। या, फ़ाइल का आकार लगभग 10 ^ 10 पूर्णांक तक बढ़ाएं।
कालेब

3
दरअसल, जब मैं "खतरनाक" शब्द सुनता हूं, तो मैं उन चीजों के बारे में सोचता हूं जो मेरे पीसी में विस्फोट करते हैं, मेरे बैंक खाते या कुछ ऐसा हटाते हैं। और मुझे लगता है कि यह शायद यह मान लेना सुरक्षित है कि - जब तक आपके प्रोग्राम का उपयोग एयरबस या पावर प्लांट को नियंत्रित करने के लिए नहीं किया जाता है - तब तक वास्तव में "खतरनाक" कुछ भी नहीं होगा जब आप अपने दिमाग में जो कुछ भी करते हैं, वह कोशिश करते हैं।
डॉक्टर ब्राउन


2
@delnan साल पहले, जब EOF चरित्र का मिथक प्रचलन में था, मुझे कॉपी प्रोटेक्शन सिस्टम याद आता है जो उस समय के कई कॉपी प्रोग्राम्स 'नकल ईओएफ चरित्र' पर आधारित थे। कुछ प्रोग्राम अतिरिक्त डेटा डालेंगे जो वे संबंधित पाठ फ़ाइल के ईओएफ मार्कर के बाद जांच करेंगे , लेकिन फ़ाइल के आवंटित अंत से पहले। प्रतिलिपि प्रोग्राम अतिरिक्त डेटा को एक क्लीन इंस्टॉल मान्य करने की प्रतिलिपि नहीं करेगा ... आह ... नॉस्टैल्जिया।

खतरा? जैसे "अगर मैं ऐसा करूँगा तो क्या मेरा कंप्यूटर उड़ जाएगा?" नहीं।
जिवंत

जवाबों:


11

एकमात्र खतरा जिसे आप चलाएंगे, वह छोटे बनाम बड़े धीरज (चाहे सबसे पहले या सबसे महत्वपूर्ण बाइट पहले लिखा गया हो)। हालाँकि यदि आप एक ही वातावरण में रहेंगे तो कोई समस्या नहीं होगी। लेखन / पार्सिंग राउंडट्रिप के सामान्य सुनिश्चित करने के अलावा।

फ़ाइल सिस्टम को बाइट्स के किसी भी क्रम को संभालने के लिए डिज़ाइन किया गया है।


2
अंतिम पंक्ति के लिए +1। मुझे यकीन नहीं है कि बड़ा / छोटा मुद्दा एकमात्र समस्या है - उदाहरण के लिए ओपी भ्रमित हो सकता है कि पूर्णांक के बीच सीमा कहां है। लेकिन वैसे भी अच्छा जवाब।
कालेब

27

नहीं, वास्तव में यह है कि कितने फ़ाइल स्वरूप काम करते हैं। इस तरह की बाइनरी फाइलों के सामान्य उदाहरणों में चित्र और संगीत / ऑडियो फाइलें शामिल हैं।

फ़ाइल की अखंडता और इससे पढ़े गए डेटा को बनाए रखने के लिए, इन दिशानिर्देशों का पालन करना सुनिश्चित करें:

  • हमेशा एक ही मोड का उपयोग करके फ़ाइल (पढ़ना या लिखना) खोलें: पाठ या बाइनरी। प्राथमिक अंतर टेक्स्ट मोड में नईलाइन्स के बारे में है, और फ़ाइल को पढ़ते समय नईलाइन्स के पात्रों को "धूमिल" कर सकता है (विशिष्ट लाइब्रेरी के उपयोग के आधार पर)। पाठ मोड यूनिकोड अनुवाद भी कर सकता है जो संभवतः गैर-यूनिकोड डेटा पर चोक होगा।
  • गैर-स्ट्रिंग डेटा को पढ़ते समय, उसी डेटा प्रकार का उपयोग करके पढ़ना सुनिश्चित करें जैसे आप लिखते हैं। उदाहरण के लिए, यदि फ़ाइल के पहले चार बाइट एक वर्णनात्मक पूर्णांक हैं, तो एक विधि का उपयोग करके पढ़ना और लिखना सुनिश्चित करें जो यह सुनिश्चित करने के लिए पूर्णांक लेता है / प्रदान करता है कि इसे लगातार व्यवहार किया जाता है। एक ही डेटा प्रकार का अलग-अलग मशीनों पर अलग-अलग आकार हो सकता है, और एक ही मशीन पर डेटा प्रकारों को मिलाने से डेटा का अर्थ भी बदल सकता है (जैसे कि साइन बिट के रूप में एक लंबे पूर्णांक के बीच में बिट की व्याख्या करना)।
  • एंडियननेस: यदि आप जिस लाइब्रेरी का उपयोग कर रहे हैं, वह इसे लगातार नहीं संभालती है, तो आपको इसे स्वयं संभालने की आवश्यकता हो सकती है। उदाहरण के लिए, जावा हमेशा मल्टी-बाइट प्रकारों के लिए नेटवर्क बाइट ऑर्डर (बड़ा एंडियन) का उपयोग करता है। C और C ++ पुस्तकालय कार्यान्वयनकर्ता ने जो भी निर्णय लिया, उसका उपयोग करें, आमतौर पर प्रोसेसर के समान (इंटेल पर थोड़ा एंडियन, अन्य लोगों पर बड़ा एंडियन)। यदि यह एक प्रणाली पर एक त्वरित अभ्यास है, तो यह उतना महत्वपूर्ण नहीं है, लेकिन फिर भी इस पर ध्यान देना और यदि आवश्यक हो तो इसके आसपास कोड करना एक अच्छी आदत है।

विशिष्ट विवरण फ्रेमवर्क, प्लेटफ़ॉर्म और भाषा के आधार पर अलग-अलग होंगे, लेकिन इसमें फ़ाइल I / O के साथ मूल "गोच" को कवर करना चाहिए।


3
गैर-स्ट्रिंग डेटा के लिए एक अतिरिक्त बिंदु: सुनिश्चित करें कि आप प्रत्येक प्रकार के लिए लगातार बाइट्स का उपयोग करते हैं। C और C ++ में int2 और 8 या अधिक बाइट्स (ऑक्टेट्स वास्तव में) के बीच कहीं भी हो सकते हैं।
बार्ट वैन इनगेन शेनौ

यह मेरे दूसरे बिंदु के साथ निहित है, उदाहरण के लिए 32 v। 64 बिट पूर्णांक। वे विभिन्न प्रकार के डेटा होंगे।

आप इसे स्पष्ट करना चाहते हैं। यह स्पष्ट नहीं है कि intदो अलग-अलग मशीनों पर अलग-अलग डेटाटिप्स माना जा सकता है।
बार्ट वैन इनगेन शेनॉ

9

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

अच्छा फ़ाइल हेडर में कम से कम तीन चीजें शामिल होती हैं:

  • एक " मैजिक नंबर ", कम से कम चार बाइट्स का। मैजिक नंबर MUST rfc2119 फाइल में बहुत पहले N बाइट्स होना चाहिए, MUST कभी भी किसी अन्य फाइल फॉर्मेट के लिए इस्तेमाल नहीं किया जा सकता है, जिसे आप खोद सकें, और उसमें कम से कम एक बाइट शामिल हो, जो प्रिंट करने योग्य ASCII कैरेक्टर न हो। वास्तव में पूरी तरह से मैजिक नंबर कैसे डिजाइन करें, इसके लिए पीएनजी विनिर्देश देखें । मौजूदा मैजिक नंबरों के एक डेटाबेस के लिए कमांड का सोर्स कोड देखें जो कि जितना संभव हो उतना व्यापक हो।file(1)

    एक जादू की संख्या का बिंदु स्पष्ट रूप से फ़ाइल, इन-बैंड को इसके प्रारूप के साथ लेबल करना है। यदि आप एक मैजिक नंबर शामिल नहीं करते हैं, या यह फ़ाइल में पहली चीज़ नहीं है, तो आप प्रोग्राम को अपनी फ़ाइल को किसी अन्य प्रकार की फ़ाइल के रूप में गलत तरीके से चलाने का जोखिम उठाते हैं , जिससे डेटा हानि, वायरस का पता लगाना , और अन्य तरह की हानि होती है आपदाओं।

  • फ़ाइल प्रारूप के संस्करण का एक संकेत । यहां तक ​​कि अगर आपको लगता है कि आपको कभी भी अपने फ़ाइल प्रारूप को संशोधित करने की आवश्यकता नहीं है, तो जादू नंबर होने के बाद अगले दो बाइट्स बनाएं 00 00और दस्तावेज़ करें कि यह कुछ निश्चित एंडियननेस में 16-बिट संस्करण संख्या है (जो भी आपको पसंद हो, लेकिन चुनें एक और फ़ाइल में यह चिपके रहते हैं ) और बाद में डेटा के अर्थ में मौलिक परिवर्तन होने पर इसे बढ़ाया जाएगा। आपका भविष्य स्वयं आपको धन्यवाद देगा।

    (PNG विनिर्देश यहां एक अलग मार्ग लेता है, यह निर्दिष्ट करते हुए कि चंक प्रारूप जमे हुए हैं, और प्रारूप में भविष्य के सभी परिवर्तन नए चंक प्रकारों का रूप ले लेंगे। यह मान्य भी है, लेकिन मैं सरल मैजिक नंबर + संस्करण संख्या दृष्टिकोण के लिए सलाह देता हूं। शुरुआती बाइनरी डेटा प्रोसेसिंग के लिए। पीएनजी डिजाइन करने वाले लोग छवि के स्वरूपों के साथ सामूहिक दशकों के अनुभव पर काम कर रहे थे।)

  • फ़ाइल में मनमाना मेटाडेटा एम्बेड करने के लिए किसी प्रकार का तंत्र । यह उतना ही सरल हो सकता है जितना कि अगले दो बाइट्स हेडर के अंत से वास्तविक डेटा की शुरुआत तक 16-बिट ऑफसेट होना चाहिए, जिसमें यूटीएफ -8 की-वैल्यू जोड़े को ला आरएफसी 822 के रूप में व्याख्या की जानी चाहिए। (यह है, " Tag: value\n" - यदि आप इस मार्ग पर जाते हैं तो मैं लंबी लाइनों को मोड़ने की अनुमति नहीं देने की सलाह देता हूं )। फिर, पीएनजी काफी चतुर है।


अपने खुद के फ़ाइल स्वरूप को बनाने की आवश्यकता नहीं है ... बस छवि के रूप में डेटा संग्रहीत करें। आपको आयाम बदलने की आवश्यकता हो सकती है (उदाहरण के लिए, 10k x 1k) इसलिए इसका समर्थन किया जाएगा। या आप FITS का उपयोग कर सकते हैं । यदि आपके डेटा की मात्र एक सरणी से अधिक जटिल है, तो आप HDF , CDF या NetCDF का उपयोग कर सकते हैं ।
जो

मैं इसे सरल रखने का सुझाव दूंगा। 256 अलग-अलग संस्करण पर्याप्त होंगे और यदि नहीं, तो अतिरिक्त संस्करणों को संस्करण 255 के विध्वंस के रूप में तैयार किया जा सकता है। इसी तरह मेटाडेटा के लिए, उन्हें संस्करण में जोड़ना आवश्यक है जब वे वास्तव में आवश्यक हों। @ जो छवि ??? आप सभी को पहले से भ्रमित करके संभावित प्रारूप भ्रम से बच रहे हैं!
Maaartinus

@maaartinus संस्करण फ़ील्ड को दो बाइट्स बनाने से प्रारूप डिज़ाइनर को सामने की ओर धीरज रखने के लिए बाध्य किया जाता है। मेटाडेटा के लिए स्थान हमेशा एक द्विआधारी प्रारूप के संस्करण 0 में होना चाहिए, अन्यथा आप आईडी 3 जैसे भयानक कीचड़ के साथ हवा करते हैं। मेरे पास पीएनजी के तर्क के बारे में बहुत अधिक सहानुभूति है क्योंकि प्रारूप संस्करण धक्कों के बजाय नए चंक प्रकारों के माध्यम से एक्स्टेंसिबिलिटी के बारे में तर्क है। हालांकि, चंक-संरचित फाइलें अपने स्वयं की जटिलता का एक गुच्छा लाती हैं इसलिए मैं उन्हें सरल मामलों के लिए सिफारिश करने में संकोच करता हूं। मुझे एचडीएफ की सिफारिश एक सामान्य प्रारूप के रूप में करने के लिए लुभाया गया था जो इन मुद्दों के बहुत से पहले से ही निपटा है।
zwol

2

विभिन्न आर्किटेक्चर में पूर्णांकों के लिए अलग-अलग अभ्यावेदन होते हैं। यहाँ मुख्य जोखिम मशीन ए में पूर्णांक के बाइट प्रतिनिधित्व को बचा रहा है और फिर उस मशीन बी में पूर्णांक के रूप में सामग्री को वापस पढ़ने और व्याख्या करने का प्रयास कर रहा है । यदि मशीन ए और बी में पूर्णांक और / या अलग-अलग एंडियननेस के लिए अलग-अलग आकार हैं , तो आप ' सबसे अधिक संभावना अपरिभाषित व्यवहार का कारण होगा (जैसे C में) या एक अपवाद।

चूंकि यह सिर्फ एक प्रोग्रामिंग उदाहरण है और "वास्तविक" कार्यक्रम नहीं है, यह वास्तव में एक मुद्दा नहीं है। यदि यह एक वास्तविक कार्यक्रम था, तो अपने स्वयं के एप्लिकेशन-विशिष्ट बाइनरी प्रारूप को रोल करना आमतौर पर एक अच्छा विचार नहीं है; बेहतर समाधान हैं, जैसे कि SQLite या स्ट्रिंग-आधारित क्रमांकन प्रारूप जैसे JSON, YAML, XML, आदि। एकल मानों के लिए इसे एक स्ट्रिंग में बदलना पर्याप्त होगा; सरल सूचियों के लिए आप प्रति पंक्ति एक स्ट्रिंग को बचा सकते हैं और जब आप इसे वापस पढ़ते हैं तो केवल इनपुट को नई सीमा पर विभाजित करते हैं।


सामान्य रूप से सहमत हैं, लेकिन JSON या XML में 10 ^ 7 नंबर वाली फ़ाइल का आकार काफी बढ़ जाएगा। इसके अलावा, वे आम तौर पर पढ़े जाते हैं और एक ही बार में पार्स हो जाते हैं, लेकिन प्रश्न में अध्याय उन फ़ाइलों को छांटने का काम करता है, जिनमें उपलब्ध डेटा से अधिक डेटा उपलब्ध होता है।
कालेब

यह इस बात पर निर्भर करता है कि आप क्या कर रहे हैं। कभी-कभी एसक्यूएल बनाम रोल-योर-ओन का प्रदर्शन हिट होता है। पिछली बार जब मैंने ऐसा किया था तो मेरे पास छोटे रिकॉर्ड थे और एक उच्च संभावना थी कि मुझे पड़ोसी चाहिए। डिस्क से एक बड़ा ब्लॉक पढ़ना आम तौर पर लगभग कुछ भी खर्च नहीं होगा, अगर मुझे एक रिकॉर्ड चाहिए था तो मैं एक कैश में 1000 पढ़ता हूं। मेरे रिकॉर्ड लगभग निश्चित रूप से एक दूसरे के बगल में थे, एसक्यूएल के साथ डिस्क सिर सभी जगह उछल रहा होगा।
लोरेन Pechtel
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.