关于IO流的概述

IO流

IO的概述

什么是IO

java.io

I/O操作主要是指使用java.io包下的内容,进行输入、输出操作。输入也叫做读取数据,输出也叫做作写出数据。

数据在设备间的传输可以看成一种数据流动,称为流。以内存为基准,按照流动方向,分为输入input 和输出output,流向内存是输入流,流出内存是输出流

IO的分类

数据的流向:输入流输出流

输入流:将数据从 其他设备 上读取到 内存 中的流
输出流:将数据从   内存  中写到 其他设备 上的流    
 /*        输入
//硬盘 ------------>内存 
           输出
  硬盘<-------------内存     */ 

数据的类型:字节流字符流

字节流:以字节为单位,读写数据的流
字符流:以字符为单位,读写数据的流    
顶级父类
输入流输出流
字节流InputStreamOutputStream
字符流ReaderWriter
均为抽象类

字节流

字节流可以传输任意文件数据,无论使用什么流对象,底层传输始终为二进制数据(文本数据,文本,图片,视频等)

字节输出流(OutputStream)

java.io.OutputStream抽象类,表示字节输出流的所有类的超类,将指定的字节信息写出到目的地。

功能方法

  • public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
  • public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。
  • public void write(byte[] b):将 b.length字节从指定的字节数组写入此输出流。
  • public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。
  • public abstract void write(int b) :将指定的字节输出流。

FileOutputStream类

java.io.FileOutputStream extends OutputStream

java.io.FileOutputStream类是文件输出流,用于将内存中数据写入到硬盘的文件。

构造方法
  • public FileOutputStream(File file):创建文件输出流以写入由指定的 File对象表示的文件。
  • public FileOutputStream(String name): 创建文件输出流以指定的名称写入文件。
参数:写入数据的目的
    String name :目的地是一个文件的路径
    File file   :目的地是一个文件
构造方法的作用:
    1.创建一个FileOutputStream对象
    2.根据构造方法中传递的文件/文件路径,创建一个空的文件
    3.把FileOutputStream对象指向创建好的文件

写入数据的原理(内存->硬盘)

java程序-->JVM-->OS--->OS调用写数据的方法-->数据写入文件中

字节输出流使用步骤

1.创建一个FileOutputStream对象,构造方法传递写入数据的目的地(文件/路径)
2.调用 FileOutputStream对象中write方法,把数据写入到文件中
3.释放资源(流使用占有一定内存)  
    
package OutputStream;

import java.io.FileOutputStream;
import java.io.IOException;

public class OutputStreamDemo {
    public static void main(String[] args) throws IOException {
        //创建一个FileOutputStream对象,构造方法中传递写入数据的目的地
        FileOutputStream fos = new FileOutputStream("D:\\Project\\Demo\\a.txt");
        //调用FileOutputStream对象中的write方法,将数据写入到文件中
        //public abstract void write(int b) :将指定的字节输出流。
        fos.write(100);
        //必须释放资源
        fos.close();
    }
}
写出字节数据

写出字节

import java.io.IOException;

public class FOSWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("fos.txt");
        // 写出数据 
        //write(int b)方法,每次可以写出一个字节数据
        fos.write(97); // 写出第1个字节
        fos.write(98); // 写出第2个字节
        fos.write(99); // 写出第3个字节
        // 关闭资源
        fos.close();
    }
}

输出结果:abc

写出字节数组

public void write(byte[] b) :将b.length字节从指定的字节数组写入此输出流

如果写的第一个字节是正数(0-127),那么会查询ASCII表

如果写的第一个字节是负数,那么第一个字节会和第二个字节组成一个中文显示,查询系统默认码表(GBK)

package OutputStream;

import java.io.FileOutputStream;
import java.io.IOException;

public class FOSWrite {
    public static void main(String[] args) throws IOException {      
        // 使用文件名称创建流对象
        FileOutputStream fos = new            FileOutputStream("fos.txt");
        // 字符串转换为字节数组
        byte[] b = "小月牛逼".getBytes();
        // 写出字节数组数据
        //write(byte[] b),每次可以写出数组中的数据
        fos.write(b);
        // 关闭资源
        fos.close();
    }
}

结果: 小月牛逼

写出指定长度字节数组

write(byte[] b, int off, int len):把字节数组的一部分写入到文件中

int off:数组的开始索引

int len:写几个字节

package OutputStream;

import java.io.FileOutputStream;
import java.io.IOException;

public class FOSWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("fos.txt");
        
        // 字符串转换为字节数组
        byte[] b = "kentxy".getBytes();
        // 写出从索引2开始,2个字节。索引2是c,两个字节,也就是nt。
        //write(byte[] b, int off, int len) ,每次写出从off索引开始,len个字节
        fos.write(b,2,2);
        // 关闭资源
        fos.close();
    }
}

结果 : nt
数据追加续写

每次程序运行,创建输出流对象,都会清空目标文件里的数据,那么如何保留目标文件中的数据,并且继续添加呢?

  • public FileOutputStream(File file, boolean append): 创建文件输出流以写入由指定的 File对象表示的文件。
  • public FileOutputStream(String name, boolean append): 创建文件输出流以指定的名称写入文件。
参数:
   String name ,  File file  :写入数据的目的地
   boolean append:追加写开关
    true : 创建对象不会覆盖源文件,继续在文件末尾加写数据
    false :创建一个新文件,覆盖源文件
写出换行

写换行:写换行符号

window :\r\n  //回车加换行
linux : /n     //换行
mac : /r      //回车

字节输入流(InputStream)

java.io.InputStream抽象类,表示字节输出流的所有类的超类,可以读取字节信息到内存中。

功能方法

  • public void close() :关闭此输入流并释放与此流相关联的任何系统资源。
  • public abstract int read(): 从输入流读取数据的下一个字节。
  • public int read(byte[] b): 从输入流中读取一些字节数,并将它们存储到字节数组 b中 。

FileInputStream类

java.io.FileInputStream extends InputStream

java.io.FileInputStream类是文件输入流,用于把硬盘文件中的数据,读取到内存中使用。

构造方法
  • FileInputStream(File file): 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。
  • FileInputStream(String name): 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。
参数:读取文件的数据源
    String name:文件的路径
    File file:文件
构造方法的作用:
    1.创建一个FileInputStream对象
    2.把FileInputStream对象指定构造方法中药读取的文件

例子

public class FileInputStreamDemo throws IOException{
    public static void main(String[] args) {
   	 	// 使用File对象创建流对象
        File file = new File("a.txt");
        FileInputStream fos = new FileInputStream(file);
      
        // 使用文件名称创建流对象
        FileInputStream fos = new FileInputStream("b.txt");
    }
}

//创建一个流对象时,必须传入文件路径,如果该路径下,没有该文件,抛出FileNotFoundException

读取数据的原理

java程序-->JVM-->OS读取数据的方法-->读取文件

字节输入流的使用步骤

1.创建FileInputStream对象,构造方法中绑定要读取的数据源
2.使用FileInputStream对象中的方法read,读取文件
3.释放资源    
读取字节数据

读取字节

public class InputStreamDemo {
    public static void main(String[] args) throws IOException{
   // 创建FileInputStream对象,构造方法中绑定要读取的数据源
       	FileInputStream fis = new FileInputStream("read.txt"); //read.txt存放了abc
   // 使用FileInputStream对象中的read方法,读取文件
   //int read()读取文件中的一个字节并返回,读取到文件末尾返回-1
    /*    int read = fis.read();
        System.out.println( read);//97 a
        
        read = fis.read();
        System.out.println( read);//98 b
        
        read = fis.read();
        System.out.println(read); //99 c
        
        // 读取到末尾,返回-1
        read = fis.read();
        System.out.println(read); //-1
        
        read = fis.read();
        System.out.println(read);//-1
      */
        
  使用while循环优化
      /* 布尔表达式(len = fis.read() != -1
       1.fis.read() :读取一个字节
       2.len = fis.read() :把读取到的字节赋值给变量len
       3.len = fis.read() != -1:判断变量len是否不等于-1
      */
      int len = 0; //记录读取到的字节
        while(len = fis.read() != -1){
            System.out.println(len);
        }
      
		// 关闭资源
        fis.close();
    }
}

使用字节数组读取

int read(byte[] b):从输出流中读取一定数量的字节,将其存储在缓存区数组b中

String类的构造方法

String(byte[ ] bytes) : 把字节数组转换为字符串

String(byte[ ] bytes ,int offset ,int length) :把字节数组的一部分转换为字符串,offset:数组的开始索引 ,length:转换的字节个数

思考:
    1.方法的参数byte[]的作用?
    缓冲作用,存储每次读取到的多个字节
    数组的长度一般定义为1024(1kb)或者1024的整数倍
    2.方法的返回值int是什么?
    每次读取的有效字节数

例子

public class InputStreamDemo02 {
    public static void main(String[] args) throws IOException{
      	// 创建FileInputStream对象,构造方法中绑定要读取的数据源
       	FileInputStream fis = new FileInputStream("read.txt"); // 文件中为abcde
      	// 定义变量,作为有效个数
        int len =0// 定义字节数组,作为装字节数据的容器   
        byte[] b = new byte[2];
        // 循环读取
        //结束条件,读取到-1结束
        while (( len= fis.read(b))!=-1) {
           	// 每次读取后,把数组变成字符串打印
            System.out.println(new String(b));//ab,cd ,ed
          System.out.println(new String(b ,0 ,len));  //ab cd e
        }
		// 关闭资源
        fis.close();
    }
}

结果 :ab
       cd
       ed
    

字符流

使用字节流读取文本时,遇到中文字符,可能会显示不完整(一个中文字符可能占用多个字节存储),所以提供字符流。专门处理文本文件

1个中文
    GBK:占用两个字节
    UTF-8:占用3个字节

字符输入流(Reader)

java.io.Reader抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。

功能方法

  • public void close() :关闭此流并释放与此流相关联的任何系统资源。
  • public int read(): 读取单个字符并返回。
  • public int read(char[] cbuf): 从一次读取多个字符,将字符读入数组

FileReader类

java.io.FileReader extends InputStreamReader extends Reader

java.io.FileReader类是读取字符文件的便利类,把硬盘文件中的数据以字符的方式读取到内存中

构造方法
  • FileReader(File file): 创建一个新的 FileReader ,给定要读取的File对象。
  • FileReader(String fileName): 创建一个新的 FileReader ,给定要读取的文件的名称。
参数:读取文件的数据源
    String fileName :文件的路径
    File file :一个文件
FileReader构造方法的作用:
    1.创建一个FileReader对象
    2.把FileReader对象指向要读取的文件

字符输入流的使用步骤

1.创建FileReader对象,构造方法中绑定要读取的数据源
2.使用FileReader对象中read方法读取文件
3.释放资源    
读取字符数据

读取字符read方法

public class FileReaderDemo {
    public static void main(String[] args) throws IOException {
      	// 创建FileReader对象,构造方法中绑定要读取的数据源
       	FileReader fr = new FileReader("read.txt");//小月牛逼
      	//使用FileReader对象中read方法读取文件
        // int read():读取单个字符并返回
/*        int len = 0 ;
        // 循环读取
        while ((len = fr.read())!=-1) {
            System.out.println((char)len); //小 月 牛 逼
        }
        
  */
        //int read(char[] cbuf):一次读取多个字符,将字符读入数组
    char[] cd = new char[1024]; //存储读取多个字符
    int len = 0; //记录每次读取的有效个数
      while((len = fr.read(cd))!=-1)  {
          System.out.println(new String(cd ,0 ,len));//小月牛逼
      }
		// 关闭资源
        fr.close();
    }
}

字符输出流(Writer)

java.io.Writer抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。

功能方法

  • void write(int c) 写入单个字符。
  • void write(char[] cbuf)写入字符数组。
  • abstract void write(char[] cbuf, int off, int len)写入字符数组的某一部分,off数组的开始索引,len写的字符个数。
  • void write(String str)写入字符串。
  • void write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个数。
  • void flush()刷新该流的缓冲。
  • void close() 关闭此流,但要先刷新它。
FileWriter类

java.io.FileWriter extends OutputStreamWriter extends Writer

java.io.FileWriter `类是写出字符到文件的便利类,把内存中字符数据写入到文件中

构造方法
  • FileWriter(File file): 创建一个新的 FileWriter,给定要读取的File对象。
  • FileWriter(String fileName): 创建一个新的 FileWriter,给定要读取的文件的名称。
参数:写入数据的目的地
    String fileName:文件的路径
    File file:是一个文件
构造方法的作用:
    1.创建一个FileWriter对象
    2.根据构造方法中传递的文件/文件路径,创建文件
    3.把FileWriter对象指向创建好的文件

字符输出流的使用步骤

1.创建FileWriter对象,构造方法中写入数据的目的地
2.使用FileWriter中的write方法,把数据写入缓冲区(字符转换为字节的过程)
3.使用FileWriter中的flush方法,把内存缓冲区的数据,刷新到文件中
4.释放资源(会先把内存缓冲区中的数据刷新到文件中)    
写出数据

写出字符write(int b) 方法

public class FileWriterDemo {
    public static void main(String[] args) throws IOException {
        // 创建FileWriter对象,构造方法中写入数据的目的地
        FileWriter fw = new FileWriter("fw.txt");  //abc   
      	//使用FileWriter中的write方法,把数据写入缓冲区(字符转换为字节的过程)
        // 写出数据
      	fw.write(97); // 写出第1个字符
      	fw.write('b'); // 写出第2个字符
      	fw.write('C'); // 写出第3个字符
      	
        //使用FileWriter中的flush方法,把内存缓冲区的数据,刷新到文件中
        // fw.flush();
      	 //如果不关闭,数据只是保存到缓冲区,并未保存到文件。
        fw.close();
    }
}
结果: abc
关闭和刷新

flush方法和close方法的区别

fluse :刷新缓冲区,流对象可以继续使用
close :先刷新缓冲区,然后通知系统释放资源,流对象不能再被使用
public class FileWriterDemo {
    public static void main(String[] args) throws IOException {
        // 创建FileWriter对象,构造方法中写入数据的目的地
        FileWriter fw = new FileWriter("fw.txt");  //abc   
      	//使用FileWriter中的write方法,把数据写入缓冲区(字符转换为字节的过程)
        // 写出数据
      	fw.write(97); // 写出第1个字符
      
      	
      //  使用FileWriter中的flush方法,把内存缓冲区的数据,刷新到文件中
        //刷新后可以继续使用
         fw.flush();
        
      	fw.write('98'); // 写出第2个字符
        
      	 //如果不关闭,数据只是保存到缓冲区,并未保存到文件。
        fw.close(); //关闭,流不能再使用
        
        fw.write('99');//IOException:Stream closed
    }
}
写出其他数据

写出字符数组

  • void write(char[] cbuf) :写入字符数组

  • abstract void write(char[] cbuf, int off, int len):写入字符数组的某一部分,off数组的开始索引,len写的字符个数

  • void write(String str) :写入字符串

  • void write(String str,int off ,int len):写入数组的某一部分,off字符串的开始索引,len写的字符个数

IO异常的处理

JDK7前try...catch...finally 代码块,处理异常部分

JDK7优化try-with-resource 语句,该语句确保了每个资源在语句结束时关闭。

格式

try (创建流对象语句,如果多个,使用';'隔开) {
	// 读写数据
} catch (IOException e) {
	e.printStackTrace();
}

JDK9改进

try-with-resource 的改进,对于引入对象的方式,支持的更加简洁。被引入的对象,同样可以自动关闭,无需手动close

改进前

// 引入方式:创建新的变量保存
try (Resource r1 = resource1;
     Resource r2 = resource2) {
     // 使用对象
}

改进后

// 引入方式:直接引入
try (resource1; resource2) {
     // 使用对象
}

属性集

java.util.Properties 继承于 Hashtable` ,来表示一个持久的属性集。

Properties类

java.util.Properties extends Hashtable<k ,v> implements Map<k ,v>

构造方法

public Properties() :创建一个空的属性列表。

Properties 可保存在流中或从流中加载
Properties集合是唯一一个和IO流相结合的集合
    可以使用Properties集合中的store方法,把集合中的临时数据,持久化写入到硬盘中存储
    可以使用Properties集合中的load方法,把硬盘保存的文件(键对值),读取到集合中使用
    
属性列表每个键及其对应值都是一个字符串。
    Properties集合是一个双列集合,key和value默认都是字符串
存储方法
  • public Object setProperty(String key, String value) : 保存一对属性。
 调用Hashtable的方法put 
  • public String getProperty(String key) :使用此属性列表中指定的键搜索属性值。
通过key找到value,相当于Map集合中的get(key)方法 
  • public Set<String> stringPropertyNames() :所有键的名称的集合。
返回此属性列表的值其中该键及其对应值是字符串,此方法相当于Map集合中的keySet方法
与流相关的方法

public void load(InputStream inStream): 从字节输入流中读取键值对。

文本中的数据,必须是键值对形式,可以使用空格、等号、冒号等符号分隔。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值