Java架构师之路:JavaSe篇---Java I/O


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

重要的设计结构:装饰者模式,适配器模式

FilterOutputStream和FilterInputStream作为装饰者得基类

InputStreamReader可以把InputStream转换为Reader适配器

OutputStreamWriter可以把OutputStream转换为Writer

io

总体架构图

Java架构师之路:JavaSe篇---Java I/O_第1张图片

输入

  • 缓冲输入文件

BufferedReader in = new BufferedReader(new FileReader(fileName));
//	注意  in.readLine()时  记得加换行符,因为该方法会自动删除
  • 内存输入

StringReader in = new StringReader(BufferedInputFile.read(fileName));
//   此时读取应强转(char)in.read();
  • 格式化内存输入

DataInputStream data = new DataInputStream(new ByteArrayInputStream(
				BufferedInputFile.read(fileName).getBytes()))
//  while(in.available() != 0){ sout.((char)in.readBye())}
//	in.available()可以获取可供存取的字符

输出

FileWriter可以向文件写入文件,通常用 BufferedWriter包装来起到缓冲输出的作用

PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file)))

nio

NIO 包含下面几个核心的组件:

  • Channel(通道)

  • Buffer(缓冲区)

    通常来说NIO中的所有IO都是从 Channel(通道) 开始的。

    • 从通道进行数据读取 :创建一个缓冲区,然后请求通道读取数据。
    • 从通道进行数据写入 :创建一个缓冲区,填充数据,并要求通道写入数据。
  • Selector(选择器)

    • 选择器用于使用单个线程处理多个通道。

唯一与通道直接交互的缓冲器:ByteBuffer

I/O类库中有三个类可以产生 FileChannel。但注意以下都是通过操纵字节与nio交互

		
		//第一种:通道FileChannel
		FileChannel fc = new FileOutputStream("DirList.out").getChannel();
		//wrap()可以将已存在的字节数组包装为ByteBuffer
        fc.write(ByteBuffer.wrap("Some text ".getBytes()));
        fc.close();
		
		//第二种
        fc = new RandomAccessFile("DirList.out", "rw").getChannel();
        fc.position(fc.size());
        fc.write(ByteBuffer.wrap("Some text ".getBytes()));
        fc.close();

		//第三种
        //Read the file
        fc = new FileInputStream("DirList.out").getChannel();
		//对于只读访问我们必须显示使用静态方法allocate()来分配ByteBuffer
        ByteBuffer buff = ByteBuffer.allocate(BSIZE);
		//调用read()就必须调用flip(),主要是为了让它做好被人读的准备
        fc.read(buff);
        buff.flip();
        while (buff.hasRemaining()){
            System.out.print((char)buff.get());
        }

Java架构师之路:JavaSe篇---Java I/O_第2张图片

理解Buffer的索引

  • Buffer有三个属性是必须掌握的,分别是:capacity容量、position位置、limit限制。
//位置交换
while(buffer.hasRemaining()) {
    buffer.mark();
    char c1 = buffer.get();
    char c2 = buffer.get();
    buffer.reset();
    buffer.put(c2).put(c1);
}

Java架构师之路:JavaSe篇---Java I/O_第3张图片

  • mark()

Java架构师之路:JavaSe篇---Java I/O_第4张图片

  • 两次buffer.get(),pos指针移动两次,并返回c1,c2

Java架构师之路:JavaSe篇---Java I/O_第5张图片

  • 用put换位置
    Java架构师之路:JavaSe篇---Java I/O_第6张图片
  • 下一次循环mar和pos位置相同
    Java架构师之路:JavaSe篇---Java I/O_第7张图片
  • tips:大文件的修改可以用nio

文件加锁

FileLock fl = fos.getChannel().trylock();

if(fl != null) {
    sout("Locked File");
    TimeUnit.MILLISECONDS.sleep(100);
    fl.release();
    sout("Released lock")
}
fos.close;
//tryLock()非阻塞,也就是其它进程持有,它将直接调用方法返回
//lock()阻塞的,也就是等待
//release()释放锁

可以通过FileLock.isShared()进行锁类型查询(共享或独占)

压缩

对象序列化

Java的对象序列化将那些实现了Serializable接口对象转换成一个字节序列,并能够恢复成原来对象。

实现了轻量级持久性

主要支持两种特性

  1. Java的远程方法调用
  2. Java Beans,对象的序列化也是必须的

实现步骤

  • 创建OutputStream对象,然后将其封装在ObjectOutputStream对象内,调用writeObject()即可对象序列化
  • 同上,还原就是InputStream,ObjectInputStream,readObject()

术语小记

同步与异步

  • 同步: 同步就是发起一个调用后,被调用者未处理完请求之前,调用不返回。
  • 异步: 异步就是发起一个调用后,立刻得到被调用者的回应表示已接收到请求,但是被调用者并没有返回结果,此时我们可以处理其他的请求,被调用者通常依靠事件,回调等机制来通知调用者其返回结果。

阻塞和非阻塞

  • 阻塞: 阻塞就是发起一个请求,调用者一直等待请求结果返回,也就是当前线程会被挂起,无法从事其他任务,只有当条件就绪才能继续。
  • 非阻塞: 非阻塞就是发起一个请求,调用者不用一直等着结果返回,可以先去干其他事情。

推荐阅读:[https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/Java%20IO%E4%B8%8ENIO.md](https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/Java IO与NIO.md)

源码阅读篇

1.适配器(Adatper)模式

定义:将一个类的接口变换城客户端所期待的另一个种接口,从而使原本不匹配而无法一起工作的两个类能够在一起工作
  • 适配模式还有个别名包装模式(Wrapper)
    • Target目标角色
      • 该角色定义把其他类转换为期望接口
    • Adaptee源角色
      • 被转换的对象
    • Adapter适配器角色
      • 把源角色转换为目标角色

Java架构师之路:JavaSe篇---Java I/O_第8张图片

//将System.in转换为BufferedReader需要的Reader类型
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

//InputStreamReader的构造器
public InputStreamReader(InputStream in) {
        super(in);
        try {
            sd = StreamDecoder.forInputStreamReader(in, this, (String)null); 
        } catch (UnsupportedEncodingException e) {
            // The default encoding should always be available
            throw new Error(e);
        }
    }
//BufferedReader的构造器
 public BufferedReader(Reader in) {
        this(in, defaultCharBufferSize);
 }
//转换过程大致如下
InputStream  ===>	InputStreamReader(System.in)  ====>  Reader

所以简单来说就是Adapter需要同时有其它两个角色的特点,并把源角色转化为目标角色。

2.Decorator 模式

定义:动态添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更灵活。

​ 适配模式还有个别名包装模式(Wrapper)

  • Component抽象构建
    • 原始对象接口
  • ConcreteComponent具体构件
    • 原始对象接口实现
  • Decorator装饰角色
    • 属性里面必然有一个private变量指向Component抽象构建

Java架构师之路:JavaSe篇---Java I/O_第9张图片

FilterInputStream

   /**
     * FilterInputStream定义了原始的接口指向
     * 后面的方法都是调用父类的实现
     */
    protected OutputStream out;

    /**举例**/
    //创建一个字节数组输出流
    ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
    //放入dataoutputStraam进行装饰
    DataOutputStream dataOutputStream=new DataOutputStream(outputStream);

你可能感兴趣的:(JAVA)