黑马程序员:IO流学习

来源:互联网 发布:计步器软件免费下载 编辑:程序博客网 时间:2024/06/08 17:11

------- android培训java培训期待与您交流! ---------- 

IO流(概述)

 1.IO(Input Output)流

  1)IO流用来处理设备之间的数据传输
  2)java对数据的操作是通过流的方式
  3)java且用于操作流的对象都在IO包中
  

什么时候使用字符流:
用记事本能够打开的看的懂的,就用字符流
一般我们说的IO流的分类,是按照操作数据类型不同划分
字节流的抽象基类:
InputStream:字节流输入流
OutputStream:字节输出流
字符流的抽象基类
Reader :字符输入流
Writer:字符输出流
特点:
都是以父亲作为后缀
需求
   我们往文本文件写入一句话:hello,io,我来了
   通过分析,我们发现,我们需要学联Writer了
   但是,writer是一个抽象类的,所以我们需要使用它的儿子:FileWriter
   FileWtriter的构造 方法:
      FileWriter(File file);
      FileWriter(String fileName);
    public void write(String str):字入一个字符串的数据
    用字符输出流写入数据的步骤:
    1、创建字符输出流对象
     这个步骤做了哪些事情? 
    2、调用对象的写方法
       public void write(String str)
    3、释放资源
为什么要释放资源?
既然释放资源对结果没有影响,那么,为什要需要释放资源这个步骤呢?
   原因有二:其一是:让这个流对象本身是个垃圾,可以被回收,提高效率
     其二是:通过操作系统释放管现fw.txt文件的资源

flush()和close()的区别?
   flush():刷新缓冲区,流对象还可以继续使用
   close():刷新缓冲区,关闭流对象。流对象不可以继续使用



public static void main(String[] args)
{
//创建字符流输出流对象,这个步骤做了哪些事情?
FileWriter fw=new FileWriter("fw.txt");
/*
  1、创建了fw对象
  2、底层调用了操作系统的资源创建了一个fw.txt文件
  3、把fw对象指向fw.txt文件
*/
//调用对象的写方法
fw.write("hello,io,我来了");
/*
  字符流对象写入数据的时候,最小单位是字符
  而数据操作的最基本单位是字节
  字符=2字节
  这就是一缓冲区概念,把2个字节数据放到缓冲区形成一个字符数据 
*/
 //刷新缓冲区
 fw.flush();
 //释放资源,关闭之前,会自动去调用flush方法
 fw.close();  
在进行字符流或字节流操作的时候,需要进行异常的处理
}
FileWriter写入数据的小问题:
1、如何数据的追加写入?
FileWriter(String fileName,boolean append):
使用带两个参数的构造,第二个参数表示是追加写入
默认是false,就会重头开始写入
如果是true,就会追加写入
2、数据如何换行?
不同的软件,换行的标准可能不一样
有些软件,可以识别常见的换行标识都是可以的
比如说:editplus Eclipse自带的文件打开方式。
在windows中换行是\r\n.而记事本是windows自带的软件。所以,它识别的换行只能是\r\n
linux:\n
mac:\r
例 :
public static void main(String[] args)
{
//创建字符输出流对象
 FileWriter fw=new FileWriter("a.txt");
 //调用writer方法
 for(int x=0;x<4;x++)
 {
  fw.write(x+"hello\r\n");
 }
 //释放资源
 fw.close();
}
--------------------Reader(读取数据)
   FileReader
   public int read():一次读取一个字符
 1、字符输入流对象
 2、调用字符输入流对象的读取方法,并显示出来
 3、释放资源
例:方式一:
public static void main(String[] args) throws IOException
{
//创建字符输入流对象
FileReader fr=new FileReader("a.txt");
做了几件事情:
1:创建fr对象
2、找到fw.txt文件
3、把fw对象指向fw.txt文件
注意:读取的时候,文件一定要存在。不然会报异常:
java.io.FileNotFoundException: fw5.txt (系统找不到指定的文件。)
/*
//调用字符输入流对象的读取方法,并显示出来
int num = fr.read();
System.out.println("num:"+num);
System.out.println("num:"+(char)num);
//我们发现了,read()方法可以自动从头开始读取,每次回自动移到下一个位置。
//并且我们发现,代码的重复度很高,所以,考虑使用循环,但是,问题来了,循环的结束条件我不知道
int num4 = fr.read();
System.out.println("num4:"+num4);
System.out.println("num4:"+(char)num4);
//通过测试,我们发现,当没有数据的时候,我们在读取的时候,将返回-1
//所以,我们就可以使用-1作为判断结束条件。
*/
/*
int num = fr.read();
while(num!=-1){
System.out.print((char)num);
num = fr.read(); //再次读取
}
*/
//开发中改进
int num = 0;
while((num=fr.read())!=-1){
System.out.print((char)num);
}

//释放资源
fr.close();
例:方式二:
  public static void main(String[] args)
  {
    //创建字符输入流对象
    FileReader fr=new FileReader("a.txt");
    //调用对象的方法 
     //定义一个字符数组
     char[] chs=new char[1024];//开发中使用
     // 读取数据 定义一个数组,但是这个数组的大小不好确定。
//char[] chs = new char[4];
//int len = fr.read(chs);
// 重新给len赋值
//System.out.println("***************************");
len = fr.read(chs);
//System.out.println("chs:" + Arrays.toString(chs));
System.out.print(String.copyValueOf(chs));
//System.out.println("len:" + len);
//发现代码重复度很高,需要找一个循环结束条件。
//意思就是说:当没有数据的时候,实际读取长度为-1.所以,len不是数组的长度,
而是实际读取数据的长度。
*/
// 读取数据 定义一个数组,但是这个数组的大小不好确定。
/*
char[] chs = new char[5];
int len = fr.read(chs);
while(len!=-1){
//chs,0,len的做法对最后一次读取数据不足有效。
System.out.print(String.copyValueOf(chs,0,len));
len = fr.read(chs);
}
*/
//开发写法
//数组的长度定义为多大呢?一般来说是1024的整数倍。
//1T = 1024 G
//1G = 1024 M
//1M = 1024 K
//1K = 1024 byte
//1byte = 8bit
char[] chs = new char[1024]; //2k
int len = 0;
while((len=fr.read(chs))!=-1){
System.out.print(String.copyValueOf(chs,0,len));
}
// 释放资源
fr.close();
  }
例:
   复制文本文件:
     思路:
       源文本文件(D:\\ddd):--读取数据----文件用txt打开是可以看的懂的---字符流----Reader---FileReader
       目标文件:(F:\\ JJ):---写入数据---字符流----Writer----FileWriter
       public static void main(String[] args)
       {
          //创建字符输入流对象
 FileReader fr=new FileReader("d:\\ddd");
 //创建字符输出流对象
 FileWriter fw=new FileWriter();
 //调用对象方法
 //方式一:
 //从数据源读取数据
 int num=0;
 while((num=fr.read())!=-1)
 {
   //把数据写入到文本文件
   fw.write(num);
 }
 //方式二:
 //定义数组
 char[] chs=new char[1024];
 int len=0;
 while((len=fr.read(chs))!=-1)
 {
    fw.write(chs,0,len);
 }
       }
------------------------------BufferedWriter
带缓冲区的输入输出流类
  字符缓冲输入流:BufferedReader
  字符缓冲输出流:BufferedWriter
BufferedWriter(Writer out)
为什么要传入一个Writer 呢?
缓冲区类,只提供缓冲区,不能直接读写文件,需要传递一个基本读写文件的对象
喝水:水龙头有水,你可以把嘴放上去喝。
        不文雅,不方便,不卫生,我就来一个缓冲区,水杯。用水杯接水,然后喝。
 假如水杯有了,但是没有水,有用吗?
 步骤:
1、创建字符缓冲输出流对象
2、调用该对象的写方法
3、释放资源
例:
    需求:往文本文件写入一句话
    public static void main(String[] args)
    {
    //创建字符缓冲输出流对象
    FileWriter fw=new FileWriter("bw.txt"); //真正的读写操作
    BufferedWriter bw=new BufferedWriter(fw); //缓冲区类
    //简化方式
      BufferedWriter bw=new BufferedWriter(new FileWriter("b.txt"));
      //写数据
      bw.write("hello");
      bw.flush();
      //释放资源
      bw.close();
      // fw.close(); 因为bw的关闭其实就是fw的关闭
    }
-----------------------------BufferedReader
字符缓冲输入流读取数据:
A:一次读取一个字符
B:一次读取一个字符数组
public static void main(String[] args)
{
//创建字符缓冲输入对象
BufferedReader br=new BufferedReader(new FileReader(bw.txt));
//读取数据
  方式一:
    int num=0;
    while((num=br.read())!=-1)
    {
    System.out.println((char)num);
    }
    方式二:
     char[] chs=new char[1024];
     int len=0;
     while((len=br.read(chs)!=-1)
     {
System.out.print(String.copyValueOf(chs,0.len));
     }
     br.close();
}
当两个种方式都写在程序里面时,只能使用一种方式。别外一个方式需要注释掉了
 因当一种方式进行read()操作后,指针已经指到最后一位了。如果在进行另外一种方式进行read操作
 那显示在控制台上面的将会什么都不会显示
 字符高效缓冲流的特殊方式:
  BufferedReader
public String readLine():根据行结束符读取一行数据,并把该行数据(不包括结束符)作为一个字符串返回
BufferedWriter
public void newLine();写入一个行分割符,可以识别不同的系统。写入不同的分割符
例:
public static void main(String[] args)throws IOException
{
 //创建字符缓冲输出流对象
BufferedWriter bw=new BufferWriter(new FileWriter("bw2.txt"))
//写入数据
for(int x=0;x<10;x++)
{
bw.write("hello"+x)
bw.newLine();//换行
}
bw.close();
//创建字符缓冲输入流对象
BufferedrReader br=new BufferedReader(new FileReader("bw2.txt"));
String line=null;
while((line=br.readLine())!=null)
{
System.out.println(line);
}
br.close();
}

复制文本文件:使用高效流实现
 使用高效流,我有三种方式;
 A:读取一个字符:read();
 B:读取一个字符数组 : read(char[] ch);
 C:读取一个字符串 :  readLine();
思路:
源文件:“D:\\java”----如果用记事本打开可以看的懂的就用---字符流---Reader----FileReader----BufferedReader
目标文件:“G:\\test”--- 字符流-----Writer----FileWriter----BufferedWriter
public static void main(String[] args)
{
  //创建字符输入流对像(封装源文件路径)
  BufferedReader br=new BufferReader(new FileReader("d:\\java"));
  //创建字符输出流对象(封装目标文件路径)
  BufferedWriter bw=new BufferWriter(new FileWriter("G:\\test"));
  //读取数据
     String len=null;
     while((len=br.readLine())!=null)
     {
     //把数据写入文本文件中
       bw.write(len);
       bw.newLine(); //换行
       bw.flush(); //刷新缓冲区
     }
     //释放资源
     bw.close();
     br.close();
}
从程序 的角度:显示就用writer 就是输出流:就像打印机
               存储就是reader 就是输入流:就打扫描仪
      当要程序进行文件的复制功能时,那么源文件就是Reader()功能,先把已知的件先读取出来,把
      目标文件(通过Wtriter()功能)。把源文件里面的内容写进目标文件中
JDK7的新特性:
 * catch()里面的异常类,可以用|隔开,也就是说,一个catch可以捕获多个异常了。
 * 注意:可以使用|隔开的异常是平级的。
 * catch (NullPointerException | ArithmeticException e) {
e.printStackTrace();
}
如果有子父关系,建议使用一个try,多个catch的情况。
如果是平级关系,建议使用JDK7的新特性,就是一个catch可以写多个异常类名,用|隔开


------- android培训java培训期待与您交流! ----------