吐槽下 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 。

你可能感兴趣的:(吐槽下 nio)