java 输入/输出

1. 简介

java的IO流使用了一种装饰器模式,它将IO流分为底层节点流和上层处理流,其中节点流用于和底层的物理存储节点直接关联,不同的物理存储节点获取节点流的方式可能存在一些差异,但程序可以把不同的物理节点流包装成统一的处理流,从而允许使用统一的方式来读取不同的物理存储节点的资源。

2. File类

File类是java.io包下代表与平台无关的文件和目录。

1)访问文件和目录

public static void main(String[] args) throws IOException{

        File file = new File("D:/Code/Java/LeetCode/src/com/blue");
        /*如果是路径,返回最后一级子目录名*/
        System.out.println(file.getName());
        System.out.println(file.getPath());
        System.out.println(file.getAbsolutePath());
        System.out.println(file.getParent());

        File tmpFile = File.createTempFile("abc", ".txt", file);
        tmpFile.deleteOnExit();//退出后删除

        File newFile = new File(System.currentTimeMillis() + "");
        System.out.println("文件是否存在:" + newFile.exists());

        newFile.createNewFile();

        String[] fileList = file.list();
        for(String fileName : fileList) {
            System.out.println(fileName);
        }

        File[] roots = File.listRoots();
        for(File root : roots) {
            System.out.println(root);
        }
    }

/** blue D:\Code\Java\LeetCode\src\com\blue D:\Code\Java\LeetCode\src\com\blue D:\Code\Java\LeetCode\src\com 文件是否存在:false abc3889250970410031061.txt sky sourcecode sql C:\ D:\ E:\ F:\ H:\ */

2) 文件过滤器

FileNameFilter接口里包含一个accpet(File dir, String name)方法,如果返回true,表示会列出

File file = new File("D:/Code/Java/LeetCode/src/com/blue/sky");
String[] nameList = file.list((dir, name) -> { return name.endsWith(".java") || new File(name).isDirectory(); }); System.out.println("--------------"); for(String name : nameList) { System.out.println(name); }

3. 输入/输出流

java把所有设备里的有序数据抽象成流模型

1)流的概念

  • InputSream/Reader:所有输入流的基类,前者是字节输入流,后者是字符输入流
  • OutputStream/Writer:所有输出流的基类,前者是字节输出流,后者是字符输出流

2)输入流

FileInputStream fis = new FileInputStream("D:\\Code\\Java\\LeetCode\\src\\com\\com\\blue\\classloader\\Test6.java");
byte[] buf = new byte[1024];
int hasRead = 0;
while((hasRead = fis.read(buf)) > 0) {
    System.out.println(new String(buf, 0, hasRead));
}
fis.close();

3) 输出流

try(FileInputStream fis = new FileInputStream("D:\\Code\\Java\\LeetCode\\src\\com\\com\\blue\\classloader\\Test6.java");
    FileOutputStream fos = new FileOutputStream("./1.txt")) {

    byte[] buf = new byte[1024];
    int hasRead = 0;
    while((hasRead = fis.read(buf)) > 0) {
        fos.write(buf, 0, hasRead);
    }
}catch (IOException e) {
    e.printStackTrace();
}

4)输入/输出流体系

java 输入/输出_第1张图片

4. 对象的序列化

对象的序列化:指将一个java对象写入到IO流中
对象的反序列化:指从IO流中恢复java对象

//实现Serializable
1. 当反序列化读取java对象时,并没有看到程序调用构造器,这表明反序列化机制无须通过构造器来初始化java对象
2. 当一个可序列化类有多个父类(直接父类和间接父类),这些父类要么有无参数的构造器,要么也是可序列化的。如果父类是不可序列化的,只有无参数的构造器,则该父类中定义的成员变量值不会序列化到二进制流中
3. 如果多次序列化同一个对象,只有第一序列化时才会把java对象转换成字节序列输出,所以当程序序列化一个可变对象时,一定要注意。
4. 自定义序列化:在实例变量前加transient,java序列化机制就不会序列化该实例变量
5. 另一种序列化机制:实现Externalizable接口 需要重写writeExternal 和readExternal方法
6. 对象的类名、实例变量(包括基本类型、对其他对象的引用和数组)都会被序列化;方法、类变量、transient实例变量都不会被序列化

5. NIO

新IO采用内存映射文件的方式来处理输入/输出,新IO将文件或文件的一段区域映射到内存中。
Channel和Buffer是新IO中的两个核心对象。在新IO系统中所有的数据都需要通过通道传输。
Buffer可以被理解成一个容器,它的本质是一个数组。发送到Channel中的所有对象都必须首先放到Buffer中,而从Chanel中读取的数据也必须先放到Buffer中。

1)Buffer使用

从内部结构看,Buffer就像一个数组,它可以保存多个类型相同的数据。常用的Buffer有ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer和DoubleBuffer。
通过allocate获取对应的XXXBuffer对象
Buffer有三个重要的概念:容量(capacity),界限(limit),位置(position)

  • 缓冲区的容量表示该Buffer的最大数据容量,创建后不能改变。
  • limit表示第一不可以被读或写的缓冲区位置索引。也就是说,limit后的数据既不可以被读,也不可以被写
  • position用于指明下一个可以被读出或者写入的缓存区位置索引

当数据装入完毕后,调用Buffer的flip方法,该方法将limit位置为position所在位置,并将position设为0
当调用clear方法时,它仅仅将position置0,将limit置为capacity,数据不会清空

2)使用Channel

  • ServerSocketChanel,SocketChannel是用于支持TCP网络通信的Channel
  • DatagramChannel是用于支持UDP网络通信的Channel
  • Pipe.SinkChannel 和Pipe.SourceChannel是用于支持线程间通信的Channel
    通过相应流的getChannel方法来获取Channel
    Channel常用的三类方法:map, read和write,其中map方法用于将Channel对应的部分或全部数据映射成ByteBuffer, read和write方法用于从Buffer中读取或者向Buffer写入数据

Java7的NIO2

提供了全面的文件和文件系统的访问支持(Paths, Files)
基于异步Channel的IO

你可能感兴趣的:(java 输入/输出)