• 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());
                }
          }
    }
    View Code
    对于只读访问,我们必须显式地使用静态的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
                }
           }
    }
    View Code
    可以看到,打开~个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());
          }
    }
    View Code
    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());
        }
    }
    View Code
    缓冲器容纳的是普通的字节,为了把它们转换成字符,我们要么在输入它们的时候对其进
    行编码(这样,它们输出时才具有意义) .要么在将其从缓冲器输出时对它们进行解码。可以使
    用java.nio.charset.Charset类实现这些功能,该类提供了把数据编码成多种不同类型的字符集的
    工具
     
     

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

  • 相关阅读:
    常用Linux命令
    KDevolop使用小技巧
    微软在5/10/2006发布新版的LINQ Preview (May 2006).msi 无为而为
    盼望已久的Office Live Beta 已经发布,大家可以去尝尝鲜 无为而为
    需求工程:TFS MSF模版中UI Flow model的应用 无为而为
    Visual Studio 2005 Team Foundation Server 试用版及中文说明文件下载,中文版可能在2006年5月15日发布 无为而为
    让我们努力从“不可救药的乐观主义者”华尔街知名投资人约翰。多尔那里学点东西(永远放弃尝试改变这个世界) 无为而为
    Visual Studio 2005 开发Office(Word/Excel)项目的若干资源和示例 无为而为
    IT人看《国富论》系列:第一篇之第十章:论工资与利润随劳动与资本用途的不同而不同,分析分析IT界薪水起伏的原因 无为而为
    非正常状态,彻底删除Exchange服务器 无为而为
  • 原文地址:https://www.cnblogs.com/tenWood/p/7471046.html
Copyright © 2020-2023  润新知