吐槽下 nio


    final static int BUFFER_SIZE = 20;  // 为了容易出现错误,把缓存弄小点

    private static void fuc_Nio() {
        FileInputStream fis = null;
        FileChannel fc = null;
        try {
            fis = new FileInputStream("src/nio/ReadFile.java");
            fc = fis.getChannel();
            ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
            CharsetDecoder decoder = Charset.forName("utf-8").newDecoder();
            while (fc.read(buffer) != -1) {
                buffer.flip();
                System.out.print(decoder.decode(buffer));   // 出现异常 MalformedInputException: Input length = 1
                buffer.clear();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            quickClose(fis);
            quickClose(fc);
        }
    }

    private static void quickClose(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (IOException ignored) {
            }
        }
    }


o(︶︿︶)o 唉,解码失败,百度了一下,无果。。。

这段代码修改自 一本叫 疯狂java xx 的书,没看几页,各种错误,让人心灰意冷,果然不应该看国内的书啊。。。。

怎么弄呢,用 PipedInputStream ? 这不行,否则 非阻塞 就费了。。

我很好奇,Writer 是怎么做到的,看了一下源代码,我重新修改了一下,这下子没有错误了。。


    private static void rightWay() {
        FileInputStream fis = null;
        FileChannel fc = null;
        try {
            fis = new FileInputStream("src/nio/ReadFile.java");
            fc = fis.getChannel();
            ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
            CharBuffer out = CharBuffer.allocate(BUFFER_SIZE * 3);     // 为了简单,确保大小足够
            CharsetDecoder decoder = Charset.forName("utf-8").newDecoder();
            while (fc.read(buffer) != -1) {
                buffer.flip();
                out.clear();
                decoder.decode(buffer, out, false);
                out.flip();
                System.out.print(out.toString());
                reset(buffer);         // 把不能解码的部分移动到前面,用于下次使用
            }
            buffer.flip();              // 剩下的不能解码的部分直接输出
            System.out.write(buffer.array(), buffer.position(), buffer.limit() - buffer.position());
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            quickClose(fis);
            quickClose(fc);
        }
    }

    private static void reset(ByteBuffer bf) {
        byte[] bytes = new byte[bf.remaining()];
        int i = 0;
        while (bf.hasRemaining()) {
            bytes[i] = bf.get();
            i++;
        }
        bf.clear();
        for (byte b : bytes) {
            bf.put(b);
        }
    }





============= 完整的代码 ==========

package nio;

/* 弄点切糕 */

// src/nio/ReadFile.java

import java.io.Closeable;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;

public class ReadFile {

    final static int BUFFER_SIZE = 20;  // 为了容易出现错误,把缓存弄小点

    private static void fuc_Nio() {
        FileInputStream fis = null;
        FileChannel fc = null;
        try {
            fis = new FileInputStream("src/nio/ReadFile.java");
            fc = fis.getChannel();
            ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
            CharsetDecoder decoder = Charset.forName("utf-8").newDecoder();
            while (fc.read(buffer) != -1) {
                buffer.flip();
                System.out.print(decoder.decode(buffer));   // 出现异常 MalformedInputException: Input length = 1
                buffer.clear();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            quickClose(fis);
            quickClose(fc);
        }
    }

    private static void rightWay() {
        FileInputStream fis = null;
        FileChannel fc = null;
        try {
            fis = new FileInputStream("src/nio/ReadFile.java");
            fc = fis.getChannel();
            ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
            CharBuffer out = CharBuffer.allocate(BUFFER_SIZE * 3);     // 为了简单,确保大小足够
            CharsetDecoder decoder = Charset.forName("utf-8").newDecoder();
            while (fc.read(buffer) != -1) {
                buffer.flip();
                out.clear();
                decoder.decode(buffer, out, false);
                out.flip();
                System.out.print(out.toString());
                reset(buffer);         // 把不能解码的部分移动到前面,用于下次使用
            }
            buffer.flip();              // 剩下的不能解码的部分直接输出
            System.out.write(buffer.array(), buffer.position(), buffer.limit() - buffer.position());
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            quickClose(fis);
            quickClose(fc);
        }
    }

    private static void reset(ByteBuffer bf) {
        byte[] bytes = new byte[bf.remaining()];
        int i = 0;
        while (bf.hasRemaining()) {
            bytes[i] = bf.get();
            i++;
        }
        bf.clear();
        for (byte b : bytes) {
            bf.put(b);
        }
    }

    private static void quickClose(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (IOException ignored) {
            }
        }
    }

    public static void main(String[] args) {
        rightWay();   // 有效方法,至少我试了可以使用
        fuc_Nio();    // 错误方法
    }
}



顺便弄上一段 复制文件 的源代码(commons-io),不然 nio 白看了
            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);
            input  = fis.getChannel();
            output = fos.getChannel();
            long size = input.size();
            long pos = 0;
            long count = 0;
            while (pos < size) {
                count = size - pos > FILE_COPY_BUFFER_SIZE ? FILE_COPY_BUFFER_SIZE : size - pos;
                pos += output.transferFrom(input, pos, count);
            }



写书的那些白痴,不经过测试的代码就别搞上去。。。

源代码编码是 utf-8,用eclipse的话应该会出现乱码,搞不懂 eclipse 为什么默认编码为 gb2312 。

猜你喜欢

转载自becominx.iteye.com/blog/1750727
NIO