黑马程序员---java之IO流(一)

java之IO流(一)
 
------- android培训java培训、期待与您交流! ----------

IO(Input   Output)流

.IO流用来处理设备之间的数据传输
.Java对数据的操作是通过流的方式
.Java用于操作流的对象都在IO包中
.流按操作数据分为两种:字节流和字符流
.流按方向分为:输入流和输出流

IO(Input   Output)流常用基类:

字节流的抽象基类:InputStream,OutputStream。
字符流的抽象基类:Reader,Writer。
注:由这4个类派生出来的子类名称都是以其父类名作为子类名的后缀。
         如:InputStream的子类FileInputStream
                  Reader的子类FileReader 

字符流---Writer

IO 流是用于操作数据的,最常见的体现形式是:文件
举例说明:
需求:在硬盘上,创建一个文件并写入一些文字数据。
首先找到一个专门用于操作文件的Writer子类对象,FileWriter,后缀名是父类名,前缀名是该流对象的功能

public static void main(String[] args) throws IOException {
          //创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件
 //而且该文件会被创建到指定的目录下,如果该目录下已有同名文件,将被覆盖
 //其实该步骤就是在明确数据要存放的具体位置
 FileWriter fw=new FileWriter("D://demo.txt");
 
 
 //调用write方法,将数据写入到流中
 fw.write("abcdef"); 
 
 //刷新流对象中的缓冲区中的数据
 // fw.flush();
 // fw.write("bbbbbbbbbb");
 // fw.flush();
 
 //关闭流资源,但是关闭之前会进行刷新一次内部的缓冲中的数据
 fw.close();
}


flush()和close()的区别:flush 刷新后,流可以继续使用,close刷新后,会将流关闭。

IO异常的处理方式

例如:
public static void main(String[] args) {
//声明文件对象
FileWriter fw=null;
try {
//创建文件夹
   fw = new FileWriter("D://demo.txt");
   //写入内容
fw.write("abcdef");

} catch (IOException e) {
System.out.println(e.toString());
}finally{
try {
//判断文件对象是否为空
if(fw!=null)
fw.close();//关闭流
} catch (IOException e) {
System.out.println(e.toString()); 
}
}

}



文件的续写

为了在创建文件时使原有的文件的文件不被覆盖,可以在创建文件的时候传递一个true参数,
代表不覆盖已有的文件,并在已有的文件末尾处进行数据续写

例如:  fw = new FileWriter("D://demo.txt",true);

如写入的内容需要换行则使用\r\n

例如:fw.write("Hello\r\nWord");

字符流---文本文件读取方式

第一种:读取单个字符read()
public static void main(String[] args) throws IOException {
//创建一个文件读取流对象,和指定名称的文件相关联
//要保证该文件是已经存在,如果不存在,会发生FileNotFoundException

FileReader fr=new FileReader("Demo.txt");
                 //调用读取流对象的read方法
                 //read():一次读一个字符,而且会自动往下读

int ch=0;
while((ch=fr.read())!=-1){

System.out.println((char)ch);
}
fr.close();

}

第二种:通过字符数组读取read(char[] )

public static void main(String[] args)throws IOException {
          FileReader fr=new FileReader("demo.txt");

         //定义一个字符数组,用于存储读到字符
          //该read(cahr[])返回的是读到的字符的个数
         char[] buf=new char[1024];
         int num=0;
         while((num=fr.read(buf))!=-1){
                     System.out.print(new String(buf,0,num));
        }
                        fr.close();
}


字符流---拷贝文本文件

需求:将C盘一个文本文件复制到d盘
原理:其实就是将c盘下的文件数据存储到d盘的一个文件中
步骤:1.在d盘创建一个文件,用于存储c盘文件中的数据
           2.定义读取流和c盘文件关联
           3.通过不断的读取完成数据存储
           4.关闭资源
public static void main(String[] args) {
FileWriter fw=null;
FileReader fr=null;
try {
fw=new FileWriter("拷贝的目的路径");
fr=new FileReader("读取文件的路径");
char[] buf=new char[1024];
int len=0;
while((len=fr.read(buf))!=-1){
fw.write(buf,0,len);
}
} catch (IOException e) {
throw new RuntimeException("读写失败");
}
finally{
   if(fr!=null)
try {
fr.close();
} catch (IOException e) {
throw new RuntimeException("读取关闭失败");
}
if(fw!=null)
try {
fw.close();
} catch (IOException e) {
throw new RuntimeException("写入关闭失败");
}
}
}

字符流的缓冲区


作用:缓冲区的出现提高了对数据的读写效率
对应类:BufferedWriter和BufferedReader
缓冲区的特点:要结合流才能使用,在流的基础上对流的功能进行了增强
              所以在创建缓冲区之前,必须先要有流对象。


BufferedWriter类(字符写入缓冲区)


newLine():该缓冲区中提供了一个跨平台的换行符,只有在缓冲区中才有。


public static void main(String[] args) throws IOException {

//创建了一个文件写入流对象
FileWriter fw=new FileWriter("demo.txt");

//为了提高字符写入流效率,加入了缓冲区技术
//只要将需要被提高的流对象作为参数传递给缓冲区的构造函数即可
BufferedWriter bufw=new BufferedWriter(fw);

for (int i = 1; i <= 3; i++) {
bufw.write("abc"+i);
bufw.newLine();
bufw.flush();//只要用到缓冲区就要记得刷新
}
bufw.close();  //其实关闭缓冲区就是在关闭缓冲区中的流对象,所以不需要fw.close().
}
输出结果为:
abc 1
abc 2
abc 3


BufferedReader类(字符读取缓冲区)


readLine():该缓冲区提供了一个一次读取一行的方法,方便于对文本数据的获取
            当返回null时,表示读到文件末尾,该方法返回的时候只返回回车符
            之前的数据内容,并不返回回车符。


public static void main(String[] args) throws IOException {
//创建一个读取流对象和文件相关联
FileReader fr=new FileReader("demo.txt");
//为了提高效率,加入缓冲技术,将字符读取流对象作为参数传递给缓冲对象的构造函数
BufferedReader bufr=new BufferedReader(fr);
String line=null;
while((line=bufr.readLine())!=null){
System.out.println(line);
}
bufr.close();
}


通过缓冲区复制一个java文件


public static void main(String[] args) {
BufferedReader bufr=null;
BufferedWriter bufw=null;
try {
bufr=new BufferedReader(new FileReader("要复制的文件路径"));
bufw=new BufferedWriter(new FileWriter("复制到指定的路径"));
String line=null;
while((line=bufr.readLine())!=null){
bufw.write(line);
bufw.newLine();
bufw.flush();
}
} catch (Exception e) {
throw new RuntimeException("读取失败");
}
finally{
try {
if(bufr!=null)
bufr.close();
} catch (IOException e) {
throw new RuntimeException("读取关闭失败");
}
try {
if(bufw!=null)
bufw.close();
} catch (IOException e) {
throw new RuntimeException("写入关闭失败");
}
}
}

字符流---自定义一个类中包含一个功能和readLine一致的方法

class MyBufferedReader{
private FileReader fr;
MyBufferedReader(FileReader fr){
this.fr=fr;
}
        
        //可以一次读一行数据的方法
public String myReaderLine() throws IOException{

                //定义一个临时容器,原BufferReader封装的是字符数组
StringBuilder sb=new StringBuilder();
int ch=0;
while((ch=fr.read())!=-1){
if(ch=='\r')
continue;
if(ch=='\n')
return sb.toString();
else
sb.append((char)ch);
}
if(sb.length()!=0)
return sb.toString();
return null;
}
public void myClose() throws IOException{
fr.close();
}
}


class Test{
public static void main(String[] args) throws IOException {
FileReader fr=new FileReader("读取的文件路径");
MyBufferedReader myBuf=new MyBufferedReader(fr);
String line=null;
while((line=myBuf.myReaderLine())!=null){
System.out.println(line);
}
myBuf.myClose();
}
}

装饰设计模式

装饰类概念:当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能
           并提供加强功能,那么自定义的该类称为装饰类

装饰类的作用:避免了继承体系的臃肿,降低了类与类之间的关系

装饰类的特点:通常会通过构造方法接收被装饰的类,并基于被装饰的对象的功能,提供更强的功能。
                         装饰类和被装饰类通常是在同一个体系中。

例如BufferedWriter和BufferedReader都是装饰类


字符流---LineNumberReader(设置行号,默认从零开始)

public static void main(String[] args)throws IOException {

          FileReader fr=new FileReader("读取文件的路径");

          LineNumberReader Inr=new LineNumberReader(fr);
         
          String line=null;

          Inr.setLineNumber(10);//设置行号从10开始

          while((line=Inr.readerLine())!=null){
                     //读取行号
                     System.Out.println(Inr.getLineNumber()+"--------"+line);
           }
           
          Inr.close();
}


模拟一个带行号的缓冲区对象

带注释的为另一种方式,不带的为优化方式,MyBufferedReader在前面的代码有
class MyLineNumberReader extends MyBufferedReader{
//private Reader r;
private int lineNumber;
MyLineNumberReader(Reader r){
//this.r=r;
super(r);
}
public String myReaderLine() throws IOException{
lineNumber++;
return super.myReaderLine();
/*StringBuilder sb=new StringBuilder();
int ch=0;
while((ch=r.read())!=-1){
if(ch=='\r')
continue;
if(ch=='\n')
return sb.toString();
else
sb.append((char)ch);
}
if(sb.length()!=0)
return sb.toString();
return null;*/
}
public void serLineNumber(int lineNumber){
this.lineNumber=lineNumber;
}
public int  getLineNumber(){
return lineNumber;
}
/*public void myClose() throws IOException{
r.close();
}*/
}
class Tset{

public static void main(String[] args) {
FileReader fr=new FileReader("读取的文件路径");
MyLineNumberReader myInr=new MyLineNumberReader(fr);
String line=null;
while((line=myInr.myReaderLine())!=null){
System.out.println(myInr.getLineNumber()+"-----"+line);
}
myInr.myClose();
}
}


字节流:InputStream   OutputStream
 
字节流读写操作例子:
/*
     * 写入操作
     */
    public static void writeFile() throws IOException{
     FileOutputStream fos=new FileOutputStream("写入存放的路径");
     fos.write("abcdef".getBytes());
     fos.close();
    }
    /*
     * 单个读取操作
     */
    public static void readFile1() throws IOException{
     FileInputStream fis=new FileInputStream("所要读取的路径");
     int ch=0;
     while((ch=fis.read())!=-1){
      System.out.println((char)ch);
     }
     fis.close();
    }
    /*
     * 多个读取操作
     */
    public static void readFile2() throws IOException{
     FileInputStream fis=new FileInputStream("所要读取的路径");
     byte[] buf=new byte[1024];
     int len=0;
     while((len=fis.read(buf))!=-1){
      System.out.println(new String(buf,0,len));
     }
     fis.close();
    }
    /*
     * 此方法同样可以操作多个,但是要慎用,因为当操作的数据过大时内存容易溢出
     */
    public static void readFile3() throws IOException{
     FileInputStream fis=new FileInputStream("所要读取的路径");
     byte[] buf=new byte[fis.available()];  //定义了一个刚刚好的缓冲区,不用在循环了。
     fis.read(buf);
     System.out.println(new String(buf));
     fis.close();
    }
    /*
  * 测试操作
  */
    public static void main(String[] args) throws IOException {
     writeFile();
     readFile2();
 }

 

复制一个图片的例子

思路:

1.用字节读取流对象和图片关联

2.用字节写入流对象创建一个图片文件,用于存储获取到的图片数据

3.通过循环读写,完成数据的存储

4关闭资源

public static void main(String[] args) {
  FileOutputStream fos = null;
  FileInputStream fis = null;
  try {
   fos = new FileOutputStream("复制到指定的路径");
   fis = new FileInputStream("读取文件所在的路径");
   byte[] buf = new byte[1024];
   int len = 0;
   while ((len = fis.read(buf))!= -1) {
                System.out.println(new String(buf,0,len));
   }
  } catch (IOException e) {
   throw new RuntimeException("复制文件失败");
  }
  finally{
   try {
    if(fis!=null)
    fis.close();
   } catch (IOException e) {
    throw new RuntimeException("读取文件失败");
   }
   try {
    if(fos!=null)
    fos.close();
   } catch (IOException e) {
    throw new RuntimeException("写入文件失败");
   }
  }
  

字节流的缓冲区

BufferedInputStream

BufferedOutputStream

/*
  * 通过字节流缓冲区完成复制
  */
 public static void main(String[] args) throws IOException {
  BufferedInputStream bufis=new BufferedInputStream(new FileInputStream("读取文件所在的路径"));
  BufferedOutputStream bufos=new BufferedOutputStream(new FileOutputStream("复制到指定的路径"));
  int by=-0;
  while((by=bufis.read())!=-1){
   bufos.write(by);
  }
  bufis.close();
  bufos.close();
 }

自定义字节流的缓冲区---read和write的特点

class MyBufferedInputStream{
  private InputStream in;
  private byte[] buf=new byte[1024*4];
  private int pos=0,count=0;
  MyBufferedInputStream(InputStream in){
   this.in=in;
  }
  //一次读一个字节,从缓冲区(字符数组)获取
  public int myRead()throws IOException{
   if(count==0){
    count=in.read(buf);
    if(count<0){
     return -1;
    }
    pos=0;
    byte b=buf[pos];
    count--;
    pos++;
    return b&255;//255的16进制形式0xff.
   }else if(count>0){
    byte b=buf[pos];
    count--;
    pos++;
    return b;
   }
   return -1;
  }
  public void myColse() throws IOException{
   in.close();
  }
 }

 

读取键盘录入(读取转化流,字节流转换为字符流)

/*
  * System.out:对应的是标准输出设备,控制台
  * System.in:对应的是标准输入设备,键盘
  */
 public static void main(String[] args) throws IOException {
  //获取键盘录入对象
  InputStream in=System.in;
  //将字节流对象转成字符流对象,使用转换流,InputStreamReader
  InputStreamReader isr=new InputStreamReader(in);
  //为了提高效率,将字符串进行缓冲区技术高效操作,使用BufferedReader
  BufferedReader bufr=new BufferedReader(isr);
  String line=null;
  while((line=bufr.readLine())!=null){
   if("over".equals(line)){
    break;
   }
   //把字符串转换为大写
   System.out.println(line.toUpperCase());
  }
  bufr.close();
 }

读取键盘录入(写入转化流,字符流转换为字节流)

 

/*
  * System.out:对应的是标准输出设备,控制台
  * System.in:对应的是标准输入设备,键盘
  */
 public static void main(String[] args) throws IOException {
  //获取键盘录入对象
  InputStream in=System.in;
  //将字节流对象转成字符流对象,使用转换流,InputStreamReader
  InputStreamReader isr=new InputStreamReader(in);
  //为了提高效率,将字符串进行缓冲区技术高效操作,使用BufferedReader
  BufferedReader bufr=new BufferedReader(isr);

  OutputStream out=System.out;

  OutputStreamWriter osw=new OutputStreamWriter(out);

  BufferedWriter bufw=new BufferedWriter(osw);


  String line=null;
  while((line=bufr.readLine())!=null){
   if("over".equals(line)){
    break;
   }
   //把字符串转换为大写
  bufw.write(line.toUpperCase());

  bufw.flush();

  }
  bufr.close();
 }

 

转换时优化代码

//键盘录入的最常见写法

BufferedReader  bufr=new BufferedReader(new InputStreamReader(System.in));

BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out));

 

 
 
 
 
 
 
------- android培训java培训、期待与您交流! ----------
 
 
 
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值