首先概述一下IO是什么
你想象 并思考一下 当你编辑一个文本文件,忘记了ctrl+s而关闭了 是不是很蛋疼,当你电脑上插入一个U盘 把一个视频从U盘拷入你电脑硬盘里。这些数据都是在那些设备上?
我们可以把这种数据的传输 看作是一种数据的流动,按照流动的方向,以内存为基准,分为输入input和输出output,即流向内存是输入流,输出内存的输出流
在Java中I/O操作主要是指使用其IO包下的内容进行输入,输出操作 通常 输入叫做读取数据 输出叫做写出数据
根据数据流向的不同 我们可以把其分为:输入流和输出流
输入流:把数据从其他设备上读取到内存中的流
输出流:把数据从内存中写出到其他设备上的流
根据数据的格局类型可以分为:字节流和字符流
字节流:以字节为单位 读写数据的流
字符流:以字符为单位,读写数据的流
在IO流下的两大分类都有两个祖宗倍的类
字节流中:
输入流: InputStream(字节输入流)
输出流:OutputStream(字节输出流)
字符流中:
输入流:Reader(字符输入流)
输出流:Writer(字符输出流)
先扯扯字节流:
在面向对象思想中有“万物皆对象”,而在这里我也把字节套一套叫"一切皆字节".
一切文件数据在存储时,都是以二进制数字的形式保存 都一个一个的字节 那么传输时一样如此。所以,字节流可以传输任意文件数据。所以我们时时刻刻都要明确,无论使用什么样的流对象 底层传输始终为二进制数据
字节输入流[InputStream]:
IO.InputStream抽象类是表示字节输入流的所有类的超类,可以读取字节信息到内存中。定义了字节输入流的基本共性功能方法
例如:
public void close():关闭此输入流并释放与此流相关链的任何系统资源
public abstract int read():从输入流读取数据的下一个字节
public int read(byte[] b):从输入流中读取一些字节数,并将它们存储到字节数组b中
注意:当完成了对流的操作方法时必须调用close方法来释放系统资源
FileInputStream类:
IO.FileInputStream类是文件输入流,从文件中读取字节
构造方法:
FileInputStream(File file):通过打开与实际文件的连接来创建一个FileInputStream 该文件由文件系统中的File对象file命名
FileInputStream(String name):通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的路径名name命名
当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有该文件,会抛出FIleNotFoundException。
代码实例:
//使用File对象创建流对象 File file=new File("a.txt"); FileInputStream fos=new FileInputStream(file); //使用文件名称创建流对象 FileInputStream fos=new FileInputStream("b.txt");
读取字节数据:
1.读取字节:read方法,每次可以读取一个字节的数据 提升为int类型 读取到文件末尾,返回-1,代码示例:
//首先使用文件名称创建流对象 FileInputStream fis=new FileInputStream("read.txt"); //然后读取数据,返回一个字节 int read=fis.read(); System.out.Println((char)read); read=fis.read(); System.out.Println((char)read); read=fis.read(); System.out.println((char)read); read=fis.read(); SYstem.out.println((char)read); //读取到末尾 返回-1 read=fis.read(); System.out.println(read); //最后记得关闭资源 fis.close(); //------------------------------------------------------------------------------------ //使用循环进行读写 //首先使用文件名创建流对象 FileInputStream fis=new FileInputStream("read.txt"); //定义变量,保存数据 int b; //循环读取 while((b=fis.read())!=-1){ System.out.println((char b)); } //关闭资源 fis.close();
注意: 读取字节会自动提升为int类型, 流操作完毕后必须释放系统资源 调用close方法
2.使用字节数组读取:read(byte[] b),每次读取b的长度个字节到数组中,返回读取到的有效字节个数 读取到末尾时,返回-1
代码示例:
//使用文件名称创建流对象 FileInputStream fis=new FileInputStream("d:\aaa.txt");//文件中为abcde //定义变量 作为有效个数 int len; //定义字节数组 作为装字节数据的容器 byte[] b=new byte[2]; //循环读取 while ((len=fis.read(b))!=-1){ //每次读取后,把数组编程字符串打印 //System.out.println(new String(b));
//len每次读取的有效字节个数
System.out.println(new String(b,0,len)); } //关闭资源 fis.close();
//如果正常执行会导致单一个 所以要通过len获取有效的字节
//使用数组读取 每次读取多个字节 可以减少系统IO操作次数 提高读写效率
字节输出流[OutputStream]:
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):将指定的字节输出流
注意:当完成流的操作时 必须调用close方法释放系统资源
FileOutputStream类:
OutputStream有很多子类 最简单的莫过于FileOutputStream类,此类为文件输出流,用于将数据写出到文件
构造方法:
public FileOutputStream(File file):创建文件输出流以写入由指定的File对象表示的文件
public FileOutputStream(String name):创建文件输出流以指定的名称写入文件
当你创建一个流对象时 必须传入一个文件路径 该路径下 如果没有这个文件 会创建该文件 如果有这个文件 会清空这个文件的数据
代码示例:
//使用File对象创建流对象 File file=new File("a.txt"); FileOutputStream fos=new FileOutputStream(file); //使用文件名称创建流对象 FileOutputStream fosr=new FileOutputStream("b.txt");
写出字节数据:
1.写出字节:write(int b)方法 每次可以写出一个字节数据
//使用文件名称创建流对象 FileOutputStream fos=new FileOutputStream("aaa.txt"); //写出数据 fos.write(97);//写出第一个字节 fos.write(98);//写出第二个字节 fos.write(99);//写出第三个字节 //关闭资源 fos.close();
注意:虽然参数为int类型四个字节 但是只会保留一个字节的信息写出
2.写出字节数组:write(byte[] b) 每次可以写出数组中的数据
//使用文件名称创建流对象 FileOutputStream fos=new FileOutputStream("fos.txt"); //字符串转换为字节数组 byte[] b="黑马程序员".getBytes(); //写出字节数组数据 fos.write(b); //关闭资源 fos.close();
3.写出指定长度字节数组:write(byte[] b,int off,int len) 每次写出从off索引开始 len个字节,代码示例:
//使用文件名称创建流对象 FileOutputStream fos=new FileOutputStream("fos.txt"); //字符串转换为字节数组 byte[] b="abcde".getBytes(); //写出从索引2开始 2个字节 索引2时c 两个字节 也就是cd fos.write(b,2,2); //关闭资源 fos.close();
数据追加续写
每次程序运行 创建输出流对象 都会清空目标文件中的数据
public FileOutputStream(File file,boolean append):创建文件输出流以写入由指定的File对象表示的文件.
public FileOutputStream(String name,boolean append):创建文件输出流以指定的名称写入文件
这两个构造方法,参数中都需要传入一个boolean类型的指 true表示追加数据 false表示清空原有数据 代码示例:
//使用文件名称创建流对象 FileOutputStream fos=new FileOutputStream("aaa.txt",true); //字符串转换为字节数组 byte[] b="abcde".getBytes(); //写出从索引2开始,2个字符 索引2是c 两个字节 也就是cd fos.write(b); //关闭索引 fos.clos e();
输出换行
windows系统中 换行比符号是 。代码示例:
//使用文件名称创建流对象 FileOutputStream fos=new FileOutputStream("aaa.txt"); //定义字节数组 byte[] words={97,98,99,100,110}; //遍历数组 for (int i = 0; i < words.length; i++) { //写出一个字节 fos.write(words[i]); //写出一个换行 换行符号转成数组写出 fos.write(" ".getBytes()); } //关闭资源 fos.close();
字符流
字符输入流【Reader】
IO.Reader抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。它的基本共性方法
public void close():关闭此流并释放与此流相关联的任何系统资源
public int read():从输入流读取一个字符
public int read(char[] cbuf):从输入流中读取一些字符 并将它们存储到字符数组cbuf中
FileReader类:
IO.FileReader类是读取字符文件的便利类 构造时使用系统默认的字符编码和默认字节缓冲区,所谓系统默认字符编码:windows默认中文编码时GBK 默认字节缓冲区时一个字节数组 用来临时存储字节数据的
构造方法:
FileReader(File file):创建一个新的FileReader 给定要读取的File对象
FileRader(String fileName):创建一个新的FileReader 给定要读取的文件的名称
//使用文件名称创建流对象 FileReader fr=new FileRader("d:\bb.txt"); //读取字符数据 int b=fr.reader(); //使用字符数组读取 char[] c=new char[2]; System.out.println(new String(c));
字符输出流【Writer】:
IO.Writer抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地.它包含了输出流的基本共性方法:
void write(int c):写入单个字符
void write(char[] c):写入字符数组
abstract void write(char[] c,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类:
IO.FileWriter类是写出字符到文件的便利类 构造时使用系统默认的字符编码和默认字节缓冲区
构造方法:
FileWriter(File file):创建一个新的FileWriter 给定要读取的File对象
FileWriter(String fileName):创建一个新的FileWriter 给定要读取的文件的名称
//使用文件名称创建留对象 FileWriter fw=new FileWriter("d:\aaa.txt"); //写出字符 fw.write(97); //关闭和刷新 fw.write(98); fw.flush(); fw.write(99); fw.close(); //write的其他用法 fw.write("嘿嘿); fw.write(new char[]) //续写与换行 FileWriter fw=new FileWriter("aaa.txt",true); fw.write(" ");
提一嘴使用异常处理IO错误 这里只写除JDk7新特性写法 因为这种写法比较常见
try(FileInputStream fis=new FileInputStream(filepath);
FileOutputStream fos=new FileOutputStream(filePath1)){ byte[] buffer=new byte[1024]; while (true){ int temp=fis.read(buffer,0,buffer.length); if(temp==-1){ break; }else { fos.write(buffer,0,temp); } } }catch (IOException e){ System.out.println(e); }
说到存储数据 不得不提一提Priperties类
属性集【Properties】继承与Hashtable 用来表示一个持久的属性集 此类因为继承字hash所以采用键值结构存储数据 ,每个键及其对应值都时一个字符串
构造方法:
public Properties():创建一个空的属性列表
基本存储方法:
public Object setProperty(String key,String value):保存一对属性
public String getProperty(String key):使用此属性列表中指定的键搜索属性值
public Set<String>stringPropertyNames():所有键的名称的合集
代码示例:
//创建属性集对象 Properties properties=new Properties(); //添加键值对元素 properties.setProperty("小明","14"); properties.setProperty("小方","15"); properties.setProperty("小花","13"); //打印属性集对象 System.out.println(properties); //通过键 获取属性值 System.out.println(properties.getProperty("小明")); System.out.println(properties.getProperty("小方")); System.out.println(properties.getProperty("小花")); //遍历属性集 获取所有键的集合 Set<String> strings=properties.stringPropertyNames(); //打印键值对 for (String string : strings) { System.out.println(strings+"--"+properties.getProperty(string)); }
与流相关的方法
public void load(InputStream inStream):从字节输入流中读取键值对
代码示例:
//创建属性集对象 Properties pro=new Properties(); //加载文本中信息到属性集 pro.load(new FileInputStream("d:\aaa.txt")); //遍历集合并打印 Set<String>strings =pro.stringPropertyNames(); for (String string : strings) { System.out.println(string+"--"+pro.getProperty(string)); }