today, when using Java NIO's channel and buffer for file operation, java.nio.charset.MalformedInputException:Input length = 1 is reported. exceptions, as follows:
Java.nio.charset.MalformedInputException:Input length = 1at java.nio.charset.CoderResult.throwException ( coderresult.java:260) at Java.nio.charset.CharsetDecoder.decode (charsetdecoder.java:781) at Cn.fuxi.nio.ReadFile.main (readfile.java:37)
The specific Java source code is as follows: Readfile.java
public class ReadFile {public static void main (string[] args) {fileinputstream fis;try {fis = new FileInputStream ("A.txt") ; FileChannel channel = Fis.getchannel ();//defines a bytebuffer for repeated reading of the data bytebuffer Bytebuffe = bytebuffer.allocate (64);// Remove 64 bytes each time//put FileChannel data into Bytebuffer while (Channel.read (bytebuffe)! = 1) {//Lock Bytebuffer blank area bytebuffe.flip ();/* Create Charset object */charset Charset = Charset.forname ("GBK");//Create decoder Charsetdecoder Charsetdecoder = Charset.newdecoder ();// Transcode the contents of bytebuffer charbuffer Charbuffer = Charsetdecoder.decode (Bytebuffe);//Charbuffer Charbuffer = Charset.decode ( Bytebuffe); System.out.println (Charbuffer);//Initialize the Bytebuffer to prepare for the next read of the data Bytebuffe.clear ();}} catch (Exception e) {//Todo:handle exceptione.printstacktrace ();}}}
The contents of the A.txt file I want to read are simple, as follows:
This was just test for filechannel be careful to report an exception: Java.nio.charset.MalformedInputException:Input length = 1, see what the hell is the reason for it.
View the Java API's official aboutMalformedinputexception's instructions are as follows:
Checked Exception thrown when an input byte sequence was not a legal for given charset, or a input character sequence is Not a legal sixteen-bit Unicode sequence.
The translation comes from:This checked exception is thrown when the input byte sequence is illegal for a given charset, or if the input character sequence is not a valid 16-bit Unicode sequence.
plainly speaking, there will be java.nio.charset.MalformedInputException anomalies, the reason is "half Chinese problem". Analysis of the above program, is because Charsetdecoder to bytebuffer decoding time, can not guarantee the successful decoding into Chinese characters, perhaps there is "half of the Chinese character" is not sure. It is said that the exception occurs when there is half a character. For example, because in GBK the letter occupies 1byte, the Chinese character occupies 2byte. such as "My ABC Kanji D" This string, intercept 5 bytes, should be "I abc", and intercept 8 bytes, should be "I abc Han", and should not be "I abc Han?" ", where?" "As a half-character, it can be understood as a forward intercept. So it will be reported abnormal. ( Note: To change character encoding GBK to UTF-8, each Chinese length is calculated as 3 characters )
My first solution was to: Bytebuffer Bytebuffe = bytebuffer.allocate (64), this line is changed to bytebuffer Bytebuffe = Bytebuffer.allocate (1024x768); because I want to read the A.txt file is not big, if read 1024 bytes at a time, it is larger than the total size of the A.txt file, so the A.txt file is read at once. Therefore, it will not be reported abnormal. But if the size of the a.txt file I want to read is larger than 1024 bytes, the exception is still likely to burst. So the method is not correct.
My second solution is: Remove the Charsetdecoder.decode () method directly using the Charset.decode () method. The following code is coming:
/* Create Charset object */charset Charset = Charset.forname ("GBK");//Create decoder Charsetdecoder Charsetdecoder = Charset.newdecoder () ;//transcoding the contents of bytebuffer//charbuffer Charbuffer = Charsetdecoder.decode (Bytebuffe);
Switch
/* Create Charset object */charset Charset = Charset.forname ("GBK"); Charbuffer Charbuffer = Charset.decode (Bytebuffe);
But after this change, will also appear the following garbled problem, so also do not advocate.
This was just test for filechannel be careful to report an exception: Java.nio.charset.MalformedInputException:Input length = 1, see what the hell is the reason for it. This was just test for filechannel be careful to report an exception: Java.nio.charset.MalformedInputException:Input length = 1, see the bottom of the sheath cut down the DUI anaconda silly g?
The third solution: each time to determine whether the last byte in the Bytebuffer is legal. If it is illegal, it means that this byte is part of a double-byte character, so that we do not include this byte when decoding, but instead put this byte into the Bytebuffer before the next decoding. In doing so, the system will not throw exceptions such as "Cannot decode correctly".The method to solve the specific code changes, today's mind a little pain, no time to change, the next change to send up again. (Can see http://songjianyong.iteye.com/blog/1399241 looking for ideas)
The fourth method: Use the Filechannel.map () method to map all the file contents to memory at once, but this can cause performance degradation if the file is read too large. The code is as follows:
public class Filechanneltest {public static void main (string[] args) {try {file File=new file ("Abc.txt");//File input stream Fileinpu Tstream create FileChannel to control the input FileChannel inchannel=new fileinputstream (file). Getchannel ();// Create FileChannel with the file output stream FileOutputStream to control the output FileChannel outchannel=new fileoutputstream ("A.txt"). Getchannel ();// Map all the data in FileChannel to Bytebuffermappedbytebuffer buffer=inchannel.map (FileChannel.MapMode.READ_ONLY, 0, File.length ());//directly output the data in buffer outchannel.write (buffer);//Call Buffer's clear () method again to restore the limit, Position position buffer.clear ();//Use GBK character set to create decoder charset charset=charset.forname ("GBK");// Create decoder (Charsetdecoder) object Charsetdecoder decoder=charset.newdecoder ();//Use decoder to convert Bytebuffer to Charbuffercharbuffer Charbuffer=decoder.decode (buffer); System.out.println (Charbuffer);} catch (Exception e) {//Todo:handle exceptione.printstacktrace ();}}}
Hey, busy one night, still no real solution java.nio.charset.MalformedInputException:Input length = 1 abnormal, ashamed. If there is a great God to help me solve, grateful.
==================================================================================================
Ouyangpeng welcome reprint, sharing with people is the source of progress!
Reprint please keep the original address : Http://blog.csdn.net/ouyang_peng
==================================================================================================
My Java Development Learning journey------>java NIO java.nio.charset.MalformedInputException:Input length = 1 exception