Java FileReader एन्कोडिंग समस्या


130

मैंने कुछ पाठ फ़ाइलों को पढ़ने और उन्हें एक स्ट्रिंग में बदलने के लिए java.io.FileReader का उपयोग करने की कोशिश की, लेकिन मैंने पाया कि परिणाम गलत तरीके से एन्कोड किया गया है और बिल्कुल भी पठनीय नहीं है।

यहाँ मेरा वातावरण है:

  • विंडोज 2003, ओएस एन्कोडिंग: CP1252

  • जावा 5.0

मेरी फाइलें UTF-8 एनकोडेड या CP1252 एन्कोडेड हैं, और उनमें से कुछ (UTF-8 एनकोडेड फाइलें) में चीनी (गैर-लैटिन) अक्षर हो सकते हैं।

मैं अपना काम करने के लिए निम्नलिखित कोड का उपयोग करता हूं:

   private static String readFileAsString(String filePath)
    throws java.io.IOException{
        StringBuffer fileData = new StringBuffer(1000);
        FileReader reader = new FileReader(filePath);
        //System.out.println(reader.getEncoding());
        BufferedReader reader = new BufferedReader(reader);
        char[] buf = new char[1024];
        int numRead=0;
        while((numRead=reader.read(buf)) != -1){
            String readData = String.valueOf(buf, 0, numRead);
            fileData.append(readData);
            buf = new char[1024];
        }
        reader.close();
        return fileData.toString();
    }

उपरोक्त कोड काम नहीं करता है। मुझे लगा कि FileReader की एन्कोडिंग CP1252 है भले ही पाठ UTF-8 एन्कोडेड हो। लेकिन java.io.FileReader के JavaDoc का कहना है कि:

इस वर्ग के निर्माता मानते हैं कि डिफ़ॉल्ट चरित्र एन्कोडिंग और डिफ़ॉल्ट बाइट-बफर आकार उपयुक्त हैं।

क्या इसका मतलब यह है कि अगर मैं FileReader का उपयोग कर रहा हूं तो मुझे खुद से चरित्र एन्कोडिंग सेट करने की आवश्यकता नहीं है? लेकिन मुझे वर्तमान में गलत तरीके से एन्कोड किया गया डेटा मिला है, मेरे सैटूटियन से निपटने का सही तरीका क्या है? धन्यवाद।


आपको लूप के अंदर String.valueOf () को भी ढीला करना चाहिए और सीधे StringBuffer.append (char [], int, int) का उपयोग करना चाहिए। यह चार [] की बहुत नकल बचाता है। इसके अलावा StringBuffer को StringBuilder से बदलें। इसमें से कोई भी आपके प्रश्न के बारे में नहीं है, 'हालांकि।
जोकिम सॉर

1
मुझे यह कहने से नफरत है, लेकिन क्या आपने जो हिस्सा चिपकाया है उसके ठीक बाद आपने जावाडोक को पढ़ा है? आप जानते हैं, जो हिस्सा कहता है "इन मूल्यों को स्वयं निर्दिष्ट करने के लिए, एक FileInputStream पर InputStreamReader का निर्माण करें?"
पॉवरलॉर्ड

आपकी टिप्पणी के लिए धन्यवाद, वास्तव में मैंने जावाडॉक पढ़ा, लेकिन मुझे यकीन नहीं है कि क्या मुझे इन मूल्यों को स्वयं निर्दिष्ट करना चाहिए या नहीं, और "FileInputStream पर एक InputStreamReader का निर्माण" करने के लिए स्विच करें।
nybon

हां, यदि आप जानते हैं कि फ़ाइल प्लेटफ़ॉर्म डिफ़ॉल्ट एन्कोडिंग के अलावा किसी और चीज़ में है, तो आपको InputStreamReader को बताना होगा कि किसका उपयोग करना है।
एलन मूर

जवाबों:


248

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

हां, इसका मतलब है कि आपको उस फ़ाइल की एन्कोडिंग को जानना होगा जिसे आप पढ़ना चाहते हैं।

नहीं, किसी भी "सादे पाठ" फ़ाइल के एन्कोडिंग का अनुमान लगाने का कोई सामान्य तरीका नहीं है ।

FileReaderप्लेटफ़ॉर्म डिफ़ॉल्ट एन्कोडिंग का उपयोग करने वाले एक-तर्कों के निर्माता आमतौर पर एक बुरा विचार होते हैं

चूंकि जावा 11 FileReaderने निर्माणकर्ता भी प्राप्त किए हैं जो एन्कोडिंग को स्वीकार करते हैं: new FileReader(file, charset)और new FileReader(fileName, charset)

जावा के पुराने संस्करणों में, आपको उपयोग करने की आवश्यकता है ।new InputStreamReader(new FileInputStream(pathToFile), <encoding>)


1
InputStream = नया FileInputStream (फ़ाइल नाम) है; यहाँ मुझे रूसी फ़ाइल नाम के साथ त्रुटि फ़ाइल नहीं मिली
भानु शर्मा

3
InputStreamReader का उपयोग करने के सुझाव के लिए +1, हालांकि कोड ब्लॉक में लिंक का उपयोग करने से कोड को कॉपी और पेस्ट करना मुश्किल हो जाता है, अगर इसे बदला जा सकता है, तो thx
Ferrybig

1
क्या यह एन्कोडिंग्स में "UTF-8" या "UTF8" होगा। एन्कोडिंग पर जावा एसई संदर्भ के अनुसार , चूंकि InputStreamReaderएक java.ioवर्ग है, यह "यूटीएफ 8" होगा?
नोबल अपलिफ्ट

9
@ नोबलअपलिफ्ट: सबसे सुरक्षित शर्त है StandardCharsets.UTF_8, वहां गलती करने का कोई मौका नहीं है;; लेकिन हां, यदि आप स्ट्रिंग के साथ जाते हैं, तो "UTF8"यह सही होगा (हालांकि मुझे लगता है कि यह दोनों तरीकों को स्वीकार करेगा)।
जोकिम सॉउर

1
@JoachimSauer वास्तव में, यह एक उद्देश्य है Byte Order Mark.. साथ में .. अच्छी तरह से .. बाइट ऑर्डर की स्थापना! :) जैसा कि मुझे यह अजीब लगता है कि जावा का FileReader स्वतः ही UTF-16 का पता लगाने में सक्षम नहीं है, जिसमें ऐसा BOM है ... वास्तव में मैंने एक बार एक UnicodeFileReaderऐसा लिखा था जो वास्तव में ऐसा करता है। दुर्भाग्य से बंद स्रोत, लेकिन Google के पास यह यूनिकोड राइडर है जो बहुत समान है।
स्टिजन डे विट

79

FileReader जावा के प्लेटफ़ॉर्म डिफ़ॉल्ट एन्कोडिंग का उपयोग करता है, जो उस पर चल रहे कंप्यूटर की सिस्टम सेटिंग्स पर निर्भर करता है और यह आमतौर पर उस लोकेल में उपयोगकर्ताओं के बीच सबसे लोकप्रिय एन्कोडिंग है।

यदि यह "सर्वश्रेष्ठ अनुमान" सही नहीं है, तो आपको एन्कोडिंग को स्पष्ट रूप से निर्दिष्ट करना होगा। दुर्भाग्य से, FileReaderयह (एपीआई में प्रमुख निरीक्षण) की अनुमति नहीं देता है। इसके बजाय, आपको उपयोग करना होगा new InputStreamReader(new FileInputStream(filePath), encoding)और आदर्श रूप से फ़ाइल के बारे में मेटाडेटा से एन्कोडिंग प्राप्त करना होगा।


24
"एपीआई में प्रमुख निरीक्षण" - इस स्पष्टीकरण के लिए धन्यवाद - मैं सोच रहा था कि मैं उस कंस्ट्रक्टर को क्यों नहीं ढूंढ पाया जो मैं था! चीयर्स जॉन
मोनोजोनी

@ भानू शर्मा: यह एक अलग स्तर पर एक एन्कोडिंग मुद्दा है, जाँच करें कि आपको फ़ाइल नाम कहाँ से मिल रहा है, और यदि यह हार्डकोड किया गया है कि संकलक किस एन्कोडिंग का उपयोग करता है।
माइकल बोर्गवर्ड

1
@ भानुशर्मा: फ़ाइल नाम एन्कोडिंग मुद्दों को इस सवाल से कोई लेना-देना नहीं है। कई मौजूदा "क्यों यूनिकोड फ़ाइलनाम जावा में काम नहीं करते हैं" सवालों में से एक देखें। Spoiler: java.io APIs जैसे FileReader C मानक पुस्तकालय फाइलसिस्टम कॉल का उपयोग करता है, जो विंडोज पर यूनिकोड का समर्थन नहीं कर सकता; इसके बजाय java.nio का उपयोग करने पर विचार करें।
बॉबिन

1
" FileReaderजावा के प्लेटफ़ॉर्म डिफ़ॉल्ट एन्कोडिंग का उपयोग करता है, जो उस पर चल रहे कंप्यूटर की सिस्टम सेटिंग्स पर निर्भर करता है और यह आमतौर पर उस लोकेल में उपयोगकर्ताओं के बीच सबसे लोकप्रिय एन्कोडिंग है।" मैं ऐसा नहीं कहूंगा। कम से कम विंडोज की। कुछ अजीब तकनीकी / ऐतिहासिक कारणों के लिए, जेवीएम इस तथ्य को नजरअंदाज करता है कि यूनिकोड 'सभी नए अनुप्रयोगों' के लिए विंडोज पर अनुशंसित एन्कोडिंग है और इसके बजाय हमेशा कार्य करता है जैसे कि विरासत एन्कोडिंग को लीगेसी एप्लिकेशन के लिए फ़ॉलबैक के रूप में कॉन्फ़िगर किया गया है जो 'प्लेटफ़ॉर्म डिफ़ॉल्ट' है।
स्टिजन डे विट

6
मैं यहां तक ​​कहूंगा कि अगर आपका जावा ऐप हर बार पढ़ने या लिखने के लिए फाइल / स्ट्रीम / रिसोर्स को स्पष्ट रूप से निर्दिष्ट नहीं करता है , तो यह टूट गया है , क्योंकि यह कभी मज़बूती से काम नहीं कर सकता है
स्टिजेन डी विट


6

जावा 7+ डॉक के लिए आप इसका उपयोग कर सकते हैं:

BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8);

यहां सभी चार्ट डॉक हैं

उदाहरण के लिए यदि आपकी फ़ाइल CP1252 में है, तो इस विधि का उपयोग करें

Charset.forName("windows-1252");

यहाँ IO और NIO doc दोनों के लिए जावा एनकोडिंग के लिए अन्य विहित नाम हैं

आप वास्तव में एन्कोडिंग आप एक फ़ाइल में मिल गया है साथ पता नहीं है, तो आप गूगल से इस उपकरण की तरह कुछ तृतीय-पक्ष libs का उपयोग कर सकते यह जो काफी साफ काम करता है।


1

InputRreamReader के साथ FileInputStream सीधे FileReader का उपयोग करने से बेहतर है, क्योंकि उत्तरार्द्ध आपको एन्कोडिंगसेट को निर्दिष्ट करने की अनुमति नहीं देता है।

यहाँ एक उदाहरण बफ़रड्रेडर, फाइलइंस्ट्रीमस्ट्रीम और इनपुटस्ट्रीमरएडर का एक साथ उपयोग किया गया है, ताकि आप एक फ़ाइल से लाइनें पढ़ सकें।

List<String> words = new ArrayList<>();
List<String> meanings = new ArrayList<>();
public void readAll( ) throws IOException{
    String fileName = "College_Grade4.txt";
    String charset = "UTF-8";
    BufferedReader reader = new BufferedReader(
        new InputStreamReader(
            new FileInputStream(fileName), charset)); 

    String line; 
    while ((line = reader.readLine()) != null) { 
        line = line.trim();
        if( line.length() == 0 ) continue;
        int idx = line.indexOf("\t");
        words.add( line.substring(0, idx ));
        meanings.add( line.substring(idx+1));
    } 
    reader.close();
}

0

उदाहरण के लिए एक और लैटिन भाषा के रूप में सिरिलिक आप इस तरह से कुछ का उपयोग कर सकते हैं:

FileReader fr = new FileReader("src/text.txt", StandardCharsets.UTF_8);

और सुनिश्चित करें कि आपकी .txtफ़ाइल UTF-8(लेकिन डिफ़ॉल्ट नहीं ANSI) प्रारूप के साथ सहेजी गई है । चीयर्स!

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.