ThinkJava-新IO

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类实现这些功能,该类提供了把数据编码成多种不同类型的字符集的

工具

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

时间: 2024-08-10 06:52:52

ThinkJava-新IO的相关文章

java 新IO

传统的IO Java中的InputStream.OutputStream.Reader.Writer这样的面向流的输入输出系统被视为传统的IO.传统的IO是阻塞式的输入输出,并且是通过字节的移动来处理的,即传统的IO一次只能处理一个字节,效率不高. 新IO 新IO和传统的IO有相同的目的,都是用于进行输入输出功能.但是新IO采用内存映射文件的方式来处理输入输出,新IO将文件或文件的一段区域映射到内存中,这样就可以像访问内存一样访问文件了,这种方式要比传统的IO快得多. Java中新IO相关的包如

Java新IO

Java从1.4开始引进了对于输入输出的改进,相关类位于java.nio包中.新IO主要有以下几个特性: (1)字符集编码器和解码器 (2)非阻塞的IO (3)内存映射文件 1. 字符集编码器和解码器 Charset类表示不同的字符集,可以使用Charset.forName方法获得指定名称的字符集对象,与Charset相关的类在java.nio.charset包中. (1)编码 将Unicode编码的字符串编码成指定编码的字节序列 Charset cset = Charset.forName("

java 21 - 15 新IO流 NIO

1:JDK4  新IO要了解的类 Buffer(缓冲),Channer(通道) 2:JDK7  要了解的新IO类 Path:与平台无关的路径. Paths:包含了返回Path的静态方法. public static Path get(URI uri):根据给定的URI来确定文件路径. Files:操作文件的工具类.提供了大量的方法, 简单了解如下方法 public static long copy(Path source, OutputStream out) :复制文件 public stati

Java -- Java 新 IO -- Java 新IO简介

20.1 Java 新IO简介 20.2 缓冲区与Buffer 例:演示缓冲区的操作流程 Class : IntBufferDemo01 20.2.2 深入缓冲区操作 20.2.3 创建子缓冲区 20.2.4 创建只读缓冲区 20.2.5 创建直接缓冲区 20.3 通道 20.3.1 FileChannel 例:使用输出通道输出内容 Class : FileChannelDemo01 例:使用通道进行读写操作 Class :FileChannelDemo02 20.3.2 内存映射 例:内存映射

Java 8特性尝鲜:新新IO

在这个专题前面的文章中,我们已经看到,使用Java8的lambda表达式对现有的JDK1.2 I/O库的提升,主要是可以使用lambda表达式来构造java.io.FileFilter的实例. 很多读者都指出了,java.io中的很多API已经被Java7中的java.nio的API所取代了,这里N的意思是New.然而Java8还给我们带来了更多的惊喜,我们把它叫做新新IO(New New IO),虽然jOOQ社区的成员都建议把它叫做企业级IO(Enterprise IO). 言归正传,我们对J

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

https://zhuanlan.zhihu.com/p/39223648 原文:Pipelines - a guided tour of the new IO API in .NET, part 1 作者:marcgravell 大约两年前,我发表了一篇关于.NET中即将到来的体验性新IO API的博文--在那时它被叫做"Channels":在2018年的五月末,它终于在System.IO.Pipelines命名空间中落地,我对这系列API巨感兴趣,而在几个星期前,我被分配去用&qu

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

Pipelines - .NET中的新IO API指引 作者 marcgravell  原文 此系列前两篇网上已有的译文 Pipelines - .NET中的新IO API指引(一) Pipelines - .NET中的新IO API指引(二) 关于System.IO.Pipelines的一篇说明 System.IO.Pipelines: .NET高性能IO 本篇不是翻译,边看边译边记而已. System.IO.Pipelines 是对IO的统一抽象,文件.com口.网络等等,重点在于让调用者注

Java新IO】_通道(Channel)\代码

//****** import java.nio.ByteBuffer ;import java.nio.channels.FileChannel ;import java.io.File ;import java.io.FileOutputStream ;public class FileChannelDemo01{    public static void main(String args[]) throws Exception{        String info[] = {"MLDN

Java新IO】_Selector

DateServer.java import java.net.InetSocketAddress ;import java.net.ServerSocket ;import java.util.Set ;import java.util.Iterator ;import java.util.Date ;import java.nio.channels.ServerSocketChannel ;import java.nio.ByteBuffer ;import java.nio.channel

Java新IO】_文件锁\代码 与字符集

import java.io.File ;import java.io.FileOutputStream ;import java.nio.channels.FileChannel ;import java.nio.channels.FileLock ; public class FileLockDemo{    public static void main(String args[]) throws Exception {        File file = new File("d:&qu