"Java.nio.charset.MalforInputException: ইনপুট দৈর্ঘ্য = 1" এড়াতে সমস্ত অন্তর্ভুক্ত চারসেট?


97

আমি জাভাতে একটি সাধারণ ওয়ার্ডকাউন্ট প্রোগ্রাম তৈরি করছি যা একটি ডিরেক্টরিতে পাঠ্য-ভিত্তিক ফাইলগুলির পাঠ্য।

তবে, আমি ত্রুটিটি পেতে থাকি:

java.nio.charset.MalformedInputException: Input length = 1

কোডের এই লাইন থেকে:

BufferedReader reader = Files.newBufferedReader(file,Charset.forName("UTF-8"));

আমি জানি আমি সম্ভবত এটি পেয়েছি কারণ আমি এমন একটি ব্যবহার করেছি Charsetযাতে এতে টেক্সট ফাইলে কিছু অক্ষর অন্তর্ভুক্ত ছিল না, যার মধ্যে কিছু অন্যান্য ভাষার অক্ষরও অন্তর্ভুক্ত ছিল। তবে আমি এই চরিত্রগুলি অন্তর্ভুক্ত করতে চাই।

আমি পরে এ শিখেছি JavaDocs যে Charset, ঐচ্ছিক এবং শুধুমাত্র ফাইলের আরও কার্যকর পড়ার জন্য ব্যবহার করা হয় তাই আমি কোড পরিবর্তিত হয়েছে:

BufferedReader reader = Files.newBufferedReader(file);

তবে কিছু ফাইল এখনও ফেলে দেয় MalformedInputException। কেন জানি না।

আমি ভাবছিলাম যে এমন কোনও সর্ব-অন্তর্ভুক্ত রয়েছে Charsetযা আমাকে বিভিন্ন ধরণের চরিত্রের সাথে পাঠ্য ফাইলগুলি পড়তে দেবে ?

ধন্যবাদ

উত্তর:


82

আপনি সম্ভবত সমর্থিত এনকোডিংগুলির একটি তালিকা পেতে চান। প্রতিটি ফাইলের জন্য, প্রতিটি এনকোডিং ঘুরেফিরে চেষ্টা করুন, সম্ভবত ইউটিএফ -8 দিয়ে শুরু হবে। প্রতিবার যখন আপনি এটি ধরেন MalformedInputException, পরবর্তী এনকোডিংটি চেষ্টা করুন।


45
আমি চেষ্টা করেছি ISO-8859-1এবং এটি ভাল কাজ করে works আমি মনে করি এটি ইউরোপীয় চরিত্রগুলির জন্য, যা ভাল। যদিও এখনও UTF-16কাজ করে না কেন জানি না।
জোনাথন লাম

4
যদি আপনার নোটপ্যাড ++ থাকে তবে আপনি পাঠ্য ফাইলটি খোলার চেষ্টা করতে পারেন এবং এটি আপনাকে মেনুতে ফাইলের এনকোডিং করতে বলবে। আপনি যদি সর্বদা একই উত্স থেকে ফাইল পান তবে আপনি কোডটি সংক্ষেপে অভিযোজিত করতে পারেন can
জেজিএফএমকে

@ জোনাথানলাম ভাল, কারণ যদি এটির সাথে এনকোড থাকে ISO-8859-1তবে তা হয় না UTF-16 । এই এনকোডিংগুলি সম্পূর্ণ আলাদা। একটি ফাইল উভয় হতে পারে।
দাউদ ইবনে কেরেম

@ ডেউডসেসরেইনস্টেটমোনিকা আমার বিশ্বাস আমি ইউটিএফ -১ 16 এর মতো কাজ করতে পারি নি বলে আমি বিস্মিত হয়েছিলাম, পাশাপাশি আইএসও -৮85৮৯-১ এর মতো ইউরোপীয় চরিত্রের ক্যাপচার সবই করছিল বলে মনে হচ্ছে। তবে তথ্যের জন্য ধন্যবাদ (এমনকি ছয় বছর পরেও): পি
জোনাথন লাম

অবশ্যই ইউটিএফ -16 এর সমস্ত ইউরোপীয় অক্ষর রয়েছে। তবে তারা আইএসও -8859-1 থেকে আলাদাভাবে প্রতিনিধিত্ব করছেন। আইএসও -8859-1 এ, সমস্ত অক্ষর কেবল 8 টি বিট দ্বারা উপস্থাপিত হয়, তাই আপনি 256 সম্ভাব্য অক্ষরের মধ্যে সীমাবদ্ধ। ইউটিএফ -১ In এ, বেশিরভাগ অক্ষরকে 16 বিট দিয়ে উপস্থাপন করা হয় এবং কিছু অক্ষর 32 বিট দিয়ে উপস্থাপন করা হয়। ইউটিএফ -16 এ আরও অনেকগুলি সম্ভাব্য অক্ষর রয়েছে তবে কোনও ইউএসএফ -8859-1 ফাইলের জন্য কেবল একই তথ্য ইউটিএফ -16 এ ব্যবহার করা হবে তার চেয়ে অর্ধেক জায়গার প্রয়োজন হবে।
দাউদ ইবনে কেরেম

41

ফাইল.নিউবফার্ডার রিডার থেকে বাফারডারিডার তৈরি করা হচ্ছে

Files.newBufferedReader(Paths.get("a.txt"), StandardCharsets.UTF_8);

অ্যাপ্লিকেশন চালানোর সময় এটি নিম্নলিখিত ব্যতিক্রম ছুঁড়ে ফেলতে পারে:

java.nio.charset.MalformedInputException: Input length = 1

কিন্তু

new BufferedReader(new InputStreamReader(new FileInputStream("a.txt"),"utf-8"));

ভাল কাজ করে.

ভিন্নটি হ'ল প্রাক্তন চরসেটডেকোডার ডিফল্ট ক্রিয়াটি ব্যবহার করে।

ত্রুটিযুক্ত-ইনপুট এবং অবিস্মরণীয়-চরিত্রের ত্রুটিগুলির জন্য ডিফল্ট ক্রিয়াটি তাদের প্রতিবেদন করা

যদিও পরবর্তীকরা রিপ্লেস ক্রিয়া ব্যবহার করে।

cs.newDecoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE)

29

আইএসও -8859-1 হ'ল একটি সর্ব-অন্তর্ভুক্ত চরসেট, এই অর্থে যে এটি মালফর্মড ইনপুট এক্সেকশন না ছোঁড়ার গ্যারান্টিযুক্ত। সুতরাং আপনার ইনপুটটি এই চরসটে না থাকলেও এটি ডিবাগিংয়ের পক্ষে ভাল। সুতরাং: -

req.setCharacterEncoding("ISO-8859-1");

আমার ইনপুটটিতে আমার কিছু ডাবল-ডান-কোট / ডাবল-বাম-কোট অক্ষর ছিল এবং ইউএস-এএসসিআইআই এবং ইউটিএফ -8 উভয়ই তাদের উপর ম্যালফর্মড ইনপুটটি ছুঁড়েছিল, তবে আইএসও -8859-1 কাজ করেছিল।


7

ত্রুটি বার্তা সহ আমিও এই ব্যতিক্রমটির মুখোমুখি হয়েছি,

java.nio.charset.MalformedInputException: Input length = 1
at java.nio.charset.CoderResult.throwException(Unknown Source)
at sun.nio.cs.StreamEncoder.implWrite(Unknown Source)
at sun.nio.cs.StreamEncoder.write(Unknown Source)
at java.io.OutputStreamWriter.write(Unknown Source)
at java.io.BufferedWriter.flushBuffer(Unknown Source)
at java.io.BufferedWriter.write(Unknown Source)
at java.io.Writer.write(Unknown Source)

এবং দেখেছি ব্যবহার করার চেষ্টা করার সময় কিছু অদ্ভুত ত্রুটি ঘটে

BufferedWriter writer = Files.newBufferedWriter(Paths.get(filePath));

একটি ক্লাসে জেনেরিক টাইপ থেকে স্ট্রিং "ওরেজগ 54" রচনা লিখতে।

//key is of generic type <Key extends Comparable<Key>>
writer.write(item.getKey() + "\t" + item.getValue() + "\n");

এই স্ট্রিংটি নিম্নলিখিত কোড পয়েন্টগুলির সাথে অক্ষর সহ 9 টি দৈর্ঘ্যের হয়:

111 114 97 122 103 9 53 52 10

তবে, ক্লাসে বাফার্ডলিটারের সাথে প্রতিস্থাপন করা থাকলে:

FileOutputStream outputStream = new FileOutputStream(filePath);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));

এটি ব্যতিক্রম ছাড়া সফলভাবে এই স্ট্রিংটি লিখতে পারে। এছাড়াও, আমি যদি একই স্ট্রিংগুলি অক্ষরগুলি থেকে তৈরি করে লিখি তবে এটি ঠিক আছে।

String string = new String(new char[] {111, 114, 97, 122, 103, 9, 53, 52, 10});
BufferedWriter writer = Files.newBufferedWriter(Paths.get("a.txt"));
writer.write(string);
writer.close();

পূর্বে আমি কোনও স্ট্রিং লিখতে প্রথম বাফারড্রাইটার ব্যবহার করার সময় কোনও ব্যতিক্রম কখনও পাইনি। এটি একটি অদ্ভুত বাগ যা জাভা.এনইও.ফাইল থেকে তৈরি বাফারড্রাইটারের সাথে ঘটে।


4
এটি কিছুটা অফ-টপিক, কারণ ওপি লেখার চেয়ে পড়ার কথা বলছিল। আমি বাফারড্রাইটার.উইরাইট (ইনট) এর কারণে একই ধরণের সমস্যা পেয়েছি - যা সেই আইটি কে একটি চরিত্র হিসাবে বিবেচনা করে এবং সরাসরি স্ট্রিমে লেখেন। কর্মক্ষেত্রটি হ'ল ম্যানুয়ালি এটিকে স্ট্রিংয়ে রূপান্তর করা এবং তারপরে লিখুন।
malaverdiere

এটি একটি দুঃখের সাথে ভোটাভুটি দেওয়া উত্তর, সত্যিই দুর্দান্ত কাজ টম। আমি ভাবছি এটি জাভা পরবর্তী সংস্করণগুলিতে সমাধান করা হয়েছে কিনা।
রাইফোফ্লাভিন


4

এটি চেষ্টা করুন .. আমার একই সমস্যা ছিল, নীচে বাস্তবায়ন আমার পক্ষে কাজ করে

Reader reader = Files.newBufferedReader(Paths.get(<yourfilewithpath>), StandardCharsets.ISO_8859_1);

তারপরে আপনি যেখানে চান রিডার ব্যবহার করুন।

পূর্বে:

CsvToBean<anyPojo> csvToBean = null;
    try {
        Reader reader = Files.newBufferedReader(Paths.get(csvFilePath), 
                        StandardCharsets.ISO_8859_1);
        csvToBean = new CsvToBeanBuilder(reader)
                .withType(anyPojo.class)
                .withIgnoreLeadingWhiteSpace(true)
                .withSkipLines(1)
                .build();

    } catch (IOException e) {
        e.printStackTrace();
    }

3

উপলব্ধ অক্ষরগুলির উপর ভিত্তি করে ফলাফলের একটি তালিকা স্ট্যান্ডার্ড আউট করার জন্য আমি নিম্নলিখিতটি লিখেছিলাম। নোট করুন যে আপনি কোন চরিত্রের সমস্যার কারণে সমস্যা সমাধান করছেন সে ক্ষেত্রে 0 ভিত্তিক লাইন নম্বর থেকে কোন লাইন ব্যর্থ হয় তা আপনাকে বলে।

public static void testCharset(String fileName) {
    SortedMap<String, Charset> charsets = Charset.availableCharsets();
    for (String k : charsets.keySet()) {
        int line = 0;
        boolean success = true;
        try (BufferedReader b = Files.newBufferedReader(Paths.get(fileName),charsets.get(k))) {
            while (b.ready()) {
                b.readLine();
                line++;
            }
        } catch (IOException e) {
            success = false;
            System.out.println(k+" failed on line "+line);
        }
        if (success) 
            System.out.println("*************************  Successs "+k);
    }
}

0

ঠিক আছে, সমস্যাটি এইভাবে Files.newBufferedReader(Path path)বাস্তবায়িত হয়:

public static BufferedReader newBufferedReader(Path path) throws IOException {
    return newBufferedReader(path, StandardCharsets.UTF_8);
}

সুতরাং আপনি নিজের কোডটিতে UTF-8বর্ণনামূলক হতে না চাইলে মূলত উল্লেখ করার কোনও অর্থ নেই । আপনি যদি একটি "বিস্তৃত" চার্সেট চেষ্টা করতে চান তবে আপনি চেষ্টা StandardCharsets.UTF_16করতে পারেন তবে যে কোনওভাবেই সম্ভব প্রতিটি চরিত্র পাওয়ার জন্য আপনি 100% নিশ্চিত হতে পারবেন না।


-1

আপনি এই জাতীয় কিছু চেষ্টা করতে পারেন, বা কেবল অনুলিপি করুন এবং নীচে টুকরো টুকরো করতে পারেন।

boolean exception = true;
Charset charset = Charset.defaultCharset(); //Try the default one first.        
int index = 0;

while(exception) {
    try {
        lines = Files.readAllLines(f.toPath(),charset);
          for (String line: lines) {
              line= line.trim();
              if(line.contains(keyword))
                  values.add(line);
              }           
        //No exception, just returns
        exception = false; 
    } catch (IOException e) {
        exception = true;
        //Try the next charset
        if(index<Charset.availableCharsets().values().size())
            charset = (Charset) Charset.availableCharsets().values().toArray()[index];
        index ++;
    }
}

ব্যতিক্রম হ্যান্ডলার সম্ভাব্যভাবে while(exception)লুপটি চিরতরে তৈরি করতে পারে যদি এটি অ্যারেটিতে কোনও কার্যকারী অক্ষর খুঁজে না পায়। অ্যারের সমাপ্তি শেষ হয়ে গেলে এবং কোনও কার্যকারী অক্ষর পাওয়া না গেলে ব্যতিক্রম হ্যান্ডলারটি পুনরায় প্রকাশ করতে হবে। এছাড়াও, এই উত্তর লেখার সময় পর্যন্ত "-2" ভোট ছিল। আমি এটি "-1" এ উন্নীত করেছি। আমি মনে করি এটি নেতিবাচক ভোট পাওয়ার কারণ হ'ল কারণ এখানে পর্যাপ্ত ব্যাখ্যা নেই। কোডটি কী করে তা আমি বুঝতে পেরেছি, অন্য লোকেরা তা নাও করতে পারে। সুতরাং "আপনি এর মতো কিছু চেষ্টা করতে পারেন" এর মতো মন্তব্য কিছু লোকের দ্বারা প্রশংসিত হতে পারে না।
mvanle

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.