Java IO学习总结(四)

一、NIO

NIO采用内存映射文件的方式来处理输入输出流,将文件或者文件的一段区域映射到内存中,这样就可以像访问内存一样访问文件,处理速度比传统的输入输出流要快。最主要的两个核心对象是Channel(通道)和Buffer(缓冲)。

1)Buffer

Buffer是一个抽象类,最主要的实现类是ByteBuffer,其他基本数据类型都有对应的buffer类。常用ByteBuffer和CharBuffer;

创建一个Buffer对象,通过static XXBuffer allocate(int capacity)方法,capacity代表容量。

Buffer中主要有三个重要的概念,容量(capacity)、界限(limit)和位置(position)

容量:表示缓冲区的最大数据容量,不可以为负值,创建后不可以改变。

界限:表示数据不可以被读出或者写入的缓冲区索引位置。

位置:表示下一个可以被读出或者写入的缓冲区位置索引,当创建一个buffer对象之后,position为0,从中读取两条数据之后,position则为2,指向buffer中的第三个数据位置。写入时类似,position自动向后移动位置。

Buffer中两个重要方法:flip()和clear();执行flip()方法之后,limit移动到position位置,position置为0,为输出数据做好准备,;执行clear()方法之后,limit移动到capacity位置,position位置置为0,为写入数据做好准备。

Buffer常用操作示例代码:

public class BufferTest {
    public static void main(String[] args) {
        // 创建Buffer
        CharBuffer buff = CharBuffer.allocate(10);

        // 初始化时:position位置为0,limit位置等于capacity
        System.out.println("缓冲区容量:" + buff.capacity());
        System.out.println("初始化position位置:" + buff.position());
        System.out.println("初始化limit位置:" + buff.limit());

        // 向缓冲区中放入三条数据
        buff.put(‘A‘);
        buff.put(‘B‘);
        buff.put(‘C‘);
        // 此时position位置为3,limit位置等于capacity
        System.out.println("装载数据时position位置:" + buff.position());
        System.out.println("装载数据时limit位置:" + buff.limit());

        // 装载数据结束
        buff.flip();
        // 查看此时position位置为0,limit位置为3
        System.out.println("装载数据完成position位置:" + buff.position());
        System.out.println("装载数据完成limit位置:" + buff.limit());

        // 取出数据,只有使用buff.get()方法时,position自动向后移动位置,使用buff.get(X)position位置不变。
        System.out.println("取出第一个数据" + buff.get());
        System.out.println("取出数据position位置:" + buff.position());

        // 取出数据完成
        buff.clear();
        // 查看此时position位置为0,limit位置等于capacity
        System.out.println("取出数据完成position位置:" + buff.position());
        System.out.println("取出数据完成limit位置:" + buff.limit());
    }
}

2)Channel

Channel类似于传统的流对象,可以直接将指定文件的部分或者全部映射成Buffer,程序不能直接访问Channel,必须通过Buffer交互;所有的Channel都不能通过构造器来直接创建,而是通过传统的节点InputStream、OutStream的getChannel()的方法返回对于的Channel。

Channel有三个主要的方法,map()、read()和write(),map()方法用于将Channel中数据映射成ByteBuffer.

示例代码

public class ChannelTest {
    public static void main(String[] args) {
        try {
            // 创建文件
            File file = new File("d:\\test.txt");

            // 创建输入和输出Channel
            FileChannel fic = new FileInputStream(file).getChannel();
            FileChannel foc = new FileOutputStream("d:\\channel.txt").getChannel();

            // 将文件内容全部映射为ByteBuffer
            MappedByteBuffer buffer = fic.map(MapMode.READ_ONLY, 0, file.length());
            // 将buffer中数据之间输出到FileChannel中
            foc.write(buffer);
            // 初始化缓冲区
            buffer.clear();

            // 创建解码器用于buffer转换
            Charset charset = Charset.forName("GBK");
            CharsetDecoder cd = charset.newDecoder();

            // 将byteBuffer转换为charBuffer用于数据输出展示
            CharBuffer charbuff = cd.decode(buffer);
            System.out.println("数据为:" + charbuff);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

另外一种读取方式

public class ChannelTest1 {
    public static void main(String[] args) {
        try {
            File file = new File("d:\\test.txt");
            FileChannel fci = new FileInputStream(file).getChannel();

            // 定义buffer
            ByteBuffer buff = ByteBuffer.allocate(256);

            while(fci.read(buff) != -1){
                // 锁定缓存区域,防止读取null
                buff.flip();
                // 创建解码器转换为charbuffer输出
                Charset charset = Charset.forName("GBK");
                CharsetDecoder decode = charset.newDecoder();
                System.out.println(decode.decode(buff));

                // 数据读取完之后,初始化缓冲区
                buff.clear();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
时间: 2024-12-28 05:37:26

Java IO学习总结(四)的相关文章

Java IO学习笔记:概念与原理

Java IO学习笔记:概念与原理 一.概念 Java中对文件的操作是以流的方式进行的.流是Java内存中的一组有序数据序列.Java将数据从源(文件.内存.键盘.网络)读入到内存 中,形成了流,然后将这些流还可以写到另外的目的地(文件.内存.控制台.网络),之所以称为流,是因为这个数据序列在不同时刻所操作的是源的不同部分. 二.分类 流的分类,Java的流分类比较丰富,刚接触的人看了后会感觉很晕.流分类的方式很多: 1.按照输入的方向分,输入流和输出流,输入输出的参照对象是Java程序. 2.

Java IO学习笔记(四)打印流

1.只有输出流才有打印流:PrintWriter和PrintStream分别针对字符和字节,提供了重载的print,Println方法用于多种数据类型的输出.PrintWriter和PrintStream操作不会抛出异常,数据没打印出来也不会抛异常. 2.System.out.print(Object object)调用的是Object实体类的toString()方法. 3.PrintWriter和PrintStream有自动的flush功能,不需要手动调用flush方法.*这里必须强调一点:P

Java IO学习笔记(五)对象流

1.Object流:直接将Object写入或读出. 2.序列化:将Object直接转化成字节流写到硬盘或网络上. 3.如果想把一个对象转化成字节流,该对象的实体类必须得实现Serializable接口,Serializable接口是标记性接口,它并没有任何方法,只是用于标识该类可以被序列化. 4.transient关键字,用于修饰成员变量,表示该成员变量是透明的,与Serializable接口同用,表示序列化的时候不考虑该成员变量.序列化时存的是该成员变量数据类型的默认值. 5.External

Java IO学习笔记(三)转换流、数据流、字节数组流

转换流 1.转换流:将字节流转换成字符流,转换之后就可以一个字符一个字符的往程序写内容了,并且可以调用字符节点流的write(String s)方法,还可以在外面套用BufferedReader()和BufferedWriter,并使用它们的readLine 和 newLine方法. 2.有两种转换流:InputStreamReader.OutputStreamWriter 练习小程序1: package test.io.transfer; import java.io.FileOutputSt

Java IO学习总结

Java IO流学习总结 Io流的内容比较多 ,大致可以分为字节流和字符流,其中为了提高效率又用到了缓冲区. Java流操作有关的类或接口: 流的概念和作用 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作. IO流的分类 根据处理数据类型的不同分为:字符流和字节流 根据数据流向不同分为:输入流和输出流 字符流和字节流 字符流的由来: 因为数据编码的不同,而有了对字符进

Java IO 学习总结 学习手册总结

Java IO 是一套Java用来读写数据(输入和输出)的API.大部分程序都要处理一些输入,并由输入产生一些输出.Java为此提供了java.io包. 代码 github地址:https://github.com/loveincode/StudyTest/tree/master/src/IO Java.io 包的范围 java.io 包并没有涵盖所有输入输出类型.例如,并不包含GUI或者网页上的输入输出,这些输入和输出在其它地方都涉及,比如Swing工程中的JFC (Java Foundati

java io学习之File类

1.先看下四个静态变量 static String pathSeparator The system-dependent path-separator character, represented as a string for convenience. static char pathSeparatorChar The system-dependent path-separator character. static String separator The system-dependent

Java IO学习笔记:File类

File类 在整个IO包了,唯一表示与文件本身有关的类就是File类.使用File类可以进行1创建或删除文件等常用操作.要想使用File类.则首先要观察File类的构造方法,此类的      常用构造方法如下所示:public File(String pathname) 实例化File类的时候,必须设置好路径 No. 方法或常量 类型 描述 1 public static final String pathSeparator 常量 表示路径的分隔符(windows是“;”) 2 public s

Java IO学习笔记(一)

一.概念 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.在两设备间的传输的数据称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,以进行数据操作. 二.流分类 数据类型:字符流和字节流 流方向:输入流和输出流 字节流和字符流区别: 读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节. 处理对象不同:字节流能处理所有类型的数据(如图片.rmvb等),字符流只能处理字符类型的数据. 处理纯文本数据,优先使用字符流,此

java io 学习

1,io 体系 在整个Java.io包中最重要的就是5个类和一个接口.5个类指的是File.OutputStream.InputStream.Writer.Reader:一个接口指的是Serializable.掌握了这些IO的核心操作那么对于Java中的IO体系也就有了一个初步的认识了. Java.io包中定义了多个流类型类实现输入输出的功能,从不同的角度可以分为: ~按照数据流方向的不同可以分为输入流和输出流. ~按照按照数据处理单位的不同可以分为字节流和字符流. 如下几张图可以直观的描述io