个人理解:
IO流就是将数据进行操作的方式,因为编码的不同,所以对文件的操作就产生两种。最好用字节流,为了方便看汉字等,(已经确定文字的话)可以使用字符流。每个流派也就分为输入和输出,这样就可以产生复制文件了!需要注意的是Flush() 是清空,而不是刷新啊。
一般主要用在IO中,即清空缓冲区数据,就是说你用读写流的时候,其实数据是先被读到了内存中,然后用数据写到文件中,当你数据读完的时候不代表你的数据已经写完了,因为还有一部分有可能会留在内存这个缓冲区中。这时候如果你调用了 close()方法关闭了读写流,那么这部分数据就会丢失,所以应该在关闭读写流之前先flush(),先清空数据。
一、IO流:
1、JAVA对数据的操作是通过流的方式,JAVA用于操作数据流的类都在IO包中;
2、IO用于在设备间进行数据传输的操作;
3、分类:
①、流向:
输入流(读取数据)
输出流(写出数据)
②、数据类型:
字节流(可以操作任何数据):
字节输入流
字节输出流
字符流:
字符输入流
字符输出流
注意:
如果没明确说明按照什么分,默认按照数据类型分;
除非文件用windows自带的记事本打开我们能够读懂,才采用字符流,否则建议使用字节流。
4、IO程序书写:
使用前,导入IO包中的异常;
使用时,可进行IO异常的处理;
使用后,释放资源。
二、字节流:
1、字节输出流:outputStream
子类:文件输出流FileOutputStream用于将数据写入File的输出流。
import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class Demo01 { public static void main(String[] args) throws IOException { //创建字节输出流对象(因为是输出,必须有数据所以必须是文件,不能是文件夹) //构造方法指定文件地址时,如果存在,则覆盖!如果不存在,则创建! FileOutputStream fos=new FileOutputStream("D:\\java\\a.txt"); //向文件中写入一个字节 write (直接写数字 会对应其ASCII值)0-48 a-97 A-65 fos.write(49); fos.write(48); fos.write(48); //向文件中写入一个字节数组 write(byte[] b)正的走表,负的是汉字,两个字节组成一个汉字!多的一个字节显示? byte[] bytes={-66,-67,-68,-69,-70}; //fos.write(bytes); fos.write(bytes,2,2);//从第一个数字开始传第二个数字的个数 //释放资源 fos.close(); } }
import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class Demo02 { public static void main(String[] args) throws IOException { //创建字节输出流(开启续写功能)默认是flase FileOutputStream fos=new FileOutputStream("D:\\java\\b.txt",true); //字符串转字节数组 getByte() fos.write("abc".getBytes()); //换行 \r\n fos.write("\r\n换行了".getBytes()); //释放资源 fos.close(); } }
异常处理:
import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class Demo03 { public static void main(String[] args) { //处理异常:close必须执行所以放在finally里面, //但是设计fos定义问题,所以先在外面进行赋值定义 FileOutputStream fos=null; try { fos=new FileOutputStream("D:\\java\\b.txt",true); fos.write("abc".getBytes()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { fos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
2、字节输入流:InputStream
子类:FileInputStream文件输入流
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class Demo04 { public static void main(String[] args) throws IOException { //创建字节输入流(明确从哪个文件中读取数据) FileInputStream fis=new FileInputStream("D:\\java\\d.txt"); //读取一个字节 /*int len=fis.read(); System.out.println((char)len);//将字节的int类型强转成char类型 len=fis.read(); System.out.println((char)len);//将字节的int类型强转成char类型 len=fis.read(); System.out.println((char)len);//将字节的int类型强转成char类型 len=fis.read(); System.out.println((char)len);//将字节的int类型强转成char类型 len=fis.read(); System.out.println((char)len);//将字节的int类型强转成char类型 len=fis.read(); System.out.println(len);//一共5个字节,当读取到没有值的时候,返回len值为-1*/ //一个字节一个字节的读取文件所有数据 int len=0; while((len=fis.read())!=-1){ System.out.println((char)len); } //释放资源 fis.close(); } }
import java.io.FileInputStream; import java.io.IOException; public class Demo05 { public static void main(String[] args) throws IOException { //明确数据源 FileInputStream fis=new FileInputStream("D:\\java\\d.txt"); //创建字节数组 byte[] bytes=new byte[2]; /* //读取一个字节数组 int len= fis.read(bytes); //实际读取的有效字节数 System.out.println(len); //字节数组转字符串 System.out.println(new String(bytes));*/ //循环读取字节数组 int len=0; while((len=fis.read(bytes))!=-1){ System.out.println(new String(bytes,0,len));//从0开始 截取len个 } fis.close(); } }
3、复制文件:
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class Copy { public static void main(String[] args) throws IOException { //明确数据源 FileInputStream fis=new FileInputStream("D:\\java\\d.txt"); //明确目的地 FileOutputStream fos=new FileOutputStream("D:\\java\\e.txt"); //开始复制 int len=0; while((len=fis.read())!=-1){ fos.write(len); } //释放资源 fis.close(); fos.close(); } }
三、字符流:
1、字符流介绍:
对比字节流(可以操作任何数据)
①、字节流操作中文数据不是特别的方便,所以就出现了转换流;
转换流的作用就是把字节流转换字符流来使用;
②、转换流其实是一个字符流:
字符流 = 字节流 + 编码表
2、编码表:
①、ASCII表:一个字节中的7位就可以表示,对应的字节都是正数。
②、GBK:目前最常用的中文码表,2万的中文和符号。用两个字节表示,其中一部分文字,第一个字节开头是1,第二个字节开头是0;
③、unicode:国际标准编码表;无论是什么文字,都用两个字节存储:
char类型就是这个码表,占两个字节。
utf-8基于unicode,一个字节就可以存储数据,不要用两个字节存储,而且这个码表更加的标准化。
3、字符输入流:Reader
子类FileReader文件输入流
import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class Demo02 { public static void main(String[] args) throws IOException { //创建字符输入流 FileReader fr=new FileReader("D:\\java\\d.txt"); //创建字符数组 char[] ch=new char[1024]; //一个字符数组一个字符数组读 int len=0; while((len=fr.read(ch))!=-1){ System.out.println(new String(ch,0,len)); } //释放资源 fr.close(); } }
4、字符输出流:Writer
子类:FileWriter
import java.io.FileWriter; import java.io.IOException; public class Demo03 { public static void main(String[] args) throws IOException { //创建字符输出流 FileWriter fw=new FileWriter("D:\\java\\d.txt"); //写入一个字符 fw.write(100); fw.flush(); //写入一个字符串 fw.write("你好啊"); fw.flush(); //写入一个字符数组 char[] ch={'a','1','r'}; fw.write(ch); fw.flush(); //释放资源 fw.close(); } }
5、Flush()和close()的区别:
flush():将流中的缓冲区缓冲的数据刷新到目的地中,刷新后,流还可以继续使用。(写入一次就刷新一次,主要用于有可能数据过多的时候,以免承受不了)
close():关闭资源,但在关闭前会将缓冲区中的数据先刷新到目的地,否则丢失数据,然后在关闭流。流不可以使用。如果写入数据多,一定要一边写一边刷新,最后一次可以不刷新,由close完成刷新并关闭。
6、复制文件:
import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class Copy { public static void main(String[] args) throws IOException { //明确数据源 FileReader fr=new FileReader("D:\\java\\d.txt"); //明确目的地 FileWriter fw=new FileWriter("D:\\java\\d.txt"); //开始复制 int len=0; while((len=fr.read())!=-1){ fw.write(len); fw.flush(); } fr.close(); fw.close(); } }