黑马程序员----IO流

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

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


字节流的抽象基类:
inputstream  和 OutputStream;
字符流的抽象基类:
Reader 和 Writer




字符流的特点:



数据最常见的体现形式是:文件


需求:在硬盘上,创建一个文件,并写入一些文字数据。


用于操作操作文件的Writer的子类FileWriter,后缀名是父类名。前缀名是该流对象的功能。
操作步骤:
1.创建一个FileWriter对象。该对象一被初始化就必须明确要被操作的文件,该文件会被创建到指定目录下,如果该目录下已经有同名文件,将被覆盖
FileWriter fw=new FileWriter("demo.txt");
2.调用write方法,将字符串写入到流中。
fw.write();
3.刷新流对象中的缓冲中的数据,将数据刷到目的地
fw.flush();
4.关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据,将数据刷到目的地中。和flush的区别,flush刷新后,流可以继续使用,close刷新后
将会将流关闭。
fw.close();




IO异常的处理方式:


FileWriter fw=null;

try {
fw=new FileWriter("demo.txt");
fw.write("sdfasd");
} catch (IOException e) {
e.printStackTrace();
}finally{

try {
if(fw!=null)
fw.close();
} catch (IOException e) {

e.printStackTrace();
}

}
}



文件的续写:
传递一个true参数,代表不覆盖已有文件,并在已知文件的末尾处进行数据续写。
FileWriter fw=new FileWriter("demo.txt",true);
换行转义字符:\r\n


文件的读取方式一:
FileReader();



1.创建一个FileReader对象。文件读取流对象,和指定名称的文件相关联,要保证该文件是已经存在的,如果不存在会发生异常
FileReader fr=new FileReader("demo.txt");
2.调用读取流的对象的read方法
    (1)int ch=fr.read();一次读一个字符,会自动往下读。
    (2)读出所有字符 
     while((ch=fr.read())!=-1)
    {
        System.out.println((char)ch);
     }


3.关闭流资源,
fr.close();



文件的读取方式2:通过字符数组进行读取
1.创建一个FileReader对象。文件读取流对象,和指定名称的文件相关联,要保证该文件是已经存在的,如果不存在会发生异常
FileReader fr=new FileReader("demo.txt");
2.定一个字符数组,用于存储读到字符,该rrad(char[])返回的是读到的字符个数。
char[] buf=new char[1024];一般定义1024-2个字节。
    int num=0;
     while((num=fr.read(buf))!=-1)
    {
        System.out.println((new String(buf,0,num));
     }
练习 :读取一个.java文件。并打印在控制台上。
FileReader fr=null;
char[] buf=new char[1024];
int num=0;
try {
fr= new FileReader("a.txt");

try {
while((num=fr.read(buf))!=-1){
System.out.print(new String(buf,0,num));
}
} catch (IOException e) {

e.printStackTrace();
}



} catch (FileNotFoundException e) {

e.printStackTrace();
}
finally
{
  try {
                               if(fr!=null)
fr.close();
} catch (IOException e) {

e.printStackTrace();
}
}


练习2:将C盘的一个文本文件拷贝到D盘(数组相当于存储之中的媒介)
步骤:新建一个文件用于存储要被拷贝的文件
2.定义读取流和源文件关联
3.通不过不断读写完成数据存储
4.关闭资源


        FileWriter fw=null;
 FileReader fr=null;
 try {
 fw=new FileWriter("b.txt");
 fr=new FileReader("a.txt");
 char[] buf=new char[1024];
 int num=0;
 while ((num=fr.read(buf))!=-1){
 fw.write(buf,0,num);
 }
}
 catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
 finally
{
  try {
fr.close();
} catch (IOException e) {

e.printStackTrace();
}
  
  try {
fw.close();
} catch (IOException e) {

e.printStackTrace();
}
}


 字符流的缓冲区
缓冲区的出现提高了对数据的读写效率
对应类:
BUfferWriter
BufferedReader
特点:缓冲区要结合流才可以使用,在创建缓冲区之前,必须要有流对象。在流的基础上对流的功能进行了增强。
BUfferWriter步骤:
1.创建一个字符写入流对象
FileWriter fw=new FileWriter("a.txt");
2.将需要被提高效率的流对象作为参数传递给缓冲区的构造函数
bufferedWriter bufw=new BufferedWriter(fw);
buff.write("asdasdas");
bufw.newLine();//换行符,跨平台的
3.将缓冲区刷新
bufw.flush;
4.关闭缓冲区,就是在关闭缓冲区中的流对象
bufw.close();




BufferedReader步骤
1.创建一个字符写入流对象
FileReader fr=new FileReader ("a.txt");
2.将需要被提高效率的流对象作为参数传递给缓冲区的构造函数
BufferedReader bufr=new BufferedReader (fr);
3.读取流对象:该缓冲区提供了一个一次读取一行的方法。当返回null时表示,文件读到末尾
String line=null;
while((line=bufr.readLine())!=null)
{
String s=line;}
4.关闭
bufr.close();




readLine()方法的原理:
无论是读一行,获取多个字符,最终都是在硬盘上一个一个读取,最终使用额还是read方法一次读一个的方法。
缓冲区练习.:通过缓冲区复制一个文件


    BufferWriter bufw=null;
BufferReader bufr=null;
 try {
 bufw=new BufferWriter(new FileWriter("b.txt"));
 bufr=new BufferReader(new FileReader("a.txt"));
String line=null;
 while ((line=buffr.read(buf))!=null){
 bufw.write(line);
                    bufw.newLine();
                    bufw.flsuh;
 }
}
 catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
 finally
{
  try {
fr.close();
} catch (IOException e) {

e.printStackTrace();
}
  
  try {
fw.close();
} catch (IOException e) {

e.printStackTrace();
}
}






自定义一个功能和readline一致的方法,来模拟下BufferedReader();




public class MyBufferedReader extends Reader {

private Reader r;



    public MyBufferedReader(Reader r) {
super();
this.r = r;
}




//可以一次读取一行的方法
public String myReadLine() throws IOException
{
//定义一个临时容器。StringBulider容器,应用于存储字符数组
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;
}


             //
}






装饰设计模式


当想要对已有的独享进行功能增强时,可以定义类,将已有的对象传入,基于已经有的功能,
并提供加强功能,那么自定义的该类称为装饰类
装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。


代码演示:
已知类:
Person()
{
  public void chifan()
   {
    }
}
增强类:
superPerson()
{
   private Person p;
   superPerson(Person p)
   {
     this.p=p;
    }
   
    public void superchifan()
    {
      p.chifan();
      .........
    {
}


自定义装饰类


package com.io;
import java.io.*;
public class MyBufferedReader  {

private Reader r;



    public MyBufferedReader(Reader r) {
super();
this.r = r;
}




//可以一次读取一行的方法
public String myReadLine() throws IOException
{
//定义一个临时容器。StringBulider容器,应用于存储字符数组
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;
}

//复写reader中的抽象方法
//复写close方法
public  void  close() throws IOException
{
r.close();
}
//复写read方法
public int read (char[] c,int off,int len) throws IOException{

return r.read(c, off, len);
}
}






带有行号的缓冲区:
LineNumberReader lnr=new LineNumberReader();


获取行号:lnr.getLineNumber();
设置行号从几开始:lnr.setLineNumber(100);


LineNumberReader 步骤
1.创建一个字符写入流对象
FileReader fr=new FileReader ("a.txt");
2.将需要被提高效率的流对象作为参数传递给缓冲区的构造函数
LineNumberReader lnfr=new LineNumberReader (fr);
3.读取流对象:该缓冲区提供了一个一次读取一行的方法。当返回null时表示,文件读到末尾
String line=null;
while((line=lnfr.readLine())!=null)
{
String s=line;
String linenum=lnfr.getLineNumber();
}
4.关闭
lnfr.close();




自定义带行号的MyLineNumber;


public class MyLineBufferReader extends MyBufferedReader {


public MyLineBufferReader(Reader r) {
super(r);

}

private int LineNumber;


public int getLineNumber() {
return LineNumber;
}


public void setLineNumber(int lineNumber) {
LineNumber = lineNumber;
}

public String myReadLine() throws IOException
{
LineNumber++;
return super.myReadLine();
}


}






操作图片数据就要用到字节流。
字符流使用的是字符数组char[],字节流使用的是字节数组byte[]。
字节流:
InputStream 读
Outputstream 写


读取
FileInputStream fis=new FileInputStream ("a.txt");
byte[] buf=new byte[fis].available(0)];//定义一个刚刚好的缓冲区,不用再循环了
fis.read(buf);
System.out.println(new String(buf));
fis.close();


练习:复制图片


        FileOutputStream fw=null;
 FileInputStream fr=null;
 try {
 fos=new FileOutputStream("b.jpg");
 fis=new FileInputStream("a.jpg");
 byte[] buf=new byte[1024];
 int num=0;
 while ((num=fis.read(buf))!=-1){
fis.write(buf,0,num);
 }
}
 catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
 finally
{
  try {
                      if(fis!=null)
fis.close();
} catch (IOException e) {

e.printStackTrace();
}
  
  try {
fos.close();
} catch (IOException e) {

e.printStackTrace();
}
}




日常的日志信息和系统信息


使用printStream();


输出到控制台:


System.SetOut(new PrintStream("sysinfo.txt"))
e.printStackTrace(System.out);


上面这两句就相当于
e.printStackTrace(new PrintStream("sysinfo.txt"));//将日志文件打印到文件中




获取系统信息:
 Properties prop =System.getProperties();
prop.list(System.out);//打印到控制台
prop.list(new PrintStream("sysinfo.txt"));//打印到文件中




字节流的缓冲区


通过字节流的缓冲区复制MP3


BufferedOutputStream
BufferedInputStream


源码:
BufferedInputStream bufis=new BufferedInputStream(new FileInputStream("a.txt"));
BufferedOutputStream bufos=new BufferedOutputStream(new FileOutputStream("b.txt"));

int len=0;
while((len=bufis.read())!=-1){
bufos.write(len);
}


自定义字节流缓冲区:


读取键盘录入


System.out:对应的是标准输出设备,控制台
System.in:对应的标准输入设备,键盘


代码 
InputStream in=System.in;
  int by=in.read();
   sop(by);
结束录入 


  in.close();




转换流


读取转换流:InputStreamReader
写入转换流:OutputStreamReader




读取转换流:InputStreamReader 字节流通向字符流的桥梁


步骤 
1.获取键盘录入对象
Inputstream in=System.in
2.将字节流对象转换成字符流对象,使用转换流InputStreamReader 
InputStreamReader isr=new InputStreamReader(in);
3.提高效率使用字符流缓冲区 BufferedReader进行读取
BufferedReader bf=new BufferedReader(is);
String line=null;
while((line=bf.readLine())!=null)
{
    if("over".equals(line))
     break;
    sop(line);
}
bufr.close;






写入转换流:OutputStreamReader 字符流通向字节流的桥梁


步骤 
1.获取输出对象
Outputstream out=System.out
2.将字符流对象转换成字节流对象,使用转换流OutputstreamWriter 
OutputstreamWriter osw=new OutputstreamWriter(out);
3.提高效率使用字符流缓冲区 BufferedWriter进行写入
BufferedWriter bw=new BufferedWriter(osw);
String line=null;
while((line=bf.readLine())!=null)
{
    if("over".equals(line))
     break;
    bw.write(line);
    bufw.newLine();
}
bufr.close;




流操作基本规律:
两个明确:
1.明确源和目的


   源:输入流。InputStream字节流  Reader 字符流
   目的:输出流 OutPutStream 字节流  Writer 字符流
 2.操作的数据是否是纯文本


   是 就是字符流 如果设备是键盘 就将字节流转换为字符流
   不是 就是 字节流



3.当体系明确后,在明确要是用那个具体的对象
  
    通过设备来区分 
     源设备  内存 硬盘 键盘
     目的设备  内存  硬盘  控制台


4.是否需要提高效率  是 BufferedReader  BufferedInputStream
                   否 BuffreredWriter BufferedOutputStream
 


案例分析 :


1.将一个文本文件中的数据存储到另一个文件中,复制文件
 
  源: InputStream字节流  Reader 字符流
  是否是纯文本 是  Reader
   设备: 文件   操作文件的对象 就是FileReader
  是否需要高效 
  是  BufferedReader
   FileReader fr=new FileReader("a.txt");
   BufferedReader bufr=new BufferedReader(fr);
  
 目的   OutPutStream 字节流  Writer 字符流
 是否是纯文本 :是 Writer 
 设备: 文件 写入文件的对象 就是 FileWriter 
 是否需要高效  是   BufferedWriter


  FileWriter fw=new FileWriter("b.txt");
   BufferedWriter bufw=new BufferedWriter(fw);




2.将一个图片文件数据存储到另一个文件中,复制文件。


分析
源:
 是否是纯文本 : 不是  InputStream
 设备 文件 就是 FileInputStream
  是否高效 是
 BufferedInputStream
  
   FileInputStream isr=new FileInputStream("a.jpg");
    BufferedInputStream bufis=new BufferedInputStream(isr);
目的
  是否纯文本 :不是 OutPutStream
  设备:文件 FileOutPutStream
是否高效 是
 BufferedOutputStream
 FileOutPutStream osw=new FileOutPutStream("b.jpg");
    BufferedOutputStream bufos=new BufferedOutputStream(osw);


3.需求将键盘录入的数据保存到一个文件中 。


 源:键盘  字节流 
  是否纯文本  Reader
  设备 :键盘  ,对应的对象时 System.in 对应的是字节流 ,为了操作方便 转成字符流
  既然明确了Reader 就将System.in 转换成字符流 InputStreamReader
  
  InputStreamReader isr=new InputStreamReader(System.in);


  需要高效吗 ?
 
  BufferedReader bufr=new BufferedReader(isr);


  目的: 文件
   是否纯文本 是  Writer
   设备:文件 FileWriter
   需要高效吗?
   是 BufferedWriter
 
4.扩展 :想要吧录入的数据按照指定的编码表(utf-8)将数据存到文件中
   目的:OutPutStream 字节流  Writer 字符流
   是否是存文本:是  Writer
   设备 :文件 fileWriter
   默认编码表是 gbk
   编码标只有转换流可以指定。所以要使用的对象是写入转换流 OutputStreamWriter
   转换流需要接受一个自己输出流,操作字节输出流的是FileOutputStream
   OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("b.txt"),"utf-8");
  BufferedWriter bufw=new BufferedWriter (osw);


通常涉及到字符编码转换的时候,就需要用到转换流。



 
  
File类


创建File对象,
1.File f=new File("c:\\abc\a.txt");//将a.txt封装成FIle对象,可以将已有的和未出现的文件或者文件夹封装成对象。
2.File f=new File("c:\\abc","a.txt"); 第一个参数代表的是目录,第二个参数代表的是目录下的文件。
3.file d=new File("c\\abc"); 将路径封装成对象
  File f=new File(d,"a.txt"); 调用路径对象




f代表的是文件路径


目录分隔符:\\
File.separator 


常见方法:
1.创建
  boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false
                          和写入流不一样,写入流创建文件会覆盖已经存在的文件。
  案例 :
   File f=new File("a.txt");
   f.createNewFile();
   创建一级目录 
   File dir=new File("abc");
   dir.mkdir();
   创建多级目录
   dir.mkdirs();


2.删除
   boolean f.delete(); 删除失败,返回false,可能不能删除
   void deleteOnExit();在程序退出时,删除指定文件。必须删除。不会失败


3.判断 :在判断文件对象是都是文件或者目的时候,必须要先判断该文件对象封装的内容是否存在。
   File f=new File("a.txt");
   f.canExecute();是否能执行。
   f.exits();返回boolean  文件是否存在
   是否是目录 
   f.isDirectory();
   是否是文件
   f.isFile();
   是否是隐藏的
   f.isHidden();
   是否是绝对路径
   f.isAbsolute();


4.获取信息。
   getName()   //获取名称
   getpath()    //获取路径
   getAbsolutePath() //获取绝对路径 
   getParent() //获取绝对路径下的父路径,如果获取的是相对路径返回null,如果相对路径中由上一级目录,该目录就是结果。
   lastModified()//获取最后一次修改时间
   length();//获取体积大小
5.其他
   renameTo();改名,重命名,如果修改路径的话,同时路径也会修改
   f1.renameTo(f2);
   




    listRoots();返回 File 数组,列出可用的文件系统根(盘符) 
   例子:
    File[] files=File.listRoots();
     for(File f: files)
     {
               sop(f)
     }






     list():返回当前目录下所有文件,包括子目录
     File f=new File("abc");


     String[] namess=f.list();//调用list方法的file对象必须封装了一个目录,把那个目录必须存在
     for(String f: names)
     {
               sop(f)
     }






    显示.bmp结尾的文件
      list(FilenameFilter Filter) 返回String[]  指定目录中满足制定过滤器的文件和目录
       File dir=new File("abc");


     String[] namess=f.list(new FilenameFileter()


           public boolean accept(File dir,String name)
               {
                  return name.endsWith(".bmp");
                  }
     );/
     for(String f: names)
     {
               sop(f);
     }


     
     listFiles();返回当前路径下的文件对象。(不包括子目录)
      
     FIle dir=new File("c:\\"); 
     File[] files=dir.listFiles();
     for(File f : files)
      {
          sop (f.getname())
      } 
      
    


列出指定目录下所有内容:使用递归 。。函数自己调用自己


     File dir=new File("d:\\");
     sop(dir);
     File[]  files=dir.listFiles();
     for(int x=0;x<files.length;x++)
      {
         if(files[x].isDirectory)
            showDir(files[x]);
         else
            System.out.println(files[x]);
      }






         
删除一个带内容的目录:


原理:从里面往外删除,就需要递归
 File dir=new File("d:\\");
File[] files=dr.listFiles();
for(int x=0;x<files.length;x++)
{
   if(files[x].isDirectory())
    removeDir(files[x]);
  
    sop(files[x].toString()+":-file-:"+files[x].delete(););
}
sop(dir+":-dir-:"+dir.delete();)




练习:讲一个指定目录下的jva文件的绝对路径,存储到一个文本文件中。
思路:
1.对指定目录进行递归
2.获取递归过程中所有以JAVA文件的路径
3.将这些目录存储到集合中,将集合中的数据写入到一个文件中。




Properties集合:是hashtable的子类,具备map集合的特点,里面存储的键值对都是字符串。,,,文件流和 键值对相结合 就用此集合
是集合中和IO技术相结合的集合容器
该对象的特点:可以用于键值对形式的配置文件,可以操作键盘的数据。
//设置和获取元素。


   Properties prop =new Properties();
   prop.setProperty("张三","30");//添加,修改
   sop(prop);
   prop.getProperty("键");


   循环获取
   Set<String> names=prop.stringPropertyNames();
   for(String s : names)
     {
           prop.getProperty(s);
     }




Properties存取配置文件,将文本a.txt中的数据存到集合中进行操作。


步骤:1.用一个六和info.txt关联
2.读取一行数据,用该行数据用"="尽情切割
2.封号左边作为建,右边作为值,存储到Properties集合中即可




BufferedReader bufr=new BufferedReader(new FileReader("a.txt"));
String line=null;
Properties prop =new Propertites();
while((line=bufr.readLine())!=null)
{
   String[] arr =line.split("=");
   prop.setProperty(arr[0],arr[1]);
}


简便方法
Properties prop =new Propertites();
FileInputStream fis=new FileInputStream("a.txt");
//将流中的数据加载进集合
prop.load(fis);
prop.list(System.out);






练习,用于记录应用程序运行次数,如果使用次数已经到,就给出注册提示。


Properties prop=new Properties();

File file=new File ("count.ini");
if(!file.exists())
 file.createNewFile();
 
FileInputStream fis=new FileInputStream(file);
prop.load(fis);
 
int count=0;
String value=prop.getProperty("time");
if(value!=null)
{
count=Integer.parseInt(value);
if(count>=5)
{
System.out.println("您使用的次数已到");
return;
}
}
         count++;
         prop.setProperty("time", count+"");
         FileOutputStream fos=new FileOutputStream(file);
         prop.store(fos, "");
         fos.close();
         fis.close();
}






其他流对象


打印流 :该流提供了打印方法,可以将各种数据类型的数据都原样打印出来。


字节打印流
 PrintStream 
 构造函数可以接受的参数类型
 1.file对象 File
 2.字符串路径 String
 3.字节输出流 OutputStream


字符打印流
 PrintWriter


 构造函数可以接受的参数类型
 1.file对象 File
 2.字符串路径 String
 3.字节输出流 OutputStream
 4.字符输出流 Writer




练习 
控制台输入后,打印在控制台


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


PrintWriter Out=new PrintWriter(System.in,true));
String line=true;
while((line=bufr.readLine()))!=numm
{
   if("over".equals(line))
      break;
   out.println(line);
}
out.close();
bufr.close();


合并流(序列流):SeaquenceInputStream 对多个流进行合并。


vactor<FileInputStream> v=new vactor<FileInputStream>();
v.add(new FileInputStream("1.txt"));
v.add(new FileInputStream("2.txt"));
v.add(new FileInputStream("2.txt"));


Enumeration<FileInputStream> en=v.elements();
SeaquenceInputStream  sis=new SeaquenceInputStream(en);


FileOutputStream fos=new FileOutputStream("4.txt");
byte[] buf=new byte[1024];


int len=0;
while((len=sis.read(buf))!=-1){
fos.write(buf,0,len);
}
fos.close();
sis.close();

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值