2012-11-11 15 views
8

पढ़ने के लिए मैं एक 132 केबी फ़ाइल है (क्या तुम सच में यह नहीं कह सकते कि यह बड़ा है) की कोशिश कर रहा है और मैं स्काला आरईपीएल से इसे पढ़ने के लिए कोशिश कर रहा हूँ, लेकिन मैं क्योंकि यह पहले ही 2048 चार नहीं पढ़ सकते हैंMalformedInputException जब पूरी फ़ाइल

val it = scala.io.Source.fromFile("docs/categorizer/usig_calles.json") // this is ok 
it.take(2048).mkString // this is ok too 
it.take(1).mkString // BANG! 

java.nio.charset.MalformedInputException: Input length = 1 
at java.nio.charset.CoderResult.throwException(CoderResult.java:277) 
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:338) 
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177) 
at java.io.InputStreamReader.read(InputStreamReader.java:184) 

किसी भी विचार क्या गलत हो सकता है: मुझे एक java.nio.charset.MalformedInputException अपवाद

ये कदम मैं ले रहे हैं देता है?

-

जाहिर है समस्या यह है कि फ़ाइल इनकोडिंग

मैं UTF के रूप में यह सहेजा नहीं UTF किया गया था और सब कुछ काम करता है, मैं तो बस पुनरावर्तक पर mkString जारी करने और यह फ़ाइल की पूरी सामग्री को पुन: प्राप्त

अजीब बात यह है कि त्रुटि केवल पहले 2048 वर्ण ही गुजर जगाया है ...

उत्तर

4

फ़ाइल के बिना कुछ नहीं हो सकता है, लेकिन अपवाद पर प्रलेखन इंगित करता है यह फेंक दिया जाता है "जब एक इनपुट बाइट seque एनसी दिया गया वर्णमाला के लिए कानूनी नहीं है, या इनपुट वर्ण अनुक्रम एक कानूनी सोलह-बिट यूनिकोड अनुक्रम नहीं है। " (MalformedInputException javadoc)

मुझे संदेह है कि 2049 में पहला चरित्र सामने आया है जो कि आपके पास पर्यावरण में डिफ़ॉल्ट जेवीएम चरित्र एन्कोडिंग के साथ मान्य नहीं है। fromFile.

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

+2

इस परीक्षण करने के लिए एक आसान तरीका नहीं है। यह निश्चित रूप से असली समस्या नहीं है, हालांकि, फ़ाइल में बिल्कुल '2^11 + 1' वर्णों पर पहले अवैध बाइट अनुक्रम को मारने के लिए बस एक शानदार संयोग होगा। –

+1

यह पहली चीज है जिसने मैंने कोशिश की, पूरे इटरेटर पर एक पतला mkString। फिर मैंने इसे 2048 तक ट्रैक किया ... – opensas

4

किसी भी समय आप एक ही पुनरावर्तक पर दो बार take फोन, सभी दांव बंद कर रहे हैं। Iterators स्वाभाविक रूप से अनिवार्य हैं, और उन्हें कार्यात्मक मुहावरे के साथ मिलाकर सबसे अच्छा पासा है। iterators आप मानक पुस्तकालय में पार चलो में से अधिकांश काफी इस संबंध में अच्छी तरह से व्यवहार हो जाते हैं, लेकिन एक बार आप take, या drop, या filter, आदि का उपयोग किया है, तो आप अपरिभाषित-व्यवहार भूमि में हैं, और में सिद्धांत कुछ भी हो सकता है।

the docs से:

यह ध्यान रखें कि, जब तक अन्यथा न कहा गया विशेष महत्व का है, एक यह पर एक विधि बुला के बाद पुनरावर्तक का उपयोग कभी नहीं करना चाहिए। दो सबसे महत्वपूर्ण अपवाद भी एकमात्र सार तरीके हैं: next और hasNext ...

def take(n: Int): Iterator[A] ...

पुन: उपयोग: इस विधि बुला के बाद, एक इटरेटर यह पर बुलाया गया था त्यागने चाहिए, और केवल उस इटरेटर का उपयोग करें जो लौटाया गया था। पुराने इटरेटर का उपयोग अपरिभाषित है, परिवर्तन के अधीन है, और परिणामस्वरूप नए इटरेटर में भी परिवर्तन हो सकता है।

तो यह शायद नीचे ट्रैक करने के लिए वास्तव में क्या गलत यहाँ चला गया कोशिश कर रहा लायक नहीं है।

+0

मैं शुरुआत से 'it.toList' करने का सुझाव देना चाहता हूं। इस तरह, वह सभी डेटा प्राप्त करने में सक्षम हो जाएगा। – pedrofurla

+0

@pedrofurla: दाएं, या 'toStream' अगर वह (या वह? पेंगुइन अवतार छवि मामूली रूप से फसल हो गई है, इसलिए मैं नहीं बता सकता) को पूरी फ़ाइल को पढ़ने की आवश्यकता नहीं है। –

+0

बहुत सच, ट्रैविस। – pedrofurla

2

तुम सिर्फ सादा लैटिन आंकड़ों के बाइट्स परिवर्तित करना चाहते हैं: 2049 तत्वों पहली बार लेकर देखें:

// File: 
io.Source.fromFile(file)(io.Codec.ISO8859).mkString 

// InputStream: 
io.Source.fromInputStream(System.io)(io.Codec.ISO8859).mkString 
संबंधित मुद्दे