黑马程序员_笔迹二_关于IO流

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

IO(Input Output)

--->IO流用来处理设备之间的数据传输

--->java对数据的操作时通过流的方式

--->Java用于操作流的对象都在IO包中

--->流按操作数据分为2种:字节流和字符流

--->流按流向分:输入流,输出流

 

IO流常用基类

字节流的抽象基类

--->InputStreamOuputStream

字符流的抽象基类

--->Reader,Writer

 

字节流

主要操作byte类型数据,已byte数组为准,主要操作类为OutputStream类和InputStream

 

字节输出流OuputStream 最基本的方法

       write(int b)

将指定的字节写入此输出流。write 的常规协定是:向输出流写入一个字节。要写入的字节是参数 b 的八个低位。b  24 个高位将被忽略。

write(byte[] b)  b.length 个字节从指定的 byte数组写入此输出流。write(b) 的常规协定是:应该与调用 write(b, 0, b.length) 的效果完全相同。 

write(byte[] b,int off,int len)  将指定 byte数组中从偏移量 off 开始的 len 个字节写入此输出流write(b,off, len) 的常规协定是:将数组 b 中的某些字节按顺序写入输出流;元素 b[off] 是此操作写入的第一个字节,b[off+len-1] 是此操作写入的最后一个字节。

数据最常见的体现形式是:文件。下面演示在硬盘上创建一个文件并且写入一些数据

向文件中写入字符串

将整个数组一次性写入文件

public class Demo{
     public static void main(String args[]) throws Exception{    //
异常抛出,不处理
          //
1步、使用File类找到一个文件
          File f= newFile("d:" + File.separator + "test.txt");     //
声明File对象
          //
2步、通过子类实例化父类对象
          OutputStream out = null;     //
准备好一个输出的对象
          out = newFileOutputStream(f)  ;     //
实例化
          //
3步、进行写操作
          String str = "HelloWorld!!!" ;          //
准备一个字符串
          byte b[] =str.getBytes();              //
只能输出byte数组,所以将字符串变为byte数组
          out.write(b);                             //
将内容输出,保存文件
          //
4步、关闭输出流
          out.close();                             //
关闭输出流
     }
};

 

循环将每个字节写入

public class Demo{

     public staticvoid main(String args[]) throws Exception{     //异常抛出,不处理
          //
1步、使用File类找到一个文件
          File f= new File("d:"+ File.separator + "test.txt") ;     //
声明File对象
          //
2步、通过子类实例化父类对象
          OutputStream out = null;     //
准备好一个输出的对象
          out = newFileOutputStream(f)  ;     //
通过对象多态性,进行实例化
          //
3步、进行写操作
          String str = "HelloWorld!!!" ;          //
准备一个字符串
          byte b[] =str.getBytes();              //
只能输出byte数组,所以将字符串变为byte数组
          for(inti=0;i<b.length;i++){         //
采用循环方式写入
              out.write(b[i]) ;     //
每次只写入一个内容
          }
          //
4步、关闭输出流
          out.close();                             //
关闭输出流
     }
};

 

字节输入流InputStream

 

字节流最基本的读取方法

int read():从输入流中读取数据的下一个字节。返回 0 255 范围内的 int字节值。如果因为已经到达流末尾而没有可用的字节,则返回值 -1。在输入数据可用、检测到流末尾或者抛出异常前,此方法一直阻塞。

 

int read(byte[] b):

从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b中。以整数形式返回实际读取的字节数。在输入数据可用、检测到文件末尾或者抛出异常前,此方法一直阻塞。

如果 b的长度为 0,则不读取任何字节并返回 0;否则,尝试读取至少一个字节。如果因为流位于文件末尾而没有可用的字节,则返回值 -1;否则,至少读取一个字节并将其存储在 b中。

 

read(byte[] b,int off,int len)

将输入流中最多 len个数据字节读入 byte数组。尝试读取 len个字节,但读取的字节也可能小于该值。以整数形式返回实际读取的字节数。 

 

从文件中读取内容

 

直接读取文件

public class Demo{
     public static void main(String args[]) throwsException{     //
异常抛出,不处理
          //
1步、使用File类找到一个文件
          File f= newFile("d:" + File.separator + "test.txt");     //
声明File对象
          //
2步、通过子类实例化父类对象
          InputStream input = null;     //
准备好一个输入的对象
          input = newFileInputStream(f)  ;     //
通过对象多态性,进行实例化
          //
3步、进行读操作
          byte b[] = newbyte[1024] ;          //
所有的内容都读到此数组之中
          input.read(b);          //
读取内容
          //
4步、关闭输出流
          input.close();                             //
关闭输出流
         System.out.println("
内容为:" + new String(b));     //byte数组变为字符串输出,此时会有很多空格,因为文件大小没有1024个字节
     }
};

 

按照文件大小读取

 

public class Demo{
     public static void main(String args[]) throwsException{     //
异常抛出,不处理
          //
1步、使用File类找到一个文件
          File f= newFile("d:" + File.separator + "test.txt");     //
声明File对象
          //
2步、通过子类实例化父类对象
          InputStream input = null;     //
准备好一个输入的对象
          input = newFileInputStream(f)  ;     //
通过对象多态性,进行实例化
          //
3步、进行读操作
          byte b[] = newbyte[1024] ;          //
所有的内容都读到此数组之中
          int len = input.read(b);          //
读取内容
          //
4步、关闭输出流
          input.close();                             //
关闭输出流\
         System.out.println("
读入数据的长度:" + len) ;
         System.out.println("
内容为:" + new String(b,0,len));     //byte数组变为字符串输出,按照文件长度输出,不会有空格,但是依然开辟了1024个字节的空间,浪费了
     }
};

 

根据文件的大小,来开辟对应的字节数组空间

public class Demo{
     public static void main(String args[]) throwsException{     //
异常抛出,不处理
          //
1步、使用File类找到一个文件
          File f= newFile("d:" + File.separator + "test.txt");     //
声明File对象
          //
2步、通过子类实例化父类对象
          InputStream input = null;     //
准备好一个输入的对象
          input = newFileInputStream(f)  ;     //
通过对象多态性,进行实例化
          //
3步、进行读操作
          byte b[] = newbyte[(int)f.length()] ;         // 
数组大小由文件决定
          int len = input.read(b);          //
读取内容
          //
4步、关闭输出流
          input.close();                             //
关闭输出流\
         System.out.println("
读入数据的长度:" + len) ;
         System.out.println("
内容为:" + new String(b));     //byte数组变为字符串输出
     }
};

 

循环读取字节来输出

 

public class Demo{
     public static void main(String args[]) throwsException{     //
异常抛出,不处理
          //
1步、使用File类找到一个文件
          File f= newFile("d:" + File.separator + "test.txt");     //
声明File对象
          //
2步、通过子类实例化父类对象
          InputStream input = null;     //
准备好一个输入的对象
          input = newFileInputStream(f)  ;     //
通过对象多态性,进行实例化
          //
3步、进行读操作
          byte b[] = newbyte[(int)f.length()] ;         // 
数组大小由文件决定
          for(inti=0;i<b.length;i++){
              b[i] = (byte)input.read();          //
读取内容
          }
          //
4步、关闭输出流
          input.close();                             //
关闭输出流\
         System.out.println("
内容为:" + new String(b));     //byte数组变为字符串输出
     }
};

 

不知道文件大小,通过判断是否读取到文件末尾来读取文件

public class Demo{
     public static void main(String args[]) throwsException{     //
异常抛出,不处理
          //
1步、使用File类找到一个文件
          File f= newFile("d:" + File.separator + "test.txt");     //
声明File对象
          //
2步、通过子类实例化父类对象
          InputStream input = null;     //
准备好一个输入的对象
          input = newFileInputStream(f)  ;     //
通过对象多态性,进行实例化
          //
3步、进行读操作
          byte b[] = newbyte[1024] ;          
          int len = 0 ;
          int temp = 0;              //
接收每一个读取进来的数据
          while((temp=input.read())!=-1){
               
//返回 0 255范围内的 int 字节值
              b[len] = (byte)temp ;
              len++ ;
          }
          //
4步、关闭输出流
          input.close();                             //
关闭输出流\
         System.out.println("
内容为:" + new String(b,0,len));     //byte数组变为字符串输出
     }
};

PS:最标准的IO异常处理

public class Demo {

 

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

         //1步、使用File类找到一个文件

        Filef = new File("d:" + File.separator + "test.txt" ); //声明File对象

        FileWriterfw = null ;//指定FW为全局引用

         try {//IO操作都要处理异常

            fw= new FileWriter(f);

            fw.write( "abc" );

 

        } catch (Exception e) {

            e.printStackTrace();

        } finally {//单独对 文件的关闭操作进行异常处理

             try {

                 if (fw!=null ){//判断文件是否为空,如果进行判断,那么在下面执行关闭操作的时候,可能出现空指针异常

                    fw.close();

                }

                

            } catch (Exception e) {

                e.printStackTrace();

            }

        }

    }

}

 

 

小结最基本的读取方式

字节流

1 直接把字符串转成byte数组写入文件

String str = "hello world";

    byte[] b = str.getBytes();

    out.write(b);

 

2 通过循环把每个字节写入

String str = "hello world";

    byte[] b = str.getBytes();

   for(int i=0;i<b. length;i++){

      out.write(b[i]);

   }

 

3 读取文件,根据文件的数据量来选择开辟空间大小,这样最节省空间

byte[] b = new byte[(int)f.length()];

in.read(b);

 

4 循环一个一个字节读取文件(知道文件长度)

byte[] b = new byte[(int)f.length()];

for(int i=0;i<b.length;i++){

       b[i] = (byte)in.read();

}

 

5 如果不知道具体要输入的内容有多大,则靠判断是否读到文件末尾的方式来读取文件

byte[] b = new byte[1024];

while((temp=in.read())!=-1){

    //将每次读取的内容给 temp变量,如果不是-1,表示文件还没读完

 

    //返回 0 255范围内的 int 字节值

    b[len] = (byte)temp;

    len++;

}

 

字符流 最基本的操作方法

Writer

write(int c):写入单个字符。要写入的字符包含在给定整数值的 16 个低位中,16高位被忽略。

write(char[] cbuf):写入字符数组

write(char[] cbuf,int off,int len) :写入字符数组的某一部分。

write(String str):写入字符串

字符输入流 Reader

用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int) close()。但是,多数子类将重写此处定义的一些方法,以提供更高的效率和/或其他功能。

int read():读取单个字符,作为整数读取的字符,范围在0 65535之间 (0x00-0xffff),如果已到达流的末尾,则返回 -1

int read(char[]cbuf):将字符读入数组,读取的字符数个数,如果已到达流的末尾,则返回 -1

PS:如果读取字符个数的长度超过定义的char数组的长度,则读取时,指针会回到数组的开头,继续开始读取,将读取到的数组,从0下标开始,依次读入数组内

int read(char[]cbuf,int off,int len)将字符读入数组的某一部分。在某个输入可用、发生 I/O错误或者到达流的末尾前,此方法一直阻塞。

while((temp=reader.read())!=-1){

c[len] = (char)temp;

len++;

}

 

向文件中写入数据

 

public class Demo{
     public static void main(String args[]) throwsException{     //
异常抛出,不处理
          //
1步、使用File类找到一个文件
          File f= newFile("d:" + File.separator + "test.txt");     //
声明File对象
          //
2步、通过子类实例化父类对象
          Writer out = null;     //
准备好一个输出的对象
          out = newFileWriter(f)  ;     //
通过对象多态性,进行实例化
          //
3步、进行写操作
          String str = "HelloWorld!!!" ;          //
准备一个字符串
          out.write(str);                             //
将内容输出,保存文件
          //
4步、关闭输出流
          out.close();                             //
关闭输出流
     }
};

 

从文件中读取内容

public class Demo{
     public static void main(String args[]) throwsException{     //
异常抛出,不处理
          //
1步、使用File类找到一个文件
          File f= newFile("d:" + File.separator + "test.txt");     //
声明File对象
          //
2步、通过子类实例化父类对象
          Reader input = null;     //
准备好一个输入的对象
          input = newFileReader(f)  ;     //
通过对象多态性,进行实例化
          //
3步、进行读操作
          char c[] = newchar[1024] ;          //
所有的内容都读到此数组之中
          int len = input.read(c);          //
读取内容
          //
4步、关闭输出流
          input.close();                             //
关闭输出流
         System.out.println("
内容为:" + new String(c,0,len));     //把字符数组变为字符串输出
     }
};

 

练习实例:进行文件的拷贝

public class Demo {

 

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

         //创建一个要被拷复制的文件

        FileReaderfr = new FileReader("d:" +File.separator +"test.txt" );

         //创建一个复制的文件

        FileWriterfw = new FileWriter("d:" +File.separator +"copytest.txt" );

         //IO读取要处理异常

         try {

             char [] c = new char[1024];

             int len = 0;

             //没有读到文件末尾的时候

             while ((len = fr.read(c))!=-1){

                fw.write(c,0,len); //将读到的内容,,写入到 fw文件

                

            }

        } catch (Exception e){

            e.printStackTrace();

        } finally {// fw,fr流在最后都要进行关闭操作的异常处理

             if (fr!=null ){

                 try {fr.close();}catch(Exception e){e.printStackTrace();};

            }

             if (fw!=null ){

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

 

            }

        }

    }

}

 

字节流与字符流的区别

字节流在操作时本身不会哟会给你到缓冲区,是文件本身直接操作的。而字符流在操作时使用了缓冲区,通过缓冲区再操作文件

转换流OutputStreamWriterInputStreamReader

--->OutputStreamWriter:Writer的子类,将输出的字符流变为字节流。

--->InputStreamReader:Reader的子类,将输入的字节流变为字符流。

 

内存操作流

使用ByteArrayInputStreamByteArryOutputStream来完成在内存的输入输出

public class Demo {

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

        Stringinfo = "helloworld";

        InputStreaminput = new ByteArrayInputStream(info.getBytes());

        OutputStreamoutput = new ByteArrayOutputStream();

         int temp = 0;

         while ((temp = input.read()) != -1) {

            output.write(Character. toUpperCase((char) temp));

        }

        Stringstr = output.toString(); //取出内容

        input.close();

        output.close();

        System. out.println(str);

    }

结果:HELLOWORLD

 

打印流

在整个IO包中,打印流是输出信息最方便的类

字节打印流:PrintStream
字符打印流:PrintWriter

PrintStream类中的构造方法中,可以直接接收OutputStream类的实例,这是因为与OutputStream类相比,PrintStream类可以更加方便的输出数据,就好像讲OutpuStream类重新包装了下,使之更加方便的输出

(装饰设计模式)

public class Demo {

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

        PrintStream out = new PrintStream( new FileOutputStream(new File("d:"

                +File. separator + "test.txt")));

                out.print(1+ " +" + 1 + " =" );

                out.println(1+ 1);

                out.println( "Hello World!!!") ;

    }

 

System类对IO的支持

 

System.out PrintStream的对象,表示向显示器上输出,而PrintStream又是OutputStream的子类,所有可以直接利用此对象向屏幕上输出信息

 

System.err 表示的是错误信息的输出,如果程序出现错误,就可以直接使用System.err进行输出。

System.outSystem.err都是PrintStream的实例化对象,一般来说,System.out是将信息显示给用户看,是正常的显示信息,而System.err是直接在后台打印,是专门显示错误的

 

System.in

System.in实际上是一个键盘的输入流,其本身是InputStream类型的对象。可以利用System.in完成从键盘读取数据的功能(不考虑可能出现的乱码情况,只是一个简单实例)

publicclass Demo{
     public static void main(String args[]) throwsException {     //
所有异常抛出
          InputStream input =System.in ;     //
从键盘接收数据
          byte b[] = new byte[5];     //
开辟空间,接收数据
          System.out.print("
请输入内容:") ;     //提示信息
          int len = input.read(b);     //
接收数据
         System.out.println("
输入的内容为:" + new String(b,0,len)) ;
          input.close();     //
关闭输入流
     }
};

 

输入/输出的重定向

通过System类可以改变System.in的输入流以及System.outSystem.err2个输入路的位置

publicclass Demo{
     public static void main(String args[]) throwsException {
          System.setOut(
              new PrintStream(
                   new FileOutputStream("d:" +
                        File.separator + "test.txt"))) ;     //System.out
输出重定向
         System.out.print("hello world") ;     //
输出时,不再向屏幕上输出
      
     }
};

 

BufferedReader

BufferedReader类用于从缓冲区读取内容,所有的读入字节数都放在缓冲区.

BufferedReader类中定义的构造方法只能接受字符输入流的实例,所以在使用时,必须使用字符输入流和字节输入流的转换类InputStreamReader将字节输入流System.in变为字符流。。

PsBufferedReader只能接受字符流的缓冲区,因为每一个中文要占两个字节,所以需要将System.in这个字节的输入流变为字符的输入流

 

键盘输入流的标准格式

System.in变为字符流放入到BufferedReader后,可以通过readLine()方法等待用户输入信息

publicclass Demo {

     public static void main(String[] args) throwsException{
         
BufferedReader buf = new BufferedReader(
          newInputStreamReader(System.in));
String str = null;
System.out.println("
请输入内容");
//
处理可能出现的IO异常,写在一行,方便查看
try{str=buf.readLine();}catch(Exception e){e.printStackTrace();}
//
打印信息
System.out.println(str);
     }
}

 

Scanner

此类不仅可以完成输入数据操作,也可以方便的对输入数据进行验证 

PS:Scanner类中提供了一个接受InputStream类型的构造方法,只要是字节输入流的子类都可以通过Scanner类进行方便的接收

publicclass Demo{
     public static void main(String args[]){
          Scanner scan = newScanner(System.in) ;     //
从键盘接收数据
          System.out.print("
输入数据:") ;
          String str = scan.next();     //
接收数据
         System.out.println("
输入的数据为:" + str) ;
     }
};

 

数据操作流

IO包中,有2个与平台无关的数据操作流,分别为数据输出流DataOutputStream和数据输入流DataInputStream。数据输出流会按照一定的格式将数据输出,再通过数据输入流按照一定的格式将数据输入,这样可以方便的对数据进行处理

publicclass DataOutputStreamDemo{
     public static void main(String args[]) throwsException{     //
所有异常抛出
          DataOutputStream dos =null;              //
声明数据输出流对象
          File f = newFile("d:" + File.separator + "test.txt") ; //
文件的保存路径
          dos = newDataOutputStream(new FileOutputStream(f)) ;     //
实例化数据输出流对象
          String names[] = {"
衣服","鞋子","围巾"} ;     // 商品名称
          float prices[] ={10.0f,10.0f,10.0f} ;          //
商品价格
          int nums[] = {1,1,1};     //
商品数量
          for(inti=0;i<names.length;i++){     //
循环输出
              dos.writeChars(names[i]) ;     //
写入字符串
              dos.writeChar('\t') ;     //
写入分隔符
              dos.writeFloat(prices[i]) ; //
写入价格
              dos.writeChar('\t') ;     //
写入分隔符
              dos.writeInt(nums[i]) ; //
写入数量
              dos.writeChar('\n') ;     //
换行
          }
          dos.close();     //
关闭输出流
     }
};

 

字符编码

在程序中处理不好字符的编码,就有可能出现乱码。要避免乱码,必须保证程序的编码与本地的默认编码一致。

要活的本地的默认编码,可以使用System类完成

publicclass Demo{
     public static void main(String args[]){
         System.out.println("
系统默认编码:" +
              System.getProperty("file.encoding")) ;     //
获取当前系统编码
     }
};

 

Ps:实现编码的转换,可以使用String类中的getBytes(String charset)方法设置编码

publicclass Demo{
     public static void main(String args[]) throwsException {
          File f = newFile("D:" + File.separator + "test.txt");     //
实例化File
          OutputStream out = newFileOutputStream(f) ;     //
实例化输出流
          byte b[] = "
你好!".getBytes("ISO8859-1");     //转码操作
          out.write(b);     //
保存
          out.close();     //
关闭
     }
};

 

IO流小结:

1  java中使用File类表示文件本身,可以直接使用此类完成文件的各种操作。

2RandomAccessFile类可以从指定的位置开始读取信息,但是要求文件中各个数据的保存长度必须固定

3 输入输出流主要分为字节流和字符流。在传输中以字节流操作比较多,字符流在操作时用到缓冲区,而字节流没有用到缓冲区U

4 IO包中是员工OutputStreamWriterInputStreamReader完成字符流与字节流的转换

5 IO中输出时最好使用打印流(PrintStream ,PrintWriter),这样可以更加方便的输入输出各种类型的数据

6 System类提供了三个支持IO操作的常量outerrin

7BufferReader可以直接从缓冲区中读取数据

8 使用Scanner类可以方便的进入输入流操作

9 造成字符乱码的根本原因就在于程序编码与本地编码的不统一



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值