黑马程序员_java_io(上)

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

        java_ io(上)
 io流是一组有序的数据序列,根据操作的类型,可分为输入流和输出流两种io(Inpout/Output)liu
同了一条通道程序,可以使用这条通道吧源中的字节序列送到目的地,虽然io流经常与词牌文件存取有关,
但是程序的源和目的地也可以是键盘鼠标,内存或者显示器窗口等.
 java有数据流处理输入/输出模式,程序与从指定源的输入流中读取源中的数据,源可以是文件.网络.压缩包
或者其他数据


 java语言定义了许多专门负责各个方式的输入/输出,这些类都被放在java.io包中.其中所有输入流
类都是抽象类InputStream(字节输入流)或者抽象类Reader(字符输入流)的子类;而所有输出流都是抽象
类OutputStream(字节输出流)或者抽象类Writer(字符流输出流)的子类.


 字节流两个基类:
  InputStream   OutputStream


 字符流两个基类:
  Reader Writer
 注由这四个类派生出来的子类名称都是 以其父类名作为子类名的后缀。


 如:InputStream的子类FileInputStream。
 如:Reader的子类FileReader。

//------------------------------------------------------------------------

构造方法:


FileWriter:用来写入字符文件的便捷类java.io Writer另请参见:

 

 FileWriter(String fileName, boolean append)
     根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。


 FileWriter(File file)
     根据给定的 File 对象构造一个 FileWriter 对象。


 FileWriter(FileDescriptor fd)
     构造与某个文件描述符相关联的 FileWriter 对象。

 
 FileWriter(String fileName)
     根据给定的文件名构造一个 FileWriter 对象。


 FileWriter(File file, boolean append)
  示:fw=new FileWriter("demo.txt",true);//在已有文件续写.如果没有就文件就创建
      根据给定的 File 对象构造一个 FileWriter 对象。

 

常用方法:
      
 void write(String str):
写入字符串。
 abstract  void flush():刷新该流的缓冲
 abstract  void close():关闭此流,但要先刷新它。
    

  //创建一个FileWriter对象。该对象一被初始化就必须要明确被操作的文件。
  //而且该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。
  //其实该步就是在明确数据要存放的目的地。
  FileWriter fw = new FileWriter(“Test.txt”);

  //调用write方法,将字符串写入到流中。
  fw.write("abcde");
  //刷新流对象中的缓冲中的数据。
  //将数据刷到目的地中。

  //fw.flush();

  //关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。
  //将数据刷到目的地中。
  //和flush区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭。
  fw.close();

 ps:\r\n:回车符.在windows里面需要两个代表回车符.在linux系统\n代表回车符.
//-------------------------------------------------------------------------                      
IO异常的处理方式续写和回车符:
示例:

import java.io.*;
class FileWriterDemo2 
{
 public static void main(String[] args)
 {
  FileWriter fw=null;//需要在代码块外边建立引用.
  try
  {
   fw=new FileWriter("demo.txt",true);
   fw.write("accd\r\nde");  
  }
  catch (IOException e)
  {
   System.out.println(e.toString());
  }
  finally
  {
   if(fw!=null)//判断fw是否为空.如果输入盘符错误的话.fw会是null;将执行不到close所以要判断
    try
    {
     fw.close();
    }
    catch (IOException e)
    {
     System.out.println("关闭资源失败");
    }  
  } 
 }
}



//---------------------------------------------------------------------

构造方法:


FileReader:用来读取字符文件的便捷类java.io Reader另请参见:


  FileReader(File file)
          在给定从中读取数据的 File 的情况下创建一个新 FileReader。


  FileReader(FileDescriptor fd)
          在给定从中读取数据的 FileDescriptor 的情况下创建一个新 FileReader。


  FileReader(String fileName)
          在给定从中读取数据的文件名的情况下创建一个新 FileReader。

 

常用方法:

  abstract  void |close() 关闭该流并释放与之关联的所有资源。


  void |mark(int readAheadLimit) 标记流中的当前位置。


  boolean |markSupported() 判断此流是否支持 mark() 操作。


  int |read() 读取单个字符。


  int |read(char[] cbuf) 将字符读入数组。


  abstract  int |read(char[] cbuf, int off, int len) 将字符读入数组的某一部分。


  int |read(CharBuffer target) 试图将字符读入指定的字符缓冲区。


  boolean r|eady() 判断是否准备读取此流。


  void |reset() 重置该流。


  long |skip(long n) 跳过字符。

 

  
 第一种取出方式: 
  //创建一个文件赌球流对象,和指定名称的文件相关联.
  //要保证该文件时已经存在的,如果不存在,会发生异常FileNotFoundException
  

FileReader fr=new FileReader("demo.txt");
  int ch=0;
  /*
  调用读取流对象的read方法
  read():一次读一个字符,而且会自动往下读.
  */
  while((ch=fr.read())!=-1)
  {
  System.out.println("ch="+(char)ch);
  }
  /*
  while(true)
  {
   int ch=fr.read();
   if(ch==-1)
    break;
  System.out.println("ch="+(char)ch);
  }
  */


 


 第二种出去方式:


  

fr=new FileReader("FileWriterDemo.java");
  //定义一个字符数组.用于存储到字符.
  //该read(char[])返回的是读到的个数
  char[] buf=new char[1024];
  //定义一个变量来记住个数
  int num=0;
  //用while循环来判断结尾是否读到的个数为-1
  while((num=fr.read(buf))!=-1)
  {
   //打印个数和字符数组.new String(buf,0,num)是Sting类中打印数组从0开始.到nun结束
   System.out.print(num+"....."+new String(buf,0,num));
   //注意输出语句没加ln.是因为数组的长度是1024,如果到了1024就会换行.所以不加.
  }



  
练习:拷贝文件


 

/*
需求:拷贝文本文件.
1.在D盘创建一个文件,用于存储c盘文件中的数据
2.定义读取流和c文件箱关联.
3.通过不断的读写完成数据存储.
4.关闭资源
*/
import java.io.*;
class  CopyText
{
 public static void main(String[] args) 
 {
  copy_2();
 }
 public static void copy_2()//建立字符数组集体拷贝
 {
  FileReader fr=null;//在代码块外边给fr初始化.要不然在代码块里面建立对象别的地方会访问不到
  FileWriter fw=null;
  try
  {
   fr=new FileReader("MathDemo.java");//建立对象并指定好目录
   fw=new FileWriter("MathDemo_copy.txt");
   char[] buf=new char[1024];//建立字符数组,用来储存数据

   int len=0;//定义一个变量来记住字符数
   while((len=fr.read(buf))!=-1)//因为字符数到末尾会是-1.进行判断
   {
    fw.write(buf,0,len);//写出数据.并从零开始.到字符数那里结束
   }
  }
  catch (IOException e)//路径不存在抛异常
  {
   throw new RuntimeException("路径不存在");
  }
  finally
  {
   try
   {
    if(fr!=null)//对close判断.是否为空如果建立对象不成功的话close根本不识别.
     fr.close();
   }
   catch (IOException e)
   {
    System.out.println("写入失败");
   }
   try
   {
    if(fw!=null)
     fw.close();
   }
   catch (IOException e)
   {
    System.out.println("读取失败");
   }
  }
 }
 public static void copy_1()//一个字符一个字符的拷贝
 {
  FileReader fr=null;
  FileWriter fw=null;
  try
  {
   fr=new FileReader("SystemDemo.java");
   fw=new FileWriter("System_copy.txt");

   int ch=0;
   while((ch=fr.read())!=-1)
   {
    fw.write(ch);
   }
  }
  catch (IOException e)
  {
   throw new RuntimeException("路径不存在");
  }
  finally
  {
   try
   {
    if(fr!=null)
     fr.close();
   }
   catch (IOException e)
   {
    System.out.println("写入失败");
   }
   try
   {
    if(fw!=null)
     fw.close();
   }
   catch (IOException e)
   {
    System.out.println("读取失败");
   }
  }
 }
}


//--------------------------------------------------------------------------
BufferedWriter类与BufferedReader类

 Bufferedwriter类和BufferedReader类分别继承了Reader类和Writer类.这两个类同样具备了内部缓存机制.
可以可进行单位进行输入输出.


 在使用BufferedWriter类的Writer()方法时,数据并没有立即写入至输出流中.而是首先进入缓存区中.
如果想理解将缓存区中个的数据写入输出流中,一定要动用flush()方法.
 缓冲区的出现提高了对数据的读写效率。


 对应类
 BufferedWriter
 BufferedReader

 

 字符输出流缓冲区:
  缓冲区要结合流才可以使用。
  在流的基础上对流的功能进行了增强
  缓冲区的出现是为了提高流的操作小路而出现的.
  所以在创建缓冲区之前,必须要先有流对象.
  该缓冲区提供了一个夸平台的换行符.
  newLine();

 

 字符读取流缓冲区:
  该缓冲区提供了一个一次读一行的方法 readLine,方便与对文本进行数据的获取.
  当返回null时候,表示读到文件末尾.

 


示例:


 

/*
需求:复制一个java文件
*/
import java.io.*;
class  CopyTextBuf
{
 public static void main(String[] args) 
 {
  BufferedReader bufr=null;
  BufferedWriter bufw=null;
  try
  {
   //为了提高效率.加入缓冲技术,将字符读取流对象作为参数传递给缓冲区的构造函数.
   //建立缓冲区,创建流对象和文件相关联的
   bufr=new BufferedReader(new FileReader("BufferedReaderDemo.java"));//字符读取流

   bufw=new BufferedWriter(new FileWriter("BufferedReaderDemoCopy_1.txt"));//字符输出流
   String s=null;//因为读取一行到末尾的时候会返回null.就可以以null作为循环条件来循环
   while((s=bufr.readLine())!=null)
   {
    bufw.write(s);//读取一行.输出一行
    bufw.newLine();//换行
   }
  }
  catch (IOException e)
  {
   throw new RuntimeException("文件路径错误");
  }
  finally
  {
   try
   {
    if(bufr!=null)
     bufr.close();
   }
   catch (IOException e)
   {
    System.out.println("读取关闭文件失败");
   }
   try
   {
    if(bufw!=null)
     bufw.close();
   }
   catch (IOException e)
   {
    System.out.println("输出关闭文件失败");
   }
  }
 }
}


//-------------------------------------------------------------------


装饰设计模式:
 以前是通过继承将每一个子类都具备缓冲功能。
 那么继承体系会复杂,并不利于扩展。

 

 现在优化思想。单独描述一下缓冲内容。
 将需要被缓冲的对象。传递进来。也就是,谁需要被缓冲,谁就作为参数传递给缓冲区。
 这样继承体系就变得很简单。优化了体系结构。

 

 装饰模式比继承
  要灵活。避免了继承体系臃肿。
  而且降低了类于类之间的关系。

 

 装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。
 所以装饰类和被装饰类通常是都属于一个体系中的。
MyReader//专门用于读取数据的类。
            |--MyTextReader
                    |--MyBufferTextReader
            |--MyMediaReader
                    |--MyBufferMediaReader
            |--MyDataReader
                    |--MyBufferDataReader


class MyBufferReader
{
 MyBufferReader(MyTextReader text)
 {}
 MyBufferReader(MyMediaReader media)
 {}
}
上面这个类扩展性很差。
找到其参数的共同类型。通过多态的形式。可以提高扩展性。

class MyBufferReader extends MyReader
{
 private MyReader r;
 MyBufferReader(MyReader r)
 {}

 


MyReader//专门用于读取数据的类。
 |--MyTextReader
 |--MyMediaReader
 |--MyDataReader
 |--MyBufferReader

 

 


 LineNumberReader:
  BufferedReaderd 的子类,也属于装饰类跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int)
  和 getLineNumber(),它们可分别用于设置和获取当前行号.


  演示:
   FileReader fr=new FileReader("demo.txt");//建立输入流对象于文件相关联
   LineNumberReader lnr=new LineNumberReader(fr);//建立缓冲区.
   String line =null;
   lnr.setLinNumber(100);//设置行号
   while((line=lnr.readLine())!=null)
   {
    System.out.println(lnr.getLineNumber()+":"+line);//获取行号,和打印一行
   }
   lnr.close
演示:

/*
明白了BufferedReader类中特有方法readLine的原理后,
可以自定义一个类中包含一个功能和readLine一致的方法。
来模拟一下BufferedReader
*/
import java.io.*;
class MyBufferedReader extends Reader
{
 private Reader r;
 MyBufferedReader(Reader r)//建立构造函数.一开始就要有流
 {
  this.r = r;
 }
 //可以一次读一行数据的方法。
 public String myReadLine()throws IOException
 {
  //定义一个临时容器。原BufferReader封装的是字符数组。
  //为了演示方便。定义一个StringBuilder容器。因为最终还是要将数据变成字符串。
  StringBuilder sb = new StringBuilder();
  int ch = 0;
  while((ch=r.read())!=-1)
  {
   if(ch=='\r')
    continue;//判断如果是\r的话在运行.判刑下个\n,如果是最后一行了.返回字符串
   if(ch=='\n')
    return sb.toString();
   else
    sb.append((char)ch);
  }

  if(sb.length()!=0)
   return sb.toString();
  return null;  
 }

 /*
 覆盖Reader类中的抽象方法。
 */
 public int read(char[] cbuf, int off, int len) throws IOException
 {
  return r.read(cbuf,off,len) ;
 }
 public void close()throws IOException
 {
  r.close();
 }
 public void myClose()throws IOException
 {
  r.close();
 }
}
class  MyBufferedReaderDemo
{
 public static void main(String[] args) throws IOException
 {
  FileReader fr = new FileReader("buf.txt");

  MyBufferedReader myBuf = new MyBufferedReader(fr);//自定义的装饰类

  String line = null;

  while((line=myBuf.myReadLine())!=null)
  {
   System.out.println(line);
  }
  myBuf.myClose();//关闭资源
 }
}



//---------------------------------------------------------------------------
        字节流
基本操作与字符流类相同
但它不仅可以操作字符,还可以操作其他 媒体文件
 InputStream类是字节输入流的抽象类,是所有字节流输入流的父类,InputStream类的具体层次结构
 InputStream
          |--AudioInputStream
          |--ByteArrayInputStream
          |--FileInputStream
                    |--BufferedInputStream
                    |--DataInputStream
                    |--等等.详情参阅API  java.io包中
           |--FilterInputStream
           |--InputStream
           |--ObjectInputStream
           |--PipedInputStream
           |--SequenceInputStream
           |--StringBufferInputStream


 常用方法:


  int  |available() 返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。


  void |close() 关闭此输入流并释放与该流关联的所有系统资源。


  void |mark(int readlimit) 在此输入流中标记当前的位置。


  boolean | markSupported() 测试此输入流是否支持 mark 和 reset 方法。


  abstract  int| read() 从输入流中读取数据的下一个字节。


  int |read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。

 
  int |read(byte[] b, int off, int len) 将输入流中最多 len 个数据字节读入 byte 数组。


  void|reset() 将此流重新定位到最后一次对此输入流调用 mark 方法时的位置。


  long| skip(long n) 跳过和丢弃此输入流中数据的 n 个字节。
 
 OutputStream类是字节输入流的抽象类,次抽象表示输出字节流的所有类的超类.OutputStream

 

 


  OutputStream
         |--ByteArrayOutputStream
         |--FileOutputStream
                 |--BufferedOutputStream
                 |--DataOutputStream
                 |--等等.详情参阅API  java.io包中
         |--FilterOutputStream
         |--ObjectOutputStream
         |--OutputStream
         |--PipedOutputStream

 

  常用方法:


   void |close() 关闭此输出流并释放与此流有关的所有系统资源。


   void |flush() 刷新此输出流并强制写出所有缓冲的输出字节。


   void |write(byte[] b) 将 b.length 个字节从指定的 byte 数组写入此输出流。

 
   void |write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。


   abstract  void |write(int b) 将指定的字节写入此输出流。

 
 FileInputStream 与 FileOutputStream 类
   FileInputStream类与FileOutputStream类都是用来操作磁盘文件的,如果用户的文件读取需求比较简单,测可以使用FileInputStream类.该类继承自InputStream类
  FlieOutputSream类与FileInputStreamLEI对应提供了基本的文件写入能力,FileOutputStream类是OutputStream类的子类.


示例:


 

/*
需求:拷贝一个图片
1.创建一个字符输入流和图片相关联.
2.用字节写入流对创建图片文件,用于存储到图片数据.
3.通过循环续写,完成数据的存储.
4.关闭资源.
*/
import java.io.*;
class  CopyPic
{
 public static void main(String[] args) 
 {
  FileInputStream fis=null;
  FileOutputStream fos=null;
  try
  {
   fis=new FileInputStream("D:\\2.jpg");//建立字符输入流对象和文件相关联
   fos=new FileOutputStream("copy.jpg");//建立字符输出流对象指定路径和文件名字
   byte[] buf=new byte[1024];//创建一个字符数组.用来缓存

   int num=0;//定义一个变量用于判断结尾处是否是-1

   while((num=fis.read(buf))!=-1)
   {
    fos.write(buf,0,num); //循环一次.字符数组输出一次.
   }
  }
  catch (IOException e)//处理异常
  {
   throw new RuntimeException("路径错误");
  }
  finally
  {
   try
   {
    if(fos!=null)//判断创建文件失败是否为null;
     fos.close();
   }
   catch (IOException e)
   {
    System.out.println("输出关闭失败");
   }
   try
   {
    if(fis!=null)
     fis.close();
   }
   catch (IOException e)
   {
    System.out.println("输入关闭失败");
   }
  }
 }
}


//------------------------------------------------------


用缓冲区技术拷贝Mp3


  BufferedInputStream buis=null;
  BufferedOutputStream buos=null;
  try
  {
   buis=new BufferedInputStream(new FileInputStream("D:\\Maid with the Flaxen Hair.mp3"));
   buos=new BufferedOutputStream(new FileOutputStream("copy.mp3"));

   int num=0;

   while((num=buis.read())!=-1)
   {
    buos.write(num);
   }
  }
  buis.close();
  buos.colse();

 


//-------------------------------------------------
InputStreamReader和OutputStreamWriter

 

InputStreamReader :


是字节流通向字符流的桥梁。
每次调用 InputStreamReader 中的一个 read()
方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。
为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。


构造方法:
  InputStreamReader(InputStream in)
  InputStreamReader(InputStream in, String charsetName)
 示例:
  BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

 

OutputStreamWriter :
是字符流通向字节流的桥梁:

 

将要写入流中的字符编码成字节
每次调用 write() 方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字节将在缓冲区中累积。
为了获得最高效率,可考虑将 OutputStreamWriter 包装到 BufferedWriter 中,以避免频繁调用转换器。


构造方法:


  OutputStreamWriter(OutputStream out)
  OutputStreamWriter(OutputStream out, String charsetName)


 示例:
  BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
 System.in 默认设备为键盘


     System.setIn(InputStream in)\\ 重新分配“标准”输入流。
 System.out 默认设备为控制台


     System. setOut(PrintStream out) \\重新分配“标准”输出流。

 


 PrintStream 的构造方法:


 PrintStream(String fileName)\\ 创建具有指定文件名称且不带自动行刷新的新打印流。
---------------------------------------------------------------------


异常的日志信息


  printStackTrace()//将此 throwable 及其追踪输出至标准错误流。

  printStackTrace(PrintStream s)// 将此 throwable 及其追踪输出到指定的输出流。

示例:

import java.io.*;
import java.util.*;
import java.text.*;
class  ExceptionInfo
{
 public static void main(String[] args)throws IOException 
 {
  try
  {
   int[] arr = new int[2];
   System.out.println(arr[3]);
  }
  catch (Exception e)
  {
   
   try
   {
    Date d = new Date();//建立日期类
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//格式化日期
    String s = sdf.format(d);

    PrintStream ps = new PrintStream("exeception.log");//设置异常文件
    ps.println(s);
    System.setOut(ps);

    
   }
   catch (IOException ex)
   {
    throw new RuntimeException("日志文件创建失败");
   }
   e.printStackTrace(System.out);//异常信息
  }
 }
}


 

 

---------------------------------------------------------------------
获取系信息
方法:


 list(PrintStream out)// 将属性列表输出到指定的输出流


示例:

import java.io.*;
import java.util.*;
class  SystemInfo
{
 public static void main(String[] args) throws IOException
 {
  Properties prop=System.getProperties();
  
  //System.out.println(prop);
  prop.list(new PrintStream("sysinfo.txt"));
  //Properties中的list方法PrintStream创建具有指定文件名称且不带自动行刷新的新打印流。
 }
}


 

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值