package com.java.io;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel; public class GetChannel {
private static final int BSIZE = 1024; @SuppressWarnings("resource")
public static void main(String[] args) throws Exception {
// 获取通道,该通道允许写操作
FileChannel fc = new FileOutputStream("data.txt").getChannel();
// 将字节数组包装到缓冲区中
fc.write(ByteBuffer.wrap("Some text ".getBytes()));
// 关闭通道
fc.close(); // 随机读写文件流创建的管道
fc = new RandomAccessFile("data.txt", "rw").getChannel();
// fc.position()计算从文件的开始到当前位置之间的字节数
// 设置此通道的文件位置,fc.size()此通道的文件的当前大小,该条语句执行后,通道位置处于文件的末尾
fc.position(fc.size()); // Move to the end
fc.write(ByteBuffer.wrap("Some more".getBytes()));
fc.close(); // Read the file:
fc = new FileInputStream("data.txt").getChannel();
ByteBuffer buff = ByteBuffer.allocate(BSIZE);
// 将文件内容读到指定的缓冲区中
fc.read(buff);
//buffer.flip();一定得有,如果没有,就是从文件最后开始读取的,当然读出来的都是byte=0时候的字符。
//通过buffer.flip();这个语句,就能把buffer的当前位置更改为buffer缓冲区的第一个位置。
buff.flip();
while(buff.hasRemaining()){
System.out.print((char)buff.get());
}
}
}
对于只读访问,我们必须显式地使用静态的allocate()方法来分配ByteBuffer。 nio的目标就是快速移动大量数据,因此ByteBuffer的大小就显得尤为重要一一实际上,这里使用的lK可能比我们通常要使用的小一点(必须通过实际运行应用程序来找到最佳尺寸).
 
一旦调用read()来告知FileChannel向ByteBuffer存储字节,就必须调用缓冲器上的flip(). 让
它做好让别人读取字节的准备(是的,这似乎有一点拙劣,但是请记住,它是很拙劣的,但却
适用于在取最大速度) 如果我们打算使用缓冲器执行进一步的read()操作,我们也必须得调用
clear()来为每个read()做好准备.这在下面这个简单文件复制程序中可以看到:
 
package com.java.io;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel; public class ChannelCopy {
private static final int BSIZE = 1024;
public static void main(String[] args) throws Exception {
if(args.length != 2) {
System.out.println("arguments: sourcefile destfile");
System.exit(1);
}
FileChannel in = new FileInputStream(args[0]).getChannel(),
out = new FileOutputStream(args[1]).getChannel();
ByteBuffer buffer = ByteBuffer.allocate(BSIZE);
while(in.read(buffer) != -1) {
buffer.flip(); // Prepare for writing
out.write(buffer);
buffer.clear(); // Prepare for reading
}
}
}
可以看到,打开~个FileChannel以用于读,而打开另一个以用于写。ByteBuffer被分配了
空间,当FileChannel.read()返回- 1时(一个分界符,毋庸置疑,色源于Unix和C) .表示我们已
经到达了输入的末尾。每次read()操作之后,就会将数据输入到缓冲器中. flip()则是准备缓冲器
以便它的信息可以由write()提取. write()操作之后,信息仍在缓冲器中,接着clear()操作则对所
有的内部指针重新安排,以便缓冲器在另一个read()操作期间能够做好接受数据的准备。
 
然而,上面那个程序并不是处理此类操作的理想方式.特殊方法transferTo()和transferFrom()则允许我们将一个通道和另一个通道直接相连:
package com.java.io;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel; public class TransferTo {
public static void main(String[] args) throws Exception {
if(args.length != 2) {
System.out.println("arguments: sourcefile destfile");
System.exit(1);
}
FileChannel in = new FileInputStream(args[0]).getChannel(),
out = new FileOutputStream(args[1]).getChannel(); in.transferTo(0, in.size(), out);
// Or:
// out.transferFrom(in, 0, in.size());
}
}
1 转换数据          
回过头看GetChannel.java这个程序就会发现,为了输出文件中的信息,我们必须每次只读
取一个字节的数据,然后将每个byte类型强制转换成char类型。这种方法似乎有点原始-一如果
我们查看一下java.nio.CharBuffer这个类,将会发现它有一个toString()方法是这样定义的: "返
回一个包含缓冲器中所有字符的字符串。"既然ByteBuffer可以看作是具有asCharBuffer()方法
的CharBuffer ,那么为什么不用它呢?正如下面的输出语句中第一行所见,这种方法并不能解
决问题:
package com.java.io;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset; public class BufferToText {
private static final int BSIZE = 1024; @SuppressWarnings("resource")
public static void main(String[] args) throws Exception {
FileChannel fc = new FileOutputStream("data2.txt").getChannel();
fc.write(ByteBuffer.wrap("Some text".getBytes()));
fc.close();
fc = new FileInputStream("data2.txt").getChannel();
ByteBuffer buff = ByteBuffer.allocate(BSIZE);
fc.read(buff);
buff.flip();
// Doesn't work:
System.out.println(buff.asCharBuffer()); // Decode using this system's default Charset:
buff.rewind();
String encoding = System.getProperty("file.encoding");
System.out.println("Decoded using " + encoding + ": " + Charset.forName(encoding).decode(buff)); // Or, we could encode with something that will print:
fc = new FileOutputStream("data2.txt").getChannel();
fc.write(ByteBuffer.wrap("Some text".getBytes("UTF-16BE")));
fc.close();
// Now try reading again:
fc = new FileInputStream("data2.txt").getChannel();
buff.clear();
fc.read(buff);
buff.flip();
System.out.println(buff.asCharBuffer()); // Use a CharBuffer to write through:
fc = new FileOutputStream("data2.txt").getChannel();
buff = ByteBuffer.allocate(24); // More than needed
buff.asCharBuffer().put("Some text");
fc.write(buff);
fc.close(); // Read and display:
fc = new FileInputStream("data2.txt").getChannel();
buff.clear();
fc.read(buff);
buff.flip();
System.out.println(buff.asCharBuffer());
}
}
缓冲器容纳的是普通的字节,为了把它们转换成字符,我们要么在输入它们的时候对其进
行编码(这样,它们输出时才具有意义) .要么在将其从缓冲器输出时对它们进行解码。可以使
用java.nio.charset.Charset类实现这些功能,该类提供了把数据编码成多种不同类型的字符集的
工具
 
 

---------------

ThinkJava-新IO的更多相关文章

  1. java 21 - 15 新IO流 NIO

    1:JDK4  新IO要了解的类 Buffer(缓冲),Channer(通道) 2:JDK7  要了解的新IO类 Path:与平台无关的路径. Paths:包含了返回Path的静态方法. public ...

  2. Java 新IO

       NIO提供全新的底层I/O模型.与最初的java.io包中面向流(stream-oriented)概念不同,NIO采用了面向块的概念(block-oriented).在尽可能的情况下,I/O的操 ...

  3. JAVA(六)数据库/网络编程/新IO

    成鹏致远 | lcw.cnblog.com |2014-02-05 数据库 1.JDBC概述 JDBC(Java Database Connectivity,Java数据库连接)提供了一种与平台无关的 ...

  4. Java -- 新IO -- 目录

    20.1 Java 新IO简介 20.2 缓冲区与Buffer 例:演示缓冲区的操作流程 Class : IntBufferDemo01 20.2.2 深入缓冲区操作 20.2.3 创建子缓冲区 20 ...

  5. Pipelines - .NET中的新IO API指引(三) 边看边记

    Pipelines - .NET中的新IO API指引 作者 marcgravell  原文 此系列前两篇网上已有的译文 Pipelines - .NET中的新IO API指引(一) Pipeline ...

  6. Java 8特性尝鲜:新新IO

    Java 8特性尝鲜:新新IO 在这个专题前面的文章中,我们已经看到,使用Java8的lambda表达式对现有的JDK1.2 I/O库的提升,主要是可以使用lambda表达式来构造java.io.Fi ...

  7. Pipelines - .NET中的新IO API指引(一)

    https://zhuanlan.zhihu.com/p/39223648 原文:Pipelines - a guided tour of the new IO API in .NET, part 1 ...

  8. Java——新IO 通道

    import java.io.File; import java.io.FileOutputStream; import java.nio.ByteBuffer; import java.nio.ch ...

  9. 新IO建立的聊天程序

    服务端: package com.net.scday3; import java.io.IOException; import java.net.InetSocketAddress; import j ...

  10. java 1.7 新io 实践 NIO2

    Files 类使用 package com.xinyu.test; import java.io.IOException; import java.nio.ByteBuffer; import jav ...

随机推荐

  1. 我的第一个Windows服务

    代码: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; ...

  2. [问题解决]不使用PWM调速系统,彻底解决一个L298N带动两个电机却转速不同的问题

    问题描述:由单片机的VCC引脚供电,使用L298N控制两个电机,发现左右两个轮子的转速老是不一样,更多的情况是左轮转速高(左轮电机接OUT1和OUT2),右轮转速低(右轮电机接OUT3和OUT4)甚至 ...

  3. js的函数作用域

    1.js作用域 //在函数内部声明的变量,如果不加var,则自动变成window的成员//预处理:扫描代码,看到var或者函数就生效./*function f(){a = 8;//var a = 8; ...

  4. Hadoop-1.0.4集群搭建笔记

    这篇文章介绍的是简单的配置Hadoop集群的方法,适合实验和小型项目用,正式运行的集群需要用更正规的方法和更详细的参数配置,不适合使用这篇文章. 相关随笔: 用python + hadoop stre ...

  5. install diagnostic_updater

    sudo apt-get install ros-kinetic-diagnostic-updater

  6. MVP框架模式

    一.基本概念 MVP是Model-View-Presenter的简称,即模型-视图-表现层的缩写.MVP是由MVC模式进化而来的,MVP改进了MVC中的控制器过于臃肿的问题.与MVC一样,MVP将应用 ...

  7. OKR 说明

    转载来源: http://www.jianshu.com/p/ce1141084427 一.什么是OKR? OKR的全称是“Objectives and Key Results”,翻译过来就是“目标和 ...

  8. JSP 日期处理

    JSP 日期处理 使用JSP最重要的优势之一,就是可以使用所有Java API.本章将会详细地讲述Java中的Date类,它在java.util包下,封装了当前日期和时间. Date类有两个构造函数. ...

  9. C# SQLite事务操作方法分析

    本文实例讲述了C# SQLite事务操作方法.分享给大家供大家参考,具体如下: 在 C#中执行Sqlite数据库事务有两种方式:SQL代码和C#代码 1. SQL代码: BEGIN… COMMIT / ...

  10. ubuntu下修改matlab R2016b的快捷键为windows下相同

    选为: windows默认类.