目录

IO流


IO流

1 IO

1.1 I

  • input
  • 输入

1.2 O

  • output
  • 输出

2 IO流的分类

2.1 、按照IO流的数据流动方向分

  • 输入流
  • 输出流

2.2 、按照IO流的数据处理的最小单位分

  • 字节流
  • 字符流

2.3 、根据IO流的作用分

  • 节点流

    • 例如:文件IO流

      • 连接文件节点
  • 处理流

    • 在节点流的基础上增加其他功能,例如缓冲,编码解码,序列化等

3 IO流的四个抽象基类,超级父类

3.1 InputStream

  • 字节输入流

3.2 OutputStream

  • 字节输出流

3.3 Reader

  • 字符输入流

3.4 Writer

  • 字符输出流

4 和文件相关的IO流

4.1 类型

  • FileInputStream

    • 文件字节输入流
    • 读取任意类型的文件
  • FileOutputStream

    • 文件字节输出流
    • 写数据到任意类型的文件
  • FileReader

    • 文件字符输入流

    • 只能读取纯文本文件

      • .java
      • .txt
      • .html
      • .js
      • .css
      • ….
  • FileWriter

    • 文件字符输出流
    • 只能把数据保存到纯文本文件中

4.2 读取

  • (1)读取一个纯文本文件

    形式一:

    //(1)指定要读取的文件

    File file = new File(“upload/exam.txt”);

    //(2)创建文本文件的输入流

    FileReader fr = null;

    try{

    fr = new FileReader(file);

    //(3)在当前程序中创建一个字符数组,用来保存每一次读取的文本信息

    char[] data = new char[10];

    //(4)用来记录每一次读取的字符个数

    int len;

    //(5)用来拼接从文件读取的信息

    StringBuilder sb = new StringBuilder();

    //(6)循环读取

    while((len = fr.read(data))!=-1){

      sb.append(new String(data,0,len));
    

    }

    System.out.println(sb);

    }catch(Exception e){

    //….

    }finally{

    //(7)释放资源

    try{

      if(fr!=null){
    
      	fr.close();
    
      }
    

    }catch(Exception e){

    }

    }

    形式二:

    File file = new File(“upload/exam.txt”);

    try(

    FileReader fr = new FileReader(file);

    ){

    char[] data = new char[10];

    int len;

    StringBuilder sb = new StringBuilder();

    while((len = fr.read(data))!=-1){

      sb.append(new String(data,0,len));
    

    }

    System.out.println(sb);

    }catch(Exception e){

    //….

    }

  • (2)读取任意类型的文件

    //(1)指定文件

    File file = new File("…..");

    //(2)创建字节输入流

    try(

    FileInputStream fis = new FileInputStream(file);

    ){

    //(3)创建字节数组,用来存储每次读取的内容

    byte[] data = new byte[1024];

    //(4)用len记录每次读取的字节数

    int len;

    //(5)循环读取

    while( (len = fis.read(data)) !=-1){

      //......
    

    }

    }catch(Exception e){

    //…

    }

4.3 保存

  • (1)把数据保存到一个纯文本文件

    //(1)指定要保存的文件

    File file = new File("….");

    try(

    FileWriter fw = new FileWriter(file);

    ){

    String info = “…..”; //要写入到文件的数据内容

    fw.write(info);

    //或

    char[] data = new char[1024];

    //…把数据保存到data中

    fw.write(data,0,len);

    }catch(Exception e){

    //….

    }

  • (2)把数据保存到一个任意类型的文件

    //(1)指定要保存的文件

    File file = new File("….");

    try(

    FileOutputSream fos = new FileOutputSream(file);

    ){

    byte[] data = ….; //用来存储要输出到文件的内容

    fos.write(data,0 ,len);

    }catch(Exception e){

    //….

    }

4.4 复制

  • 一边读一边写

    • 纯文本文件

      public static void main(String[] args) {

        //(1)创建源文件对象
      
        File src = new File("1.txt");
      
      
      
        //(2)创建目标文件对象
      
        File dest = new File("2.txt");
      
      
      
        //(3)创建输入流
      
        FileReader fr = null;
      
        //(4)创建输出流
      
        FileWriter fw = null;
      
      
      
        try {
      
        	fr = new FileReader(src);
      

      // fw = new FileWriter(dest);//覆盖模式

        	fw = new FileWriter(dest,true);//追加模式
      
      
      
        	//(5)一边读一边写
      
        	//从fr读一些,就写入fw一些
      
        	char[] data = new char[6];//1024
      
        	while(true){
      
        		int len = fr.read(data);
      
        		if(len == -1){
      
        			break;
      
        		}
      
        		fw.write(data,0,len);//本次读了几个字符,就写几个字符
      
        	}
      
        } catch (FileNotFoundException e) {
      
        	e.printStackTrace();
      
        } catch (IOException e) {
      
        	e.printStackTrace();
      
        } finally{
      
        	try {
      
        		if(fr!=null){
      
        			fr.close();
      
        		}
      
        	} catch (IOException e) {
      
        		e.printStackTrace();
      
        	}
      
      
      
        	try {
      
        		if(fw!=null){
      
        			fw.close();
      
        		}
      
        	} catch (IOException e) {
      
        		e.printStackTrace();
      
        	}
      
        }
      

      }

    • 任意类型文件

      public static void main(String[] args) {

        // (1)创建源文件对象
      
        File src = new File("2.jpeg");// 完整的描述:路径+文件名+后缀名
      
      
      
        // (2)创建目标文件对象
      
        File dest = new File("3.jpg");
      
      
      
        // (3)创建输入流
      
        // (4)创建输出流
      
      
      
        try (
      
        		FileInputStream fis = new FileInputStream(src);
      
        		FileOutputStream fos = new FileOutputStream(dest);
      
        	) {
      
      
      
        	byte[] data = new byte[10];
      
      
      
        	int len;
      
        	while ((len = fis.read(data)) != -1) {
      
        		fos.write(data, 0, len);
      
        	}
      
      
      
        } catch (FileNotFoundException e) {
      
        	e.printStackTrace();
      
        } catch (IOException e) {
      
        	e.printStackTrace();
      
        }
      

      }

4.5 File

  • 用来表示一个文件或者一个目录

    • 实际上是一个抽象的路径名
  • 获取文件或目录的一些信息

    • (1)获取文件的大小

      • long length()

      • 如果要获取目录的大小,必须编写递归

        public long getDirLength(File dir){

          if(dir.isFile()){//如果是文件,直接返回文件的大小
        
          	return dir.length();
        
          }else if(dir.isDirectory()){
        
          	long sum = 0;
        
          	File[] listFiles = dir.listFiles();
        
          	for (File sub : listFiles) {
        

        // sum += 下一级的大小;

          		sum += getDirLength(sub);
        
          	}
        
          	return sum;
        
          }
        
          return 0;//既不是文件又不是文件夹,不存在
        

        }

      • 如果文件不存在,返回0

    • (2)获取文件或目录的名称

      • String getName()
    • (3)获取文件或目录的路径

      • String getPath():获取路径 String getAbsolutePath():获取绝对路径 String getCanonicalPath():获取规范路径,例如:../ /
    • (4)获取文件的后缀名

      • String name = file.getName();//得到文件名 包含扩展名
      • String ext = name.substring(name.lastIndexOf(’.’));
    • (5)获取文件的最后修改时间

      • long lastModified()

        • 毫秒数
      • 如果文件不存在,返回0

    • (6)获取上一级目录

      • String getParent()
      • File getParentFile()
  • 判断

    • (1)是否是文件

      • isFile()

        • 仅当file代表的文件存在,并且是个文件,才返回true
      • 如果文件不存在,返回false

    • (2)是否是目录

      • isDirectory()

        • 仅当file对象代表的目录存在,并且是个文件夹目录,才返回true
      • 如果对应的不存在,返回false

    • (3)是否存在

      • exists()
    • (4)是否隐藏

      • isHidden()
    • (5)文件是否可读

      • canRead()
    • (6)文件是否可写

      • canWrite()
  • 操作

    • (1)创建文件

      • createNewFile()
    • (2)创建目录

      • mkdir()

        • 如果父目录不存在,那么创建失败
      • mkdirs()

        • 如果父目录不存在,也一并创建
    • (3)删除文件或目录

      • delete()

      • 只能删空目录

      • 如果要删除有内容的目录,需要使用递归

        public void delDir(File file){

          //如果是目录
        
          if(file.isDirectory()){
        
          	//(2)先获取下一级,并删除下一级
        
          	//a:获取下一级
        
          	File[] listFiles = file.listFiles();
        
          	//b:遍历并删除下一级
        
          	for (File sub : listFiles) {
        
          		//这是一个重复的过程
        
          		delDir(sub);//调用自己
        
          	}
        
          }
        
        
        
          //删除自己
        
          file.delete();
        

        }

    • (4)重命名

      • renameTo(File newFile)
  • 操作文件夹

    • 获取它的下一级

      • String[] list();
      • File[] listFiles()

5 处理流

5.1 缓冲流

  • 作用:增加缓冲区,提供效率

  • 类型

    • BufferedInputStream

      • 包装InputStream

        • 例如:FileInputStream、DataInputStream、ObjectInputStream等
    • BufferedOutputStream

      • 包装OutputStream

        • 例如:FileOutputStream、DataOutputStream、ObjectOutputStream等
    • BufferedReader

      • 包装Reader

        • 例如:FileReader、InputStreamReader等
      • String readLine()

        • 判断是否读完,使用 ==null
    • BufferedWriter

      • 包装Writer

        • 例如:FileWriter,OutputStreamWriter等
      • write(String) + newLine()

    • 缓冲区的大小

      • 字节流

        • 8192字节
      • 字符流

        • 8192字符

5.2 数据流

  • 作用:可以处理Java的基本数据类型+字符串(UTF-8修改版)

  • 类型

    • DataOutputStream

      • writeXxx()

        • writeInt(int)
        • writeDouble(double)
        • writeChar(char)
        • writeUTF(String)
    • DataInputStream

      • readXxx()

        • int readInt()
        • double readDouble()
        • char readChar()
        • String readUTF()
  • 注意:

    • (1)DataOutputStream写,用DataInputStream读取

    • (2)写的顺序和读的顺序要一致

      • 写与读之间需要配置文件等形式进行沟通顺序和类型

5.3 对象流

  • 作用:可以处理Java对象等

  • 类型

    • ObjectOutputStream

      • writeObject(Object)
      • 对象的序列化
    • ObjectInputStream

      • Object readObject()
      • 对象的反序列化
  • 注意

    • (1)凡是要序列化的对象,它的类型必须实现java.io.Serializable接口

      • 否则会报:NotSerializableExecption
    • (2)如果属性涉及到其他的引用数据类型,那么这个类型也必须实现java.io.Serializable接口

    • (3)如果某个属性不想要序列化,那么可以在属性之前加transient

      • 一旦加了这个关键字修饰,该属性的值会在序列化的过程中,被忽略
      • 一旦加了这个关键字修饰,该属性在反序列化的过程中,它的值就赋默认值
    • (4)在实现java.io.Serializable接口时,最好加一个常量:序列化版本ID

      • private static final long serialVersionUID = 1L;
    • (5)静态的属性不能序列化

5.4 打印流

  • 作用:可以打印各种类型的数据,最终都是以字符的形式打印,如果是引用数据类型,就调用它的toString()

  • 类型

    • PrintStream

      • 代表

        • System.out
      • 方法

        • print(xxx)
        • println(xxx)
    • PrintWriter

      • 方法

        • print(xxx)
        • println(xxx)

6 NIO(了解)

6.1 NIO

  • Non - Blocking IO

    • 非阻塞式IO

6.2 NIO和IO的区别

  • 区别一

    • IO是面向流,是单向的,从某个流中要么只能读,要么只能写

      • 例如:要读文件

        • FileInputStream
        • FileReader
      • 类型即决定可以进行的操作

    • NIO是面向通道+缓冲区,即可以是单向的,又可以是双向的

      • 例如:ByteBuffer

        • put

          • 往里写
        • get

          • 往外读
      • 例如:FileChannel

        • 既可以指定为只读
        • 又可以指定为可读可写
  • 区别二

    • IO是阻塞式的,一旦某个线程在读,此时没有可读的数据,会一直等待
    • NIO是非阻塞式
  • 区别三

    • NIO可以使用选择器

6.3 和新的IO的API相关的

  • Path

    • 是一个接口
  • Paths

    • 用来获取Path的对象
    • Paths.get(URI)
    • Paths.get(String first, String… others)
  • Files

    • 工具类

      • 静态方法
    • 和Path用来替代原来的File

    • 方法

      • 创建文件

        • createFile

          • 如果文件已存在,直接报异常
        • 和File类的createNewFile()区别

          • 如果文件已存在,不提示
      • 创建目录

        • createDirectory

          • 替代原来的File的mkdir
          • 不同的是,如果目录已存在,就会报异常
        • createDirectories

          • 替代原来的File的mkdirs
          • 不同的是,如果目录已存在,就会报异常
      • 复制文件

        • copy

        • 区别

          • 如果目标文件不存在,直接创建
          • 如果目标文件已存在,要看是覆盖模式吗
          • 默认情况下,已存在,会报异常
      • 读取文件

        • readAllLines(Path path)

          • 读取文件,返回List

          • 默认是StandardCharsets.UTF_8

          • 可以自己指定字符编码方式

            • Charset.forName(字符集名称)
      • ….

6.4 通道

  • 主要是四种类型

    • 和文件读取和存储相关的

      • FileChannel
    • 和TCP服务器端使用

      • ServerSocketChannel
    • 和TCP的客户端使用

      • SocketChannel
    • 和UDP的两端使用

      • DatagramChannel
  • 必须和缓冲区结合才能使用

  • 它的对象的创建

    • 例如:

      • FileChannel.open(xxx)

6.5 缓冲区

  • 主要是7大类型

    • ByteBuffer

      • MappedByteBuffer
    • ShortBuffer

    • IntBuffer

    • LongBuffer

    • FloatBuffer

    • DoubleBuffer

    • CharBuffer

    • 除了boolean

  • 属性

    • (1)capacity:容量

      • 总大小,一旦创建就固定
    • (2)limit:限制

      • 可读或可写的最大索引的位置
    • (3)position:当前位置

      • 当前正在读或写的位置
    • (4)mark:标记的位置

    • 0<=mark<=position<=limit<=capacity

  • 方法

    • (1)put

      • 往缓冲区写

      • 或者调用通道.read(xx)

        • 也相当于往缓冲区写
    • (2)get

      • 从缓冲区取

      • 或者调用通道.write(xx)

        • 也相当于从缓冲区取数据
    • (3)flip()

      • 切换读写模式
    • (4)clear()

      • 重新使用缓冲区
  • 示例

    • (1)读文件

      @Test

      public void test() throws IOException{

        Path path = Paths.get("1.txt");
      
        FileChannel fc = FileChannel.open(path, StandardOpenOption.READ);//打开通道
      
        ByteBuffer bb = ByteBuffer.allocate(1024);
      
        StringBuilder sb = new StringBuilder();
      
      
      
        while(true){
      
        	//把数据放到缓冲区
      
        	int len = fc.read(bb);//把数据装到缓冲区    对于缓冲区来说是存储,相当于put
      
        	if(len<=0){
      
        		break;
      
        	}
      
        	//切换
      
        	bb.flip();
      
      
      
        	//从缓冲区读取数据
      
        	byte[] data = new byte[10];
      
        	bb.get(data,0,bb.limit());
      
        //	System.out.println(new String(data,0,bb.limit()));
      
        	sb.append(new String(data,0,bb.limit()));
      
      
      
        	bb.clear();
      
        }
      
      
      
        System.out.println(sb);
      

      }

    • (2)复制文件

      @Test

      public void testCopy()throws Exception{

        long start = System.currentTimeMillis();
      
        FileChannel fc = FileChannel.open(Paths.get("software/ideaIU-Ultimate-2017.1.4.exe"), StandardOpenOption.READ);
      
        FileChannel to = FileChannel.open(Paths.get("2.exe"), StandardOpenOption.WRITE,StandardOpenOption.CREATE_NEW);
      
      
      
        ByteBuffer bb = ByteBuffer.allocate(10);//定义缓冲区大小
      
      
      
        while(fc.read(bb)!=-1){//读取数据到缓冲区,即往缓冲区写  相当于put
      
        	bb.flip();//修改limit为position  然后position为0       没有这个,就从position开始读到limit,limit=capacity,position为写完的位置
      
      
      
        	to.write(bb);
      
      
      
        	bb.clear();//limit变成capicity  position=0   没有这个,那么就会重复写第一次读取的内容,一会文件大小就很大,爆了
      
        }
      
      
      
        fc.close();
      
        to.close();
      
      
      
        long end = System.currentTimeMillis();
      
        System.out.println("ByteBuffer:"+ (end-start));
      

      }

    • (3)物理映射复制文件(速度超快)

      @Test

      public void test2()throws Exception{

        long start = System.currentTimeMillis();
      
      
      
        FileChannel from = FileChannel.open(Paths.get("software/ideaIU-Ultimate-2017.1.4.exe"), StandardOpenOption.READ);
      
        FileChannel to = FileChannel.open(Paths.get("3.exe"), StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE_NEW);//如果CREAD,如果文件已经存在不会报错,但是会从文件头开始写
      
      
      
        MappedByteBuffer fbb = from.map(MapMode.READ_ONLY, 0, from.size());
      
        MappedByteBuffer tbb = to.map(MapMode.READ_WRITE, 0, from.size());
      
      
      
        tbb.put(fbb);
      
      
      
        from.close();
      
        to.close();
      
      
      
        long end = System.currentTimeMillis();
      
        System.out.println("ByteBuffer:"+ (end-start));
      

      }

7 length

7.1 数组

  • 数组的长度

    • int len = arr.length;

      • 属性

7.2 字符串的长度

  • int len = str.length();

7.3 文件的长度

  • long len = file.length();

8 org.apache工具包