黑马程序员_输入输出流(I/O)

<a href="http://www.itheima.com"  target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流!

输入输出流(I/O)

    流(Stream)

    在java API中,可以从其中读入一个字节序列的对象称做输入流,而可以向其中写入一个字节序列的对象称做输出流。这些字节序列的来源地和目的地可以是文件,而且通常都是文件,但是也可以是网络连接,甚至是内存块。抽象类InputStream和OutputStream构成了有层次结构的输入/输出(I/O)类的基础。

    因为面向字节的流不便于处理Unicode形式存储的信息,所以从抽象类Reader和Writer中继承出来的专门用于处理Unicode字符的类构成了一个单独的层次结构。这些类拥有的读入和写出操作都是基于两字节的Uncode码元的,而不是基于单字节的字符。

    I/O流用来处理设备之间的数据传输,java对数据的操作是通过流的方式,用于操作流的对象都在IO包中.

    通过以上也可以看出流按操作数据分为两种:字节流与字符流;流按流向分为输入流,输出流.

    字节流的抽象基类:InputStream,OutputStream;字符流的抽象基类:Reader,Writer.由这四个类派生出来的子类名称,都是以基父类作为名作为子类名的后缀.

    如:InputStream的子类FileInputStream,Reader的子类FileReader.

字符流

Writer

直接已知子类:

BufferedWriter,CharArrayWriter, FilterWriter, OutputStreamWriter, PipedWriter, PrintWriter,StringWriter

Writer

append(char c)
将指定字符添加到此 writer。

Writer

append(CharSequence csq)
将指定字符序列添加到此 writer。

Writer

append(CharSequence csq, int start, int end)
将指定字符序列的子序列添加到此 writer.Appendable。

abstract void

close()
关闭此流,但要先刷新它。

abstract void

flush()
刷新该流的缓冲。

void

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

abstract void

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

void

write(int c)
写入单个字符。

void

write(String str)
写入字符串。

void

write(String str, int off, int len)
写入字符串的某一部分。

 

    Reader

直接已知子类

BufferedReader,CharArrayReader, FilterReader, InputStreamReader, PipedReader, StringReader

注:子类的后缀是其父类名,前缀名则是其功能.如OutputStreamWriter前缀名OutputStream是其功能,后缀Writer是其父类名.

方法摘要:

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

ready()
判断是否准备读取此流。

void

reset()
重置该流。

long

skip(long n)
跳过字符。

//FileWriter继承至OutputStreamWriter

FileWriter类

其中构造方法

FileWriter(File file)

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

参数:

file- 要写入数据的 File 对象。

抛出:

IOException - 如果该文件存在,但它是一个目录,而不是一个常规文件;或者该文件不存在,但无法创建它;抑或因为其他某些原因而无法打开它

FileWriter(String fileName)

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

参数:

fileName- 一个字符串,表示与系统有关的文件名。

抛出:

IOException - 如果指定文件存在,但它是一个目录,而不是一个常规文件;或者该文件不存在,但无法创建它;抑或因为其他某些原因而无法打开它

FileWriter(String fileName, boolean append)

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

参数:

fileName- 一个字符串,表示与系统有关的文件名。

append- 一个 boolean 值,如果为 true,则将数据写入文件末尾处,而不是写入文件开始处。

抛出:

IOException - 如果指定文件存在,但它是一个目录,而不是一个常规文件;或者该文件不存在,但无法创建它;抑或因为其他某些原因而无法打开它

FileReader类

其中构方法

FileReader(String fileName)

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

参数:

file- 要从中读取数据的 File

抛出:

FileNotFoundException - 如果文件不存在,或者它是一个目录,而不是一个常规文件,抑或因为其他某些原因而无法打开进行读取。

FileReader(File file)

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

参数:

file- 要从中读取数据的 File

抛出:

FileNotFoundException - 如果文件不存在,或者它是一个目录,而不是一个常规文件,抑或因为其他某些原因而无法打开进行读取。

练习拷贝一个文件

实现思路:

  1. 创建一个文件,用于存储拷贝的文件内容
  2. 定义读取流,关联待拷贝文件
  3. 通过读写完成数据的存储(复制)
  4. 关闭资源

实现代码:

import java.io.*;

 

public class CopyTest

{

    public static voidmain(String[] args)

    {

        copy();//调用方法

    }

   

    public static void copy()

    {

FileWriterfw = null;

        FileReaderfr = null;

       

        try

        {

           

            fw = newFileWriter("test_copy.txt");  //创建目的地,如果该文件存在则覆盖.

            fr = new FileReader("test.txt");   //与已有文件关联

           

            char[] cbuf =new char[1024];//声明一个char数组

           

            int len = 0;   //声明一个len变量用于接收fr.read()方法返回的存储的字符个数

           

            while((len =fr.read(cbuf)) != -1)

            {

                fw.write(cbuf,0, len); //调用方法将一个数组写入到流缓冲区,从0开始写,写入len个字符

            }  

        }

        catch(Exception e)

        {

            e.printStackTrace();

        }

        finally

        {

            try

            {

                if (fw !=null)

                    fw.close();//关闭资源

            }

            catch(Exception e2)

            {

                e2.printStackTrace();

            }

            try

            {

                if (fr !=null)

                    fr.close();

            }catch(Exceptione3)

            {

                e3.printStackTrace();

            }

        }

    }

}

BufferedWriter

将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。

该类提供了 newLine() 方法,它使用平台自己的行分隔符概念,此概念由系统属性 line.separator 定义。并非所有平台都使用新行符 ('\n') 来终止各行。因此调用此方法来终止每个输出行要优于直接写入新行符。

 

BufferedReader

从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。

通常,Reader 所作的每个读取请求都会导致对底层字符或字节流进行相应的读取请求。因此,建议用 BufferedReader 包装所有其 read() 操作可能开销很高的 Reader(如 FileReader 和 InputStreamReader)。例如,

 BufferedReader in

  = new BufferedReader(new FileReader("foo.in"));

 

将缓冲指定文件的输入。如果没有缓冲,则每次调用 read() 或 readLine() 都会导致从文件中读取字节,并将其转换为字符后返回,而这是极其低效的。

通过用合适的 BufferedReader 替代每个DataInputStream,可以对将 DataInputStream 用于文字输入的程序进行本地化

    练习通过缓冲区复制一个文本文件

import java.io.*;

 

public class CopyByBufTest

{

    public static voidmain(String[] args)

    {

        //创建缓冲对象

        BufferedWriterbw = null;

        BufferedReaderbr = null;

       

        try

        {

            //该对象构造方法接收流对象

            bw = newBufferedWriter(new FileWriter("test_copy.txt"));

            br = newBufferedReader(new FileReader("test.txt"));

           

            Stringline = null;

           

            while((line =br.readLine()) !=null) //br.readLine()此方法属性BuffereReader,属于增强功能,且只返回回车前之前的内容

            {

                bw.write(line);//写入一行字符串

                bw.newLine();//换行,此方法属性BufferedWriter

                bw.flush();//刷新

            }

           

        }catch(Exceptione)

        {

            e.printStackTrace();

        }

        finally

        {

            try

            {

                if (bw !=null)//关闭资源

                    bw.close();

            }

            catch(Exception e2)

            {

                e2.printStackTrace();

            }

            try

            {

                if (br !=null)

                    br.close();

            }catch(Exceptione3)

            {

                e3.printStackTrace();

            }

        }

    }

}

 

缓冲对输入/输出流进行了功能的增强,这里使用到了装饰设计模式:将一个体系优化后进行功能的增强,并且扩展性更强佳,装饰设计模式比继承更灵活,避免了继承体系的臃肿,而且降低了类与类之间的关系.装饰类因为是增强已有类,具备的功能和已有的是相同的,只不过提供了更强的功能,所以装饰类和被装饰类通常都是属于一个体系中的.装饰类是通过找到其参数的共同类型,通过多态的形式,来提高扩展性的.

字节流

    InputStream

直接已知子类:

AudioInputStream,ByteArrayInputStream, FileInputStream, 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

直接已知子类:

ByteArrayOutputStream,FileOutputStream, 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类

其中构造方法:

FileInputStream(File file)

通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。创建一个新 FileDescriptor 对象来表示此文件连接。

首先,如果有安全管理器,则用 file 参数表示的路径作为参数调用其 checkRead 方法。

如果指定文件不存在,或者它是一个目录,而不是一个常规文件,抑或因为其他某些原因而无法打开进行读取,则抛出 FileNotFoundException。

参数:

file- 为了进行读取而打开的文件。

抛出:

FileNotFoundException - 如果该文件不存在,或者它是一个目录,而不是一个常规文件,抑或因为其他某些原因而无法打开进行读取。

SecurityException - 如果存在安全管理器,且其 checkRead 方法拒绝对文件进行读取访问。

FileInputStream(String name)

通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。创建一个新 FileDescriptor 对象来表示此文件连接。

首先,如果有安全管理器,则用 name 作为参数调用其 checkRead 方法。

如果指定文件不存在,或者它是一个目录,而不是一个常规文件,抑或因为其他某些原因而无法打开进行读取,则抛出 FileNotFoundException。

参数:

name- 与系统有关的文件名。

抛出:

FileNotFoundException - 如果该文件不存在,或者它是一个目录,而不是一个常规文件,抑或因为其他某些原因而无法打开进行读取。

SecurityException - 如果存在安全管理器,且其 checkRead 方法拒绝对文件进行读取访问。

    FileOutputStream类

其中构造方法:

FileOutputStream(File file)

创建一个向指定 File 对象表示的文件中写入数据的文件输出流。创建一个新FileDescriptor 对象来表示此文件连接。

首先,如果有安全管理器,则用 file 参数表示的路径作为参数来调用 checkWrite 方法。

如果该文件存在,但它是一个目录,而不是一个常规文件;或者该文件不存在,但无法创建它;抑或因为其他某些原因而无法打开,则抛出 FileNotFoundException。

参数:

file- 为了进行写入而打开的文件。

抛出:

FileNotFoundException - 如果该文件存在,但它是一个目录,而不是一个常规文件;或者该文件不存在,但无法创建它;抑或因为其他某些原因而无法打开

SecurityException - 如果存在安全管理器,且其 checkWrite 方法拒绝对文件进行写入访问。

FileOutputStream(String name)

创建一个向具有指定名称的文件中写入数据的输出文件流。创建一个新 FileDescriptor 对象来表示此文件连接。

首先,如果有安全管理器,则用 name 作为参数调用 checkWrite 方法。

如果该文件存在,但它是一个目录,而不是一个常规文件;或者该文件不存在,但无法创建它;抑或因为其他某些原因而无法打开它,则抛出 FileNotFoundException。

参数:

name- 与系统有关的文件名

抛出:

FileNotFoundException - 如果文件存在,但它是一个目录,而不是一个常规文件;或者该文件不存在,但无法创建它;抑或因为其他某些原因而无法打开它

SecurityException - 如果存在安全管理器,且其 checkWrite 方法拒绝对文件进行写入访问。

FileOutputStream(String name, boolean append

创建一个向具有指定 name 的文件中写入数据的输出文件流。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处。创建一个新 FileDescriptor 对象来表示此文件连接。

首先,如果有安全管理器,则用 name 作为参数调用 checkWrite 方法。

如果该文件存在,但它是一个目录,而不是一个常规文件;或者该文件不存在,但无法创建它;抑或因为其他某些原因而无法打开它,则抛出 FileNotFoundException。

参数:

name- 与系统有关的文件名

append- 如果为 true,则将字节写入文件末尾处,而不是写入文件开始处

抛出:

FileNotFoundException - 如果该文件存在,但它是一个目录,而不是一个常规文件;或者该文件不存在,但无法创建它;抑或因为其他某些原因而无法打开它。

SecurityException - 如果存在安全管理器,且其 checkWrite 方法拒绝对文件进行写入访问。

    练习复制一个图片

实现思路:

  1. 用字节读取流对象和图片关联
  2. 用字节写入流对象创建一个图片文件,用于存储取到的图片数据
  3. 通过循环读写完成数据的存储
  4. 关闭资源

实现代码:

import java.io.*;

 

public class CopyPicture

{

    public static void main(String[]args)

    {

        //声明流对象

        FileOutputStreamfos = null;

        FileInputStreamfis = null;

       

        try

        {

            fos = newFileOutputStream("test_copy.jpg");

            fis = newFileInputStream("test.jpg");

           

            byte[] b =new byte[1024];//创建一个字节数组,用于存储读取的数据

           

            int len = 0;   //存储该次读取了多少个字节数据

           

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

            {

                fos.write(b,0, len);   //写入目的地

            }

           

        }catch(Exceptione)

        {

            e.printStackTrace();

        }finally

        {

            try

            {

                if(fis !=null)    //关闭资源

                    fis.close();

            }catch(Exceptione2)

            {

                e2.printStackTrace();

            }

            finally

            {

                try

                {

                    if (fos !=null)

                        fos.close();

                }

                catch(Exception e3)

                {

                    e3.printStackTrace();

                }

            }

        }

    }

}

  转换流练习:通过键盘录入并打印到控制台,将字节流转换成字符流并使用缓冲增强效率

代码实现:

import java.io.*;

 

public class TransStreamTest

{

    public static voidmain(String[] args)

    {

        // 获取键盘录入对象

        InputStreamin = System.in;

       

        //输出对象

        OutputStreamout = System.out;

 

        // 将字节流对象转换成字符流的对象

        InputStreamReaderr = new InputStreamReader(in);

        OutputStreamWriterw = new OutputStreamWriter(out);

 

        // 加入缓冲区,提高效率

        BufferedReaderbr = new BufferedReader(r);

        BufferedWriterbw = new BufferedWriter(w);

 

        String line= null;

 

        try

        {

            while ((line =br.readLine()) !=null)

            {

                //如果输入的是"over"就停止录入

                if ("over".equals(line))

                    break;

               

                bw.write(line.toUpperCase());

                bw.newLine();//换行

                bw.flush();  //刷新

            }

            br.close();

        }

        catch(Exception e)

        {

            e.printStackTrace();

        }

        finally

        {

            try

            {

                if(br !=null)

                    br.close();

            }

            catch(Exception e2)

            {

                e2.printStackTrace();

            }

            try

            {

                if(bw !=null)

                    bw.close();

            }

            catch(Exceptione3)

            {

                e3.printStackTrace();

            }

        }

    }

}

File类

    文件和目录路径名的抽象表示形式.用来将文件或文件夹封装成对象,方便对文件和文件夹的属性信息操作.该对象的出现弥补了流对象的不足(对文件夹的操作,文件属性的操作),流只能操作数据.

    File常见方法

1.    创建:

createNewFile() 在指定位置创建文件,如果该文件存在,则不创建,返回false.和输出流不一样,输出流一建立就创建文件.如果文件存在则会覆盖

    mkdir() 创建文件夹

mkdirs() 创建多级文件夹

2.    删除

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

deleteOnExit() 在程序运行结束时删除指定文件

3.    判断

Exisis() 文件是否存在

isFile() 是否是文件

isDirectory() 是否是目录

isHidden() 是否是一个隐藏文件

isAbsolute() 是否为绝对路径名

4.    获取信息

getName() 获取名称

getPath() 获取路径

getParent() 获取父目录,如果封装的路径中没有父目录则返回null

getAbsolutePath() 获取绝对路径

lastModified() 最后一次修改时间,返回long类型

length() 返回文件的长度long类型

    对文件对象进行判断是否是文件(isFile())或目录(isDirectory())时必须判断该文件对象封装的内容是否存在,通过exists().如没有判断则始终返回false

    练习:列出指定目录下的文件和文件夹

实现代码:

import java.io.*;

 

public class ShowFile

{

    public static voidmain(String[] args)

    {

        // 封装一个文件对象

        File file = new File("e:\\ps\\");

 

        showFile(file);

    }

 

    public static voidshowFile(File f)

    {

        // 是否存在该目录

        if(f.exists())

        {

            System.out.println(f);

            for (File s :f.listFiles())

            {

                if(s.isDirectory() && s.length() > 0)//是否是目录,并且不是空目录

                {

                    showFile(s);    //如果是目录再次调用showFile()方法

                }

                else

                    System.out.println(s);

            }

        }

    }

}

注:递归时注意内存溢出!限定条件

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值