FileWriter (Java) का उपयोग करके UTF-8 में एक फ़ाइल लिखें?


82

मेरे पास हालांकि निम्नलिखित कोड हैं, मैं चाहता हूं कि यह यूटीएफ -8 फ़ाइल के रूप में विदेशी पात्रों को संभालने के लिए लिखें। क्या ऐसा करने का एक तरीका है, क्या कोई पैरामीटर होना चाहिए?

मैं वास्तव में इस के साथ आपकी मदद की सराहना करेंगे। धन्यवाद।

try {
  BufferedReader reader = new BufferedReader(new FileReader("C:/Users/Jess/My Documents/actresses.list"));
  writer = new BufferedWriter(new FileWriter("C:/Users/Jess/My Documents/actressesFormatted.csv"));
  while( (line = reader.readLine()) != null) {
    //If the line starts with a tab then we just want to add a movie
    //using the current actor's name.
    if(line.length() == 0)
      continue;
    else if(line.charAt(0) == '\t') {
      readMovieLine2(0, line, surname.toString(), forename.toString());
    } //Else we've reached a new actor
    else {
      readActorName(line);
    }
  }
} catch (IOException e) {
  e.printStackTrace();
}

जवाबों:


77

सुरक्षित एन्कोडिंग निर्माता

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

फ़ाइल I / O के लिए, हमेशा दूसरे तर्क के रूप में उपयोग करने के लिए हमेशा सुनिश्चित करें OutputStreamWriterऔर InputStreamReaderफैंसी एनकोडर तर्क दोनों :

  Charset.forName("UTF-8").newEncoder()

वहाँ भी अन्य कट्टर संभावनाओं रहे हैं, लेकिन तीन सरल संभावनाओं में से कोई भी अपवाद सौंपने के लिए काम करते हैं। ये करते हैं:

 OutputStreamWriter char_output = new OutputStreamWriter(
     new FileOutputStream("some_output.utf8"),
     Charset.forName("UTF-8").newEncoder() 
 );

 InputStreamReader char_input = new InputStreamReader(
     new FileInputStream("some_input.utf8"),
     Charset.forName("UTF-8").newDecoder() 
 );

साथ चलने के लिए

 $ java -Dfile.encoding=utf8 SomeTrulyRemarkablyLongcLassNameGoeShere

समस्या यह है कि यह चरित्र धाराओं के लिए पूर्ण एनकोडर तर्क फॉर्म का उपयोग नहीं करेगा, और इसलिए आप फिर से एन्कोडिंग समस्याओं को याद करेंगे।

लंबा उदाहरण

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

 // this runs a perl script with UTF-8 STD{IN,OUT,ERR} streams
 Process
 slave_process = Runtime.getRuntime().exec("perl -CS script args");

 // fetch his stdin byte stream...
 OutputStream
 __bytes_into_his_stdin  = slave_process.getOutputStream();

 // and make a character stream with exceptions on encoding errors
 OutputStreamWriter
   chars_into_his_stdin  = new OutputStreamWriter(
                             __bytes_into_his_stdin,
         /* DO NOT OMIT! */  Charset.forName("UTF-8").newEncoder()
                         );

 // fetch his stdout byte stream...
 InputStream
 __bytes_from_his_stdout = slave_process.getInputStream();

 // and make a character stream with exceptions on encoding errors
 InputStreamReader
   chars_from_his_stdout = new InputStreamReader(
                             __bytes_from_his_stdout,
         /* DO NOT OMIT! */  Charset.forName("UTF-8").newDecoder()
                         );

// fetch his stderr byte stream...
 InputStream
 __bytes_from_his_stderr = slave_process.getErrorStream();

 // and make a character stream with exceptions on encoding errors
 InputStreamReader
   chars_from_his_stderr = new InputStreamReader(
                             __bytes_from_his_stderr,
         /* DO NOT OMIT! */  Charset.forName("UTF-8").newDecoder()
                         );

अब आप तीन चरित्र धाराओं कि त्रुटियों एन्कोडिंग पर सभी बढ़ाने अपवाद क्रमश: कहा जाता है chars_into_his_stdin, chars_from_his_stdoutऔर chars_from_his_stderr

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

बस मुझे PrintStreamखाने के अपवाद के बारे में शुरू नहीं मिलता है।


1
महान जवाब है, लेकिन मुझे लगता है कि इसके साथ एक मामूली बग है - InputStreamReader char_input = new InputStreamWriterपढ़ना चाहिए: InputStreamReader char_input = new InputStreamReader और InputStreamReaderनिर्माणकर्ता एक लेता है CharsetDecoder, ए नहीं CharsetEncoder
मार्क रोड्स

लेकिन क्या यह एक वास्तविक समस्या है, यूटीएफ -8 का प्रतिनिधित्व करना संभव नहीं है, मुझे लगा कि यह कुछ भी सांकेतिक शब्दों में बदल सकता है।
पॉल टेलर

आप, अपवाद खाने स्ट्रीम के बारे में शिकायत करने की कोशिश करना चाहते हैं CipherInputStreamकि निकाल देता है, BadPaddingExceptionकी, वे एक प्रमाणीकृत सिफर धारा द्वारा बनाई गई हैं, भले ही :(
मार्टेन Bodewes

मुझे आपके कोड में थोड़ी त्रुटि मिली: "Charset.forName (" UTF-8 ")।" InputStreamReader "के लिए newEncoder ()" "Charset.forName (" UTF-8 ")। newDecoder ()" "होना चाहिए। तो "एनकोडर" के बजाय "डिकोडर"। लेकिन वैसे भी, इस अच्छे जवाब और +1 के लिए धन्यवाद। :)
कोडप्लेब

2
(संपूर्ण जावा आईओ प्रणाली हमेशा गड़बड़ी रही है। पूरी तरह से फिर से काम करना चाहिए जैसे कि
जॉडा

56

खाई FileWriterऔर FileReader, जो बिल्कुल बेकार हैं क्योंकि वे आपको एन्कोडिंग निर्दिष्ट करने की अनुमति नहीं देते हैं। इसके बजाय, उपयोग करें

new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)

तथा

new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);


12
यदि आप बहुत क्रियात्मक Charset.forName("UTF-8").newDecoder()तर्क (या कुछ कट्टर निर्माण) का उपयोग नहीं करते हैं "UTF-8", तो आपको एन्कोडिंग त्रुटियों के बारे में ठीक से सूचित नहीं किया जाएगा (पढ़ें: अपवादों को दबा दिया जाएगा, और यह रहस्यमय रूप से एन्कोडिंग त्रुटियों को छिपा देगा)।
15

3
new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8 )
अब्दुल

46

आपको OutputStreamWriterअपने लिए लेखक पैरामीटर के रूप में कक्षा का उपयोग करने की आवश्यकता है BufferedWriter। यह एन्कोडिंग स्वीकार करता है। इसके लिए javadocs की समीक्षा करें ।

कुछ इस तरह:

BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
    new FileOutputStream("jedis.txt"), "UTF-8"
));

या आप सिस्टम प्रॉपर्टी के साथ वर्तमान सिस्टम एन्कोडिंग file.encodingको UTF-8 में सेट कर सकते हैं ।

java -Dfile.encoding=UTF-8 com.jediacademy.Runner arg1 arg2 ...

आप इसे रनटाइम पर एक सिस्टम प्रॉपर्टी के रूप में भी सेट कर सकते हैं System.setProperty(...)यदि आपको केवल इस विशिष्ट फ़ाइल के लिए इसकी आवश्यकता है, लेकिन इस तरह के मामले में मुझे लगता है कि मैं पसंद करूंगा OutputStreamWriter

सिस्टम गुण सेट करके आप उपयोग कर सकते हैं FileWriterऔर अपेक्षा कर सकते हैं कि यह आपकी फ़ाइलों के लिए डिफ़ॉल्ट एन्कोडिंग के रूप में UTF-8 का उपयोग करेगा। इस मामले में उन सभी फाइलों के लिए जो आप पढ़ते हैं और लिखते हैं।

संपादित करें

  • एपीआई 19 से शुरू होकर, आप स्ट्रिंग "यूटीएफ -8" को बदल सकते हैं StandardCharsets.UTF_8

  • के रूप में द्वारा नीचे टिप्पणी में सुझाव दिया tchrist , आप एन्कोडिंग आपकी फ़ाइल में त्रुटियों आप का उपयोग करने के लिए मजबूर किया जाएगा पता लगाने के लिए चाहते हैं, तो OutputStreamWriterदृष्टिकोण और निर्माता है कि एक चारसेट एनकोडर प्राप्त करता है का उपयोग करें।

    कुछ हद तक पसंद है

    CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
    encoder.onMalformedInput(CodingErrorAction.REPORT);
    encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
    BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("jedis.txt"),encoder));
    

    आप क्रियाओं के बीच चयन कर सकते हैं IGNORE | REPLACE | REPORT

साथ ही, इस सवाल का जवाब यहां पहले ही दिया जा चुका था ।


वह पर्याप्त नहीं है। आपको एक भी चाहिए InputStreamReader(InputStream in, CharsetDecoder dec), जैसे कि अंतिम तर्क Charset.forName("UTF-8").newDecoder()
tchrist

1
यदि आप ऐसा करते हैं तो इनपुट एन्कोडिंग त्रुटियों को चुपचाप हटा दिया जाएगा।
tchrist

एनकोडर की कोई आवश्यकता नहीं है। कंस्ट्रक्टर इनपुट, आउटपुट दोनों वर्गों में एक स्ट्रिंग, एक सेटसेट या एक एनकोडर को स्वीकार करता है। यकीन नहीं होता कि आप अपनी टिप्पणी से क्या मतलब रखते हैं। क्या आप कृपया विस्तार से बता सकते हैं?
एडविन डेलोरोज़ो

3
@edalorzo आप चार अलग-अलग परीक्षण तो {In,Out}putStream{Reader,Writer}गलत डेटा पर constructers, आपको लगता है कि उनमें से तीन पता चल जाएगा सभी अपवादों मुखौटा है कि चाहिए एन्कोडिंग त्रुटियों से उत्पन्न होती हैं, और केवल चौथे प्रपत्र सही ढंग से उन्हें आप को भेजता है। यही कारण है कि एक ही है कि शामिल है Charset.forName("UTF-8").newDecoder()। मैं अपने उत्तर में इसे थोड़ा समझाता हूं।
१12

1
हां, यह बहुत बेहतर है। यह ज्यादा : की तुलना में यह उत्पादन के साथ आता है इनपुट एन्कोडिंग त्रुटियों जहां इस ऊपर आता है के साथ अधिक बार (8 बिट उत्पादन एन्कोडिंग हमेशा से रहे हैं कम से कम यह एक UTF प्रपत्र अगर खो-खो हालांकि, अगर आप सिद्धांत में अब भी उन्हें लगा सकता है यूनिकोड में।) आउटपुट पर क्योंकि जावा अनपेक्षित सरोगेट्स को मेमोरी में स्ट्रिंग्स में मौजूद करने की अनुमति देता है (यह है , यह एक बग नहीं है!), लेकिन कोई अनुरूप यूटीएफ- {8,16,32} आउटपुट एनकोडर को आउटपुट पर उन्हें उत्पादन करने की अनुमति नहीं है।
१२:३१


7

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

Files.newBufferedWriter(file.toPath(), StandardCharsets.UTF_8);

आप इसके बारे में अधिक जानकारी JavaDoc में पा सकते हैं:


5

चीनी पाठ के साथ, मैंने चारसेट यूटीएफ -16 का उपयोग करने की कोशिश की और सौभाग्य से यह काम करता है।

आशा है कि यह मदद कर सकता है!

PrintWriter out = new PrintWriter( file, "UTF-16" );

साथ UTF-32 की कोशिश कर सकते
एंसन

1

ठीक है अब 2019 है, और जावा 11 से आपके पास चारसेट के साथ एक कंस्ट्रक्टर है:

FileWriter​(String fileName, Charset charset)

दुर्भाग्य से, हम अभी भी बाइट बफर आकार को संशोधित नहीं कर सकते हैं, और यह 8192 पर सेट है। ( https://www.baeldung.com/java-filewriter )


0

एन्कोडिंग प्रकार सेट करने के लिए FileWriter के बजाय OutputStream का उपयोग करें

// file is your File object where you want to write you data 
OutputStream outputStream = new FileOutputStream(file);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, "UTF-8");
outputStreamWriter.write(json); // json is your data 
outputStreamWriter.flush();
outputStreamWriter.close();

-3

मेरी राय में

यदि आप अनुवर्ती UTF-8 लिखना चाहते हैं। आपको एक बाइट सरणी बनाना चाहिए। फिर, आप निम्न जैसे कर सकते हैं: byte[] by=("<?xml version=\"1.0\" encoding=\"utf-8\"?>"+"Your string".getBytes();

फिर, आप प्रत्येक बाइट को आपके द्वारा बनाई गई फ़ाइल में लिख सकते हैं। उदाहरण:

OutputStream f=new FileOutputStream(xmlfile);
    byte[] by=("<?xml version=\"1.0\" encoding=\"utf-8\"?>"+"Your string".getBytes();
    for (int i=0;i<by.length;i++){
    byte b=by[i];
    f.write(b);

    }
    f.close();

ढेर अतिप्रवाह में आपका स्वागत है! हालांकि यह कोड स्निपेट प्रश्न को हल कर सकता है, जिसमें स्पष्टीकरण सहित वास्तव में आपकी पोस्ट की गुणवत्ता में सुधार करने में मदद करता है। याद रखें कि आप भविष्य में पाठकों के लिए प्रश्न का उत्तर दे रहे हैं, और वे लोग आपके कोड सुझाव के कारणों को नहीं जान सकते हैं। कृपया अपने कोड को व्याख्यात्मक टिप्पणियों के साथ भीड़ देने की कोशिश न करें, इससे कोड और स्पष्टीकरण दोनों की पठनीयता कम हो जाती है!
इशीया मीडोज
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.