2012-10-15 10 views
10
readFile "file.html" 
"start of the file... *** Exception: file.html: hGetContents: invalid argument (invalid code page byte sequence) 

यह नोटपैड ++ के साथ बनाई गई एक यूटीएफ -8 फ़ाइल है ... मैं हैकेल में फ़ाइल कैसे पढ़ सकता हूं?हैकेल - अमान्य कोड पेज बाइट अनुक्रम

+0

क्या आप शायद एक न्यूनतम फ़ाइल का हेक्स डंप पोस्ट कर सकते हैं जो आपके लिए यह त्रुटि दिखाता है? मैं आपकी त्रुटि को डुप्लिकेट नहीं कर सकता। – ghoti

+1

इस चरित्र का प्रयोग करें: 'č' –

+0

आपका लोकेल क्या है? क्या यह एक यूटीएफ -8 एक या कुछ ucs2ish है (नोटपैड ++ विंडोज का सुझाव देता है)? –

उत्तर

12

डिफ़ॉल्ट रूप से, सिस्टम लोकेल में फ़ाइलें पढ़ी जाती हैं, इसलिए यदि आपके पास गैर-मानक एन्कोडिंग का उपयोग करने वाली फ़ाइल है, तो आपको फ़ाइल को एन्कोडिंग स्वयं को संभालने की आवश्यकता है।

foo = do 
    handle <- openFile "file.html" ReadMode 
    hSetEncoding handle utf8_bom 
    contents <- hGetContents handle 
    doSomethingWithContents 
    hClose handle 

आपको प्रारंभ करना चाहिए। ध्यान दें कि यह कोई त्रुटि हैंडलिंग शामिल हैं, बेहतर तरीका इस प्रकार होगा

import Control.Exception -- for bracket 

foo = bracket 
     (openFile "file.html" ReadMode >>= \h -> hSetEncoding h utf8_bom >> return h) 
     hClose 
     (\h -> hGetContents h >>= doSomething) 

या

foo = withFile "file.html" ReadMode $ 
     \h -> do hSetEncoding h utf8_bom 
       contents <- hGetContents h 
       doSomethingWith contents 
+0

मैं कुछ इसी तरह के साथ आया (जैसे आपके 'foo' उदाहरण, हालांकि मुझे' _bom' .. के बारे में पता नहीं था)। क्या मैं बाहर की गणना करना संभव है, जैसा कि मैं इसे 'readFile' के साथ करता हूं? 'foo' उदाहरण काम करता है अगर मैं' hClose' लाइन का उपयोग नहीं करता (और यह मेरे खिलौने कार्यक्रम के लिए ठीक है, लेकिन "सही तरीका" जानना चाहता हूं .. क्या मुझे कुछ आईओ (स्ट्रिंग, हैंडल) '?) –

+0

यह थोड़ा मुश्किल है, अगर आपको अपनी फ़ाइल को आलसी पढ़ने की आवश्यकता है। जब गणना गणना होती है, तो 'hClose' फ़ाइल को बंद कर देता है, जो फ़ाइल के कुछ भी पढ़ने से पहले हो सकता है। तो यदि आपके पास एक ही समय में पूरी फ़ाइल मेमोरी हो सकती है, तो एक साधारण '' लम्बाई सामग्री 'सीईसी' रिटर्न कंटेंट 'करने से पूरी फाइल पढ़ना पड़ेगा और आप बाहर प्रसंस्करण कर सकते हैं। अन्यथा, शायद आलसी 'बाइटस्ट्रिंग' के रूप में फ़ाइल को पढ़ने के लिए सबसे अच्छा होगा और उस से कनवर्ट करें ('utf8-string' पैकेज से 'Data.ByteString.Lazy.UTF8.toString' का उपयोग करके)। –

+0

मैं नहीं देखता कि कैसे 'बाइटस्ट्रिंग' चीजों को आसान बनाता है/बनाता है (हालांकि मैं एक नौसिखिया हूं) .. 'readFile' आलसी है, है ना? तो यह फ़ाइल को कैसे बंद करता है? क्या यह जांचता है कि आखिरी चरित्र पढ़ा गया था? क्या मैं किसी भी तरह से इसका व्यवहार अनुकरण कर सकता हूं? –

1

this site के अनुसार, अपने 6 बाइट्स इस प्रकार डिकोड:

EF BB BF -> ZERO WIDTH NO-BREAK SPACE (i.e. the BOM, although its not needed in UTF-8 
C4 8D -> LATIN SMALL LETTER C WITH CARON (what you said) 
0D  -> CARRIAGE RETURN (CR) 

तो इसकी एक कानूनी यूटीएफ -8 अनुक्रम।

हालांकि मानक प्रीलूड फ़ंक्शन मूल रूप से बस ASCII करते थे। मुझे नहीं पता कि वे अब क्या करते हैं, लेकिन कुछ और विचारों के लिए इस प्रश्न को How does GHC/Haskell decide what character encoding it's going to decode/encode from/to? देखें। और फिर प्रीलूड फ़ंक्शंस के बजाय http://hackage.haskell.org/package/utf8-string का उपयोग करें।

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