BIO & NIO &AIO
遗留问题
AIO 也是面向字节流的,在一次读入缓存的字节流中末尾部分有存在不能转码的字节,如何关联到下次读取结果中。
BIO 读取文件
底层面向的是字节流,
public static String readFileBio(String fileName) throws IOException {
StringBuilder sb = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(new File(fileName)),"UTF-8"))) {
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
}
return sb.toString();
}
BIO写文件
public static void writeBio(String fileName, String content) throws IOException {
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName),Charset.forName("utf-8")))) {
writer.write(content);
}
}
NIO 读取文件内容
注意如何转码,一次读取转码后尾部剩余的字节的回读。
public static String readFileNio(String fileName) throws IOException {
StringBuilder sb = new StringBuilder();
try (FileChannel channel = new FileInputStream(new File(fileName)).getChannel()) {
/**
* 缓冲区大小
* 一般根据内存的页大小设置,此处是为了模拟一次读取的字节流尾部有未能转码的字节问题
*/
int cap = 5;
ByteBuffer buffer = ByteBuffer.allocate(cap);
CharBuffer charBuffer = CharBuffer.allocate(cap);
/**
* 解码
*/
Charset charset = Charset.forName("utf-8");
CharsetDecoder decoder = charset.newDecoder();
int size;
while ((size = channel.read(buffer)) != -1) {
buffer.flip();
decoder.decode(buffer, charBuffer, size < cap);
charBuffer.flip();
sb.append(charBuffer.toString());
//将读取的定位值 减去多读取的信息
int sub = buffer.limit() - buffer.position();
//将读取通道 position 向前移位 sub 长度
channel.position(channel.position() - sub);
//清理俩个缓冲区
buffer.clear();
charBuffer.clear();
}
}
return sb.toString();
}
NIO写文件
public static void writeFileNio(String fileName, String fileContent) throws IOException {
try (FileChannel fileChannel = new FileOutputStream(new File(fileName)).getChannel()) {
fileChannel.write(Charset.forName("utf-8").encode(fileContent));
}
}
AIO 读取文件内容:每次读取作为一个异步任务,等待结果也是阻塞的
public static String readFileAio(String fileName) throws IOException, ExecutionException, InterruptedException {
try (AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths.get(fileName), StandardOpenOption.READ)) {
StringBuilder sb = new StringBuilder();
ByteBuffer buffer = ByteBuffer.allocate(32);
Charset charset = Charset.forName("utf-8");
int pos = 0;
while (pos < channel.size()) {
Future<Integer> read = channel.read(buffer, pos);
while (!read.isDone()) ;
pos += read.get();
buffer.flip();
sb.append(charset.decode(buffer).toString());
buffer.compact();
}
return sb.toString();
}
}
AIO写文件
public static void writeFileAio(String fileName, String fileContent) throws IOException {
File file = new File(fileName);
file.createNewFile();
try (AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths.get(fileName), StandardOpenOption.WRITE)) {
ByteBuffer encode = Charset.forName("utf-8").encode(fileContent);
Future<Integer> write = channel.write(encode, 0);
while (!write.isDone());
}
}