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. POJ 3259 Wormholes(最短路&spfa正权回路)题解

    题意:给你m条路花费时间(双向正权路径),w个虫洞返回时间(单向负权路径),问你他能不能走一圈回到原点之后,时间倒流. 思路:题意有点难看懂,我们建完边之后找一下是否存在负权回路,存在则能,反之不能. ...

  2. [调参]CV炼丹技巧/经验

    转自:https://www.zhihu.com/question/25097993 我和@杨军类似, 也是半路出家. 现在的工作内容主要就是使用CNN做CV任务. 干调参这种活也有两年时间了. 我的 ...

  3. python 获取5天前的日期

    from datetime import date, timedelta dt = date.today() - timedelta() print('Current Date :',date.tod ...

  4. ✅javascript 语法:附加子节点

    received: function(data) { $("#notifications").prepend(data.html); } 如何用原生js写出jquery的功能: 先 ...

  5. 使用yum安装pip

    PIP 简介:pip 是一个现代的,通用的 Python 包管理工具.提供了对 Python 包的查找.下载.安装.卸载的功能.功能类似于RedHat里面的yum 使用yum安装pip 因为测试环境搭 ...

  6. epoint:TreeView

    Epoint.Web.UI.WebControls2X.EpointTreeNode 思路:就是使用递归 RootNodeText 根节点名称RootNodeUrl 根节点路径ShowRootNode ...

  7. C++设计模式之桥接模式

    [DP]书上定义:将抽象部分与它的实现部分分离,使它们都可以独立地变化.考虑装操作系统,有多种配置的计算机,同样也有多款操作系统.如何运用桥接模式呢?可以将操作系统和计算机分别抽象出来,让它们各自发展 ...

  8. ajax下载,前端js下载(转)

    前面一直做过下载的功能.就是后台将文件流写入response里面,然后就好了.前台会自动弹出下载提示等. 今天打算做一个ajax下载.想当然的结果死活浏览器没反应.我擦. 然后浏览器调试,发现resp ...

  9. C# ,asp.net 获取当前,相对,绝对路径

    一.C#获取当前路径的方法: 1. System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName -获取模块的完整路径. 2. ...

  10. OPENCV Linux安装

    https://docs.opencv.org/master/d7/d9f/tutorial_linux_install.html