黑马程序员——IO流

来源:互联网 发布:宝马工程师编程步骤 编辑:程序博客网 时间:2024/06/05 09:49

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

IO流

流概念:

流是一组有顺序、有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。

特点:

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

Java对数据的操作是通过流的方式

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

分类:

1、按操作数据划分

字节流与字符流

2、按流向分类

输入流,输出流

字节流两个基类:

InputStream   OutputStream

字符流两个基类:

Reader   Writer


字符流

字符流的由来:

因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查指定的码表。

字节流和字符流的区别:

读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。

处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。

FileWriter文件写入

定义文件路径时,可以用“/”或者“\\”。

在创建FileWriter对象时,该对象一被初始化就必须要明确被操作的文件。而且该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。其实该步就是在明确数据要存放的目的地。

FileWriter  fw = new  FileWriter("demo.txt");

fw.write("abcde");//调用write方法,将字符串写入到流中。

fw.flush();//刷新流对象中的缓冲中的数据,将数据刷到目的地中。

fw.close();//关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据,将数据刷到目的地

close和flush区别:

flush刷新后,流可以继续使用

close刷新后,会将流关闭。

注意:传递一个true参数,代表不覆盖已有的文件。并在已有文件的末尾处进行数据续写。

FileWriter  fw = new  FileWriter("demo.txt",true);

fw.write("nihao\r\nxiexie");//   \r\n:在Windows系统中代表换行

FileReader文件读取

在创建读取流对象时,和指定名称的文件相关联。要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundException

FileReader  fr = new  FileReader("demo.txt");

文件读取两种方式:

第一种:

调用读取流对象的read方法。read():一次读一个字符。而且会自动往下读。

int ch = 0;

while((ch=fr.read())!=-1)

     {

         System.out.println((char)ch);

     }

第二种:

通过字符数组进行读取

定义一个字符数组,用于存储读到字符。该read(char[])返回的是读到字符个数。

char[]  buf = new char[1024];

int  num = 0;

while((num=fr.read(buf))!=-1)

{

System.out.println(new String(buf,0,num));

}


字符流缓冲区

缓冲区的出现提高了对数据的读写效率。

缓冲区对应的类

BufferedWriter      BufferedReader

缓冲区的出现是为了提高流的操作效率。所以在创建缓冲区之前,必须要先有流对象。该缓冲区中提供了一个跨平台的换行符。newLine();

操作步骤:

1、创建一个字符写入流对象

FileWriter  fw = new FileWriter("buf.txt");

2、将需要被提高效率的流对象作为参数传递给缓冲区的构造函数

BufferedWriter bufw = new BufferedWriter(fw);

简写为:

BufferedWriter bufw = new BufferedWriter(new  FileWriter("buf.txt"));

字符读取流缓冲区:

该缓冲区提供了一个一次读一行的方法 readLine,方便于对文本数据的获取。当返回null时,表示读到文件末尾。

readLine方法返回的时候只返回回车符之前的数据内容。并不返回回车符。

需求:通过缓冲区复制一个.java文件。

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;class CopyTextByBuf {public static void main(String[] args) {BufferedReader bufr = null;BufferedWriter bufw = null;try {bufr = new BufferedReader(new FileReader("1.java"));bufw = new BufferedWriter(new FileWriter("2.txt"));String line = null;while ((line = bufr.readLine()) != null) {bufw.write(line);bufw.newLine();bufw.flush();}} catch (IOException 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("写入关闭失败");}}}}


字节流

字节流和字符流的基本操作是相同的,但字节流还可以操作其他媒体文件。

由于媒体文件数据中都是以字节存储的,所以,字节流对象可直接对媒体文件的数据写入到文件中,而可以不用再进行刷流动作。因为字节流操作的是字节,即数据的最小单位,不需要像字符流一样要进行转换为字节。所以可直接将字节数据写入到指定文件中。

字节流:

InputStream   输入流(读)      FileInputStream(读)

OutputStream  输出流(写)    FileOutputStream(写)

FileInputStream(读)

第一种:读取单个字节

FileInputStream  fis = new FileInputStream("fos.txt");

int ch = 0;

while((ch=fis.read())!=-1)

{

System.out.println((char)ch);

}

第二种:通过字节数组读取

FileInputStream  fis = new FileInputStream("fos.txt");

byte[]  buf = newbyte[1024];

int len = 0;

while((len=fis.read(buf))!=-1)

{

System.out.println(newString(buf,0,len));

}

特有方法:available()获取文件中字节的个数.

当文件比较小的时候可以用,可以不用循环直接打印;文件过大慎用

int num = fis.available();

byte[] buf = new  byte[num];//定义一个刚刚好的缓冲区,不用在循环了

fis.read(buf);

    

需求:复制一个图片

思路:

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

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

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

4、关闭资源

import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;class  CopyPic{     public static void main(String[] args)     {         FileOutputStream fos = null;         FileInputStream fis = null;         try         {              fos = new FileOutputStream("2.bmp");              fis = new FileInputStream("1.bmp");              byte[] buf =new byte[1024];              int len = 0;              while((len=fis.read(buf))!=-1)              {                   fos.write(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("写入关闭失败");              }         }     }}

需求:通过缓冲区演示mp3的复制

由于在缓冲区内部定义了字节数组,因此不用定义数组

import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class copyMp3 {public static void main(String[] args) throws IOException {BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("c:\\0.mp3"));BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("c:\\1.mp3"));int by = 0;while ((by = bufis.read()) != -1) {bufos.write(by);}bufos.close();bufis.close();}}


转换流

InputStreamReader:字节转换成字符

OutputStreamWriter:字符转成字节

需求:通过键盘录入数据。当录入一行数据后,就将该行数据进行打印。如果录入的数据是over,那么停止录入。

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

System.in:对应的标准输入设备:键盘

import java.io.IOException;import java.io.InputStream;class ReadIn {public static void main(String[] args) throws IOException {InputStream in = System.in;StringBuilder sb = new StringBuilder();while (true) {int ch = in.read();if (ch == '\r')continue;if (ch == '\n')// 输入字符串,当遇到回车符开始打印{String s = sb.toString();// 把缓冲区变成字符串if ("over".equals(s))break;// 当输入over时结束循环System.out.println(s.toUpperCase());// 字符串变成大写打印sb.delete(0, sb.length());// 每次打印完清空缓冲区} elsesb.append((char) ch);// 把键盘录入的字符装入缓冲区}}}

上述键盘录入一行数据并打印其大写,发现其实就是读一行数据的原理,也就是readLine方法。能不能直接使用readLine方法来完成键盘录入的一行数据的读取呢?readLine方法是字符流BufferedReader类中的方法。而键盘录入的read方法是字节流InputStream的方法。那么能不能将字节流转成字符流再使用字符流缓冲区的readLine方法呢?InputStreamReader可以完成将字节流转成字符流。

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;class TransStreamDemo {public static void main(String[] args) throws IOException {// 获取键盘录入对象BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));// 获取键盘输出对象BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));String line = null;while ((line = bufr.readLine()) != null) {if ("over".equals(line))break;bufw.write(line.toUpperCase());bufw.newLine();bufw.flush();}bufr.close();}}

流操作的基本规律

通过三个明确来完成

1、明确源和目的

源:输入流。InputStream  Reader

目的:输出流。OutputStream  Writer

2、操作的数据是否是纯文本

是:字符流

不是:字节流

3、当体系明确后,在明确要使用哪个具体的对象

通过设备来进行区分:

源设备:内存,硬盘,键盘

目的设备:内存,硬盘,控制台

举例说明:

1、将一个文本文件中数据存储到另一个文件中,复制文件

分析:

源:纯文本,Reader

设备:硬盘上一个文件, FileReader

是否需要提高效率:是! BufferedReader.

BufferedReader  bufr = new  BufferedReader(new  FileReader("a.txt"));

目的:纯文本,Writer

设备:硬盘一个文件,FileWriter

是否需要提高效率:是!BufferedWriter

BufferedWriter bufw = newBufferedWriter( newFileWriter("b.txt"));

2、将键盘录入的数据保存到一个文件中

分析:

源:纯文本,Reader

设备:键盘,对应的对象是System.in,将System.in转换成Reader,用了Reader体系中转换流:InputStreamReader

             是否需要提高效率:是!BufferedReader

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

目的:纯文本 ,Writer

设备:硬盘一个文件, FileWriter

是否需要提高效率:是!BufferedWriter 

BufferedWriter  bufw = new  BufferedWriter(new  FileWriter("1.txt"));

3、把录入的数据按照指定的编码表(utf-8),将数据存到文件中

分析:

目的:纯文本 ,Writer

设备:硬盘一个文件,FileWriter

但FileWriter默认编码表是GBK。而题目要求存储时,加入指定编码表utf-8,而指定的编码表只有转换流可以指定,所以要使用的对象是OutputStreamWriter,而该转换流对象要接收一个字节输出流,而且还可以操作的文件的字节输出流,因此用FileOutputStream

是否需要提高效率:是!BufferedWriter 

              BufferedWriter bufw = new  BufferedWriter(new  OutputStreamWriter(new  FileOutputStream("d.txt"),"UTF-8"));

注意:涉及到字符编码转换时,需要用到转换流


File类

文件和目录路径名的抽象表现形式

特点:

1、用来将文件或文件夹封装成对象

2、方便于对文件与文件夹的属性信息进行操作

3、File类的实例是不可变的;也就是说,一旦创建,File对象表示的抽象路径名将永不改变

4、File对象可以作为参数传递给流的构造函数

File创建对象的三种方式:

方式一:     

File  f =new  File("a.txt");

将a.txt封装成File对象,可以将已有的和未出现的文件或者文件夹封装成对象

方式二:

File  f2=new  File("c:\\abc","b.txt");

将文件所在目录路径和文件一起传入,指定文件路径

方式三:

File d=new File("c:\\abc");

File  f3=new File(d,"c.txt");

将文件目录路径封装成对象,再创建文件对象,降低了文件于父目录的关联性

sop(f);//封装的目录是什么就打印什么

File类常见方法:

1、创建

boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。和输出流不一样,输出流对象一建立创建文件,而且文件已经存在会覆盖

boolean mkdir():创建文件夹

boolean mkdirs():创建多级文件夹

2、删除

boolean delete():删除失败返回false,如果文件正在被使用,则删除不了返falsel

void deleteOnExit();在程序退出时删除指定文件

3、判断

boolean exists() :文件是否存在.

isFile():是否是文件

isDirectory();是否是目录

isHidden();是否隐藏

isAbsolute();是否是绝对路径

4、获取信息

getName():获取名字

getPath():获取路径

getParent():获取绝对路径中的父目录

getAbsolutePath()获取绝对路径

long length()获取长度

注意:在判断文件对象是否是文件或者目的时,必须要先判断该文件对象封装的内容是否存在,通过exists判断

需求:列出当前目录下所有文件及文件夹

     public  static  void  listDemo()

     {

         File  f = new  File("c:\\");

//调用list方法的file对象必须是封装了一个目录,该目录还必须存在

         String[]  names =f.list();

         for(String name :names)

         {

              System.out.println(name);

         }

     }

需求:列出磁盘中有效的盘符

     public  static  void  listRootsDemo()

     {

         File[] files =File.listRoots();

         for(File f :files)

         {

              System.out.println(f);

         }

}

需求:文件名过滤

         String[]  arr =dir.list(new FilenameFilter()

         {

              public  boolean  accept(File dir,String name)

              {                 

                   returnname.endsWith(".bmp");

              }

         });

 

 

Properties类

Properties是hashtable的子类,它具备map集合的特点,里面存储的键值对都是字符串,是集合中和IO技术相结合的集合容器

特点:

可以用于键值对形式的配置文件

在加载数据时,需要数据有固定格式:键=值

需求:将流中的数据存储到集合中

1、用一个流和info.txt文件关联

2、读取一行数据,将该行数据用"="进行切割

3、等号左边作为键,右边作为值,存入到Properties集合中即可

public static void method() throws IOException {
BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));
String line = null;
Properties prop = new Properties();
while ((line = bufr.readLine()) != null) {
String[] arr = line.split("=");
prop.setProperty(arr[0], arr[1]);
}
bufr.close();
System.out.println(prop);
}

 

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

0 0
原创粉丝点击