1、Java中的I/O分类

I/O分类:

  • 输入流,输出流,或者字节流,字符流

I/O中的四个抽象基类:

  • InputStream,OutputStream:两者属于字节流,前者输入,后者输出。一般后缀名为这两个的都属于字节流家族。
  • Reader,Writer:两者属于字符流,前者输入,后者输出。一般后缀名为这两个的都属于字符流家族。

2、File常用方法

常用方法:

  • mkdir()创建一个文件夹,mkdirs()创建一个文件夹以及它的上级文件夹。
  • createNewFile()创建一个文件。
  • isDirectory()判断文件是否存在以及是否是一个目录,exists()判断文件路径是否存在。
  • delete()删除文件或者目录。
  • 示例代码如下
 package com.spring.test.service;

 import java.io.File;
import java.io.IOException; /**
* @Author: philosopherZB
* @Date: 2019/9/29
*/
public class Test {
public static void main(String[] args){
//File.separator返回本系统的名称分隔符,方便代码跨系统移植,比如windows下文件分隔符是\,而其他系统可能就不是\。
//创建一个文件夹
String path1 = "D:" + File.separator + "Test";
File file1 = new File(path1);
file1.mkdir(); //创建一个文件夹以及他的上级文件夹
String path2 = "D:" + File.separator + "Test" + File.separator + "Temp" + File.separator + "demo";
File file2 = new File(path2);
file2.mkdirs(); //创建一个文件
String path3 = "D:" + File.separator + "Test" + File.separator + "Test.txt";
File file3 = new File(path3);
try {
file3.createNewFile();
} catch (IOException e) {
e.printStackTrace();
} //读取文件夹以及文件
String path4 = "D:" + File.separator + "Test"; //指定读取目录
File file4 = new File(path4);
//判断目录是否存在
if(file4.isDirectory()){
// String[] str = file4.list();
// for(int i=0;i<str.length;i++){
// File f = new File("D:" + File.separator + "Test" + File.separator + str[i]);
// if(f.isDirectory()) {
// System.out.println(str[i] + "是一个目录");
// }else{
// System.out.println(str[i] + "是一个文件");
// f.delete();//删除该文件
// }
// }
//如果需要获取全路径可以使用listFiles,这个方法的返回时File。
File[] files = file4.listFiles();
if(files.length!=0) {
for(File file : files){
if(file.isDirectory()) {
System.out.println(file + "是一个目录");
}else{
System.out.println(file + "是一个文件");
file.delete();//删除该文件
}
}
}
}else{
System.out.println("目录不存在");
}
}
}

3、对文件进行写入,读出

分别使用字符流,字节流写入读出:

  • 字节流使用的是:BufferedOutputStream(写入),BufferedInputStream(读出)
  • 字符流使用的是:BufferedWriter(写入),BufferedReader(读出)
  • 其中字符流是线程安全的(源码中对应的方法加了sychronized),字节流不是线程安全的。
  • 其中使用的try-with-resource是一个Java的语法糖,如果是实现了Closeable接口的类,可以免去自己写finally块进行资源关闭的操作
  • 示例代码如下:
 package com.spring.test.service;

 import java.io.*;

 /**
* @Author: philosopherZB
* @Date: 2019/9/29
*/
public class Test {
public static void main(String[] args){
String path = "D:" + File.separator + "Test" + File.separator + "Test.txt";
String str = "文件测试内容";
//字节流
writeFile(path,str);
System.out.println("字节流:" + readFile(path));
//字符流
writeFileByStr(path,str);
System.out.println("字符流:" + readFileByStr(path));
} //写入字符串到指定文件中----字节流,字节流线程不安全,可以通过synchronized来使其成为一个静态同步方法
public static synchronized void writeFile(String fileName,String content){
//此处使用的是try-with-resource,实现了Closeable接口的类,可以免去自己写finally块进行资源关闭的操作,是一个java的语法糖
try(BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(fileName)))){
byte[] b = content.getBytes();
bos.write(b); //写入
bos.flush(); //刷新缓存,及时将缓存中的数据刷到文件中
}catch (IOException e){
throw new RuntimeException(e.getMessage(), e);
}
} //从指定文件中读取字符串-----字节流,字节流线程不安全,可以通过synchronized来使其成为一个静态同步方法
public static synchronized String readFile(String fileName){
try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(fileName)))){
byte[] b = new byte[256];
int count = 0;
int temp = 0;
//不确定文件内容有多大,循环读取
//读到文件末尾的时候才会返回-1
while((temp = bis.read()) != -1){
b[count++] = (byte) temp;
}
return new String(b);
}catch (IOException e){
throw new RuntimeException(e.getMessage(), e);
}
} //写入字符串到指定文件中----字符流,字符流的write方法是线程安全的
public static void writeFileByStr(String fileName,String content){
try(BufferedWriter bw = new BufferedWriter(new FileWriter(new File(fileName)))){
bw.write(content);
bw.flush();
}catch (IOException e){
throw new RuntimeException(e.getMessage(), e);
}
} //从指定文件中读取字符串-----字符流
public static String readFileByStr(String fileName){
try(BufferedReader br = new BufferedReader(new FileReader(new File(fileName)))){
char[] c = new char[256];
int count = 0;
int temp = 0;
//不确定文件内容有多大,循环读取
//读到文件末尾的时候才会返回-1
while((temp = br.read()) != -1){
c[count++] = (char) temp;
}
return new String(c);
}catch (IOException e){
throw new RuntimeException(e.getMessage(), e);
}
} }

4、BIO,NIO,AIO

BIO(Block IO):

  • 同步阻塞式IO,一般指平常所用的IO类。
  • 一个请求对应一个响应,为了合理的利用资源,可以使用多线程(线程池)。
  • 此IO一般针对并发量较小的场景(<1000)。
  • BIO操作的对象是流(Stream)。
  • 比如:在ATM机上取钱,只能一个一个的取,前面有人的时候,需要等待;取钱的时候,需要本人进行相关取钱操作(取出之后拿到钱才走)。

NIO(NewIO):

  • 同步非阻塞式IO。
  • 利用Channel(通道)通讯,实现了多路复用。
  • 核心组件:Buffer(缓冲区),Channel(通道),Selector(选择器)
  • NIO操作的对象是缓存区(Buffer)。
  • 基本运行流程:当Channel发生新连接、就绪读,就绪写的时候,首先会在Selector上注册相应的事件,生成一个与Channel绑定的selectKey;其次由一个线程轮询selectKey集合,利用操作系统底层的函数select() 或者 epoll(Linux 2.6之前是select、poll,2.6之后是epoll,Windows是iocp)去操作系统查询IO是否就绪,如果就绪则执行相应的事件处理器(通过selectKey找到Channel,然后利用与Channel绑定的buffer进行实际读写)。
  • 比如:在银行大厅取钱,对于前面是否有人等候,只需要隔一段时间去问一下大堂经理是否可以取钱就可以了,不需要一直去排队(这段时间可以做其他事);取钱的时候,需要柜员进行相关操作,同时也需要保证你也在柜员面前(不能离开,不然柜员可能会找不到你,然后钱就没有实际拿到手里了)。

AIO(Asynchronous IO):

  • 异步非阻塞式IO。
  • 其实现是基于事件以及回调机制。
  • AIO与NIO有点相似,不过对于实际读写而言,AIO是交给操作系统底层自己去完成的,完成之后会返回一个IO完成的回调消息。
  • 比如:同样是去银行取钱,不过这次你是让朋友去帮忙取的,你朋友会帮你排队,然后取钱,接着把钱给你,并告诉你已经取好了。

IO阶段:

  • IO中对于读写一般分为两个阶段:就绪读写(准备数据)以及实际读写(真正读写数据)。
  • 对应上面取钱例子而言,就绪读写指的是排队,实际读写指的是取钱操作。

同步,异步:

  • 同步指的是操作的时候,需要等待当前任务返回结果;异步则相反,它不需要等待当前任务返回,通常情况下是依赖于事件,回调机制来实现任务间的次序关系。
  • 同步,异步对于IO而言指的是实际读写阶段;对应取钱例子而言,就是真正取钱操作(同步,自己取钱;异步,朋友帮忙取钱)。

阻塞,非阻塞:

  • 阻塞指的是如果任务在执行,当前线程会阻塞,需要等待任务执行完,这期间该线程不能执行其他任务;非阻塞则是说在一个任务执行期间,线程不会阻塞,可以执行其他任务。
  • 阻塞,非阻塞对于IO而言指的是就绪读写阶段;对应取钱例子而言,就是排队等候(阻塞,排队没带手机,只能干等着;非阻塞,排队带了手机,可以一边玩手机一边排队)。

BIO,NIO,AIO示例代码参考:

(以上所有内容皆为个人笔记,如有错误之处还望指正。)

Java中的I/O的更多相关文章

  1. java中的锁

    java中有哪些锁 这个问题在我看了一遍<java并发编程>后尽然无法回答,说明自己对于锁的概念了解的不够.于是再次翻看了一下书里的内容,突然有点打开脑门的感觉.看来确实是要学习的最好方式 ...

  2. java中的字符串相关知识整理

    字符串为什么这么重要 写了多年java的开发应该对String不陌生,但是我却越发觉得它陌生.每学一门编程语言就会与字符串这个关键词打不少交道.看来它真的很重要. 字符串就是一系列的字符组合的串,如果 ...

  3. Java中的Socket的用法

                                   Java中的Socket的用法 Java中的Socket分为普通的Socket和NioSocket. 普通Socket的用法 Java中的 ...

  4. java中Action层、Service层和Dao层的功能区分

    Action/Service/DAO简介: Action是管理业务(Service)调度和管理跳转的. Service是管理具体的功能的. Action只负责管理,而Service负责实施. DAO只 ...

  5. Java中常用集合操作

    一.Map 名值对存储的. 常用派生类HashMap类 添加: put(key,value)往集合里添加数据 删除: clear()删除所有 remove(key)清除单个,根据k来找 获取: siz ...

  6. java中的移位运算符:<<,>>,>>>总结

    java中有三种移位运算符 <<      :     左移运算符,num << 1,相当于num乘以2 >>      :     右移运算符,num >& ...

  7. 关于Java中进程和线程的详解

    一.进程:是程序的一次动态执行,它对应着从代码加载,执行至执行完毕的一个完整的过程,是一个动态的实体,它有自己的生命 周期.它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而 ...

  8. Java中的进程和线程

     Java中的进程与线程 一:进程与线程 概述:几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是 ...

  9. Java中的进程与线程(总结篇)

    详细文档: Java中的进程与线程.rar 474KB 1/7/2017 6:21:15 PM 概述: 几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进 ...

  10. 初探java中this的用法

    一般this在各类语言中都表示“调用当前函数的对象”,java中也存在这种用法: public class Leaf { int i = 0; Leaf increment(){ i++; retur ...

随机推荐

  1. ES6——Promise

    异步和同步 异步,操作之间没有关系,同时执行多个操作, 代码复杂 同步,同时只能做一件事,代码简单 Promise 对象 用同步的方式来书写异步代码 Promise 让异步操作写起来,像在写同步操作的 ...

  2. 编辑器和IDE的区别以及WebStorm和PhpStorm的区别

    编辑器和IDE的区别: 编辑器就是纯粹编辑文本的编辑器,识别级别在文字级,只显示你想写入和打开的文本内容,不管你写什么内容,只提供接收与显示功能,Windows自带的写字板就是最简单的编辑器.举个生活 ...

  3. mui实现分页上拉加载更多 下拉刷新数据的简单实现 移动端下拉上拉

    空下来把mui上拉加载更多,下拉刷新数据做了一个简单的实现,希望可以帮助到需要的朋友 demo项目的结构 <!DOCTYPE html> <html> <head> ...

  4. 基于谷歌开源的TensorFlow Object Detection API视频物体识别系统搭建自己的应用(四)

    本章主要内容是利用mqtt.多线程.队列实现模型一次加载,批量图片识别分类功能 目录结构如下: mqtt连接及多线程队列管理 MqttManager.py # -*- coding:utf8 -*- ...

  5. referenceQueue用法

    何为referenceQueue 在java的引用体系中,存在着强引用,软引用,虚引用,幽灵引用,这4种引用类型.在正常的使用过程中,我们定义的类型都是强引用的,这种引用类型在回收中,只有当其它对象没 ...

  6. 重启uwsgi

    sudo pkill -f uwsgi -9 uwsgi --ini mysite.uwsgi.ini

  7. Java 逻辑运算符相关解析

    问:定简单说说 Java 中 & 与 && 有什么区别?| 与 || 呢? 答:& 是位运算符,&& 是布尔逻辑运算符,| 与 || 类似同理.在进行逻 ...

  8. flask之url_for函数

    一:url_for函数 干什么的?传入函数名,得到函数的路由地址(访问视图函数的地址) from flask import Flask from flask import url_for app = ...

  9. python 日期封装

    import time import datetime import locale class TimeUtil: def __init__(self, curtime=None): self.cur ...

  10. rm 或者ls 报Argument list too long

    一个文件夹下面碎文件太多,rm 或者 ls的时候报 Argument list too long 解决办法: find /tmp -type d -name "*-*-" -del ...