输入输出流

程序在运行期间,可能需要从外部的存储媒介或其他程序中读入所需的数据,这就需要使用输入流。输入流的指向称为它的源,程序通过输入流读取源中的数据。另一方面,程序处理数据后,可能需要将处理的结果写入到永久的存储媒介中或传送给其他的应用程序,这就需要用输出流。输出流的指向称为它的目的地,虽然I/O流经常与磁盘文件存取有关,但是源和目的地也可以是键盘、内存或显示器窗口。

java.io包(I/O流库)提供大量的流类,所有输入流都是抽象类InputStream(字节输入流)或抽象类Reader(字符输入流)的子类,而所有输出流都是抽象类OutputSteam(字节输出流)或抽象类Writer(字符输出流)的子类。

1、File类

File类的对象主要用来获取文件本身的一些信息,例如文件目录、文件长度或文件读写权限等,不涉及对文件的读写操作。

创建一个File对象的构造方法有3个:

  • File(String filename)
  • File(String directoryPath, String filename)
  • File(File dir, String filename)

其中,filename是文件名字,directoryPath是文件的路径,dir为一个目录。使用File(String filename)创建文件时,该文件被认为与当前应用程序在同一目录中。

1、文件的属性

经常使用File类的下列方法获取文件本身的一些信息。

  • public String getName() 获取文件的名字
  • public boolean canRead() 判断文件是否可读
  • public boolean canWrite() 判断文件是否可被写入
  • public boolean exists() 判断文件是否存在
  • public long length() 获取文件的长度(单位是字节)
  • public String getAbsolutePath() 获取文件的绝对路径
  • public String getParent() 获取文件的父目录
  • public boolean isFile() 判断文件是否是一个普通文件,而不是目录
  • public boolean isDirectory() 判断文件是否是一个目录
  • public boolean isHidden() 判断文件是否是隐藏文件
  • public long lastModified() 获取文件最后的修改时间(时间是从1970年午夜至文件最后时刻的毫秒数)

2、目录

1、创建目录

File对象调用方法public boolean mkdir() 创建一个目录,成功返回true。

2、列出目录中的文件

如果File对象是一个目录,那么该对象调用下述方法列出该目录下的文件和子目录。

  • public String[] list()

    • 返回目录下的所有文件
  • public File[] listFiles()

    • 返回目录下的所有文件。

      有时需要列出目录下的指定类型的文件,比如.java、.txt等文件,可以使用File类的下述两个方法,列出指定类型的文件。

    • public String[] list(FilenameFilter obj)

      • 返回目录下指定类型的所有文件
    • public File[] listFiles(FIlenameFilter obj)

      • 返回目录下指定类型的所有文件

上述两个方法的参数FilenameFilter是一个接口,该接口有一个方法:

public boolean accept(File dir,String name);

File对象dirFile调用list方法时,需向该方法传递一个实现FilenameFilter接口的对象,list方法执行时,参数obj不断回调接口方法accept(File dir,String name),该方法中的参数dir为调用list的当前目录dirFile,参数name被实例化为dirFile目录中的一个文件名,返回true时,list方法就将名字为name的文件存放到返回的数组中。

3、文件的创建与删除

当使用File类创建一个文件对象后,

File file = new File("C:\\myletter","letter.txt");

如果C:\myletter目录中没有letter.txt文件,文件对象file调用方法

public boolean createNewFile();

可以在C:\myletter目录建立一个letter.txt文件。文件对象调用方法public boolean delete()可以删除当前文件。

file.delete();

4、运行可执行文件

2、文件字节输入流

使用输入流通常包括4个基本步骤:

  • 设定输入流的源;
  • 创建执行源的输入流;
  • 让输入流读取源中的数据;
  • 关闭输入流。

如果对文件读取需求比较简单,可以用FileInputStream类(文件字节输入流),该类是InputStream类的子类(以字节为单位读取文件),该类的实例方法都是从InputStream类继承而来的。

1、构造方法

可以使用FileInputSteam类的下列构造方法创建指向文件的输出流。

FileInputStream(String name);//创建FileInputSteam流
FileInputStream(File file);

参数name和file指定的文件称为输入流的源。

2、使用输入流读取字节

文件字节流可以调用从父类继承的read方法顺序地读取文件,只要不关闭流,每次调用read方法就顺序的读取文件中的其余内容,知道文件的末尾或文件字节输入流被关闭。

字节输入流的read方法以字节为单位读取源中的数据。

  • int read() 输入流调用该方法从源中读取单个字节的数据,该方法返回字节值(0-255之间的一个整数),如果未读出字节就返回-1
  • int read(byte[] b) 试图读取b.length个字节到字节数组b中,返回实际读取的字节数目。到文件的末尾返回-1。
  • int read(byte[] b, int off, int len) 试图读取 len 个字节到字节数组b中,返回实际读取的字节数目。到文件末尾返回-1,参数off指定从字节数组的某个位置开始存放读取的数据。
注:FileInputStream流顺序地读取,只要不关闭流,每次调用read方法就顺序地读取源中其余地内容,知道源地末尾或流被关闭。

3、关闭流

输入流都提供了关闭方法close(),尽管程序结束时会自动关闭所有打开的流,但这是好习惯。如果没关闭流,就可能不允许另一个程序操作这些流所用的资源。

3、文件字节输出流

可以使用FileOutputStream类(文件字节输出流),它是OutputSteam类的子类(以字节为单位向文件写入内容),该类的实例方法都是从OutputStream类继承来的。

1、构造方法

可以使用FileOutputStream类的下列具有刷新功能的构造方法创建指向文件的输出流。

FileOutputStream(String name);
FileOutputStream(File file);

FileOutputStream输出流开通一个到达文件的通道(目的地就是这个文件,输出流指向这个文件),如果指向的文件不存在,Java就会创建该文件,如果指向的文件已存在,输出流将刷新该文件(使得文件的长度为0).

可以使用 FileOutputStream类的下列能选择是否具有刷新功能的构造方法创建指向文件的输出流

FileOutputStream(String name,boolean append);
FileOutputStream(File file,boolean append)

当用构造方法创建指向一个文件的输出流时,如果参数append取值true,输出流不会刷新所指向的文件(假如文件已存在),输出流的write的方法将从文件的末尾开始向文件写入数据,参数append取值false,输出流将刷新所指向的文件(假如文件已存在)。

2、使用输出流写字节

文件字节流可以调用从父类继承的write方法顺序地写文件。FileOutputStream流顺序地写入文件,即只要不关闭流,每次调用write方法就顺序地向文件写入内容,直到流被关闭。

  • void write(int n) 写入单个字节
  • void write(byte[] b) 写入一个字节数组
  • void write(byte[] b,int off,int len) 给定字节数组中起始与偏移量off处取len个字节写入
  • void close() 关闭输出流

3、关闭流

调用close()方法,可以保证操作系统把流缓冲区地内容写到目的地,即关闭输出流可以把该流所用缓冲区地内容冲洗掉(通常冲洗到磁盘空间上)

4、文件字符输入、输出流

文件字节输入、输出流的read和write方法使用字节数组读写数据,即以字节为单位处理数据。因此,字节流不能很好地操作Unicode字符,例如,一个汉字在文件中占用两个字节,如果使用字节流,读取不当会出现“乱码”现象。

与FileInputStream、FileOutputStream字节流相对应地是FileReader、FileWriter字符流(文件字符输入、输出流),FileReader和FIleWriter分别是Reader和Writer的子类,其构造方法分别是:

FileReader(String filename);   				 FileReader(File filename);
FileWriter(String filename);   				 FileWriter(File filename);
FileWriter(String filename,boolean append);  FileWriter(File filename,boolean append);

字符输出流和输出流的read和write方法使用字符数组读写数据,即以字符为基本单位处理数据。

注:对于Writer流,writer方法将数据首先写入到缓冲区,每当缓冲区溢出时,缓冲区的内容被自动写入到目的地,如果关闭流,缓冲区的内容会立刻被写入到目的地。流调用flush()方法可以立刻冲洗当前缓冲区,即将当前缓冲区的内容写入到目的地。

5、缓冲流

BufferedReaderBufferedWriter类创建的对象称为缓冲输入、输出流,二者增强了读写文件的能力。

两者的源和目的地必须是字符输入流字符输出流

构造方法:

BufferedReader(Reader in);
BufferedWriter(Writer out);

BufferedReader流能读取文本行,方法 readLine()。

通过向BufferedReader传递一个Reader子类的对象(如FileReader的实例),来创建一个BufferedReader对象,如:

FileReader inOne = new FileReader("Student.txt");
BufferedReader inTwo = new BUfferedReader(inOne);

然后inTwo流调用readLine()方法中读取Student.txt,例如

String strLine = inTwo.readLine();

类似的,可以将BufferedWriter流和FileWriter流连接在一起,然后使用BufferedWriter流将数据写到目的地,例如:

FileWriter tofile = new FileWriter("hello.txt");BufferedWroter out = BufferedWriter(tofile);

然后out使用BufferedReader类的方法writer(String s,int off,int len)把字符串s写到hello.txt中,参数off是s开始处的偏移量,len是写入的字符数量。

BufferedWriter流有一个独特的向文件写入一个回行符的方法

newLine();

可以把BufferedReader和BufferedWriter称为上层流,把它们指向的字符流称为底层流,Java采用缓存技术将上层流和底层流连接。底层字符输入流首先将数据读入缓存,BufferedReader流再从缓存读取数据;BufferedWrirter流将数据写入缓冲,底层字符输出流会不断地将缓冲中的数据写入到目的地。当BufferedWriter流调用flush()刷新缓冲或调用close()方法关闭时,即使缓冲没有基础,底层流也会立刻将缓存地内容写入目的地。

注:关闭输出流时要首先关闭缓冲输出流,然后关闭缓冲输出流指向的流,即先关闭上层流再关闭底层流。再编写代码时指向关闭上层流,那么上层流的底层流将自动关闭。

6、随机流

通过该流能读文件也能写文件。

RandomAccessFile类创建的类被称为随机流,与前面不同的是,RandomAccessFile类既不是InputStream类的子类,也不是OutputStream类的子类,RandomAccessFile类创建的流的指向既可以作为流的源,也可以作为流的目的地。

构造方法:

  • RandomAccessFile(String name, String mode) 参数name用来确定一个文件名,给出创建的流的源,也是流的目的地。参数mode取r(只读)或 rw(可读写),决定创建的流对文件的访问权利。
  • RandomAccessFile ( File file, String mode)

注:RandomAccessFile流指向文件时,不刷新文件。

RandomAccessFile类中有一个方法seek(long a) 用来定位RandomAccessFile流的读写位置,其中参数 a 确定读写位置距离文件开头的字节个数。另外流还可以调用 getFIlePointer() 方法获取流的当前读写位置。RandomAccessFile流对文件的读写比顺序读写更灵活。

RandomAccessFile类的常用方法

方法描述
close()关闭文件
getFilePointer()获取当前读写的位置
length()获取文件长度
read()从文件读取一个字节的数据
readBoolean()从文件读取一个布尔值,0代表false,其他值代表true
readByte()从文件读取一个字节
readChar()从文件中读取一个字符(2个字节)
readDouble()从文件读取一个双精度浮点值(8个字节)
readFloat()从文件读取一个单精度浮点值(4个字节)
readFully(byte[] b)读b.length()字节放入数组b,完全填满该数组
readInt()从文件读取一个int值(4个字节)
readLine()从文件读取一个文本行
readLong()读取一个长整型(8个字节)
readShort()读取一个短型值(2个字节)

需要注意的是,RandomAccessFile流的readLine()方法在读取含有非ASCII字符的文件时(比如有汉字)会出现乱码,因此,需要把readLine()读取的字符串用“iso-8859-1”编码重新编码存放到byte数组中,然后再用当前机器的默认编码将该数组转化为字符串,操作如下。

1、读取

String str = in.readLine();

2、用“iso-8859-1”重新编码

byte[] b = str.getBytes("iso-8859-1");

如果机器的默认编码是“GB2312”,那么

String content = new String(b);

等同于

String content = new String(b,"GB2312);

7、数组流

流的源和目的地除了可以是文件外,还可以是计算机内存

1、字节数组流

字节数组输出流ByteArrayInputStream和字节数组输出流ByteArrayOutputStream分别使用字节数组作为流的源和目的地。

ByteArrayInputStream的构造方法:

ByteArrayInputStream(byte[] buf);ByteArrayInputStream(byte[] buf, int offset, int length);

第一个构造方法的源:buf指定的数组的全部字节单元。

第二个构造方法的源:buf指定的数组从offset处按顺序取得length个字节单元。

字节数组输出流:

调用public int read();方法可以顺序地从源中读出一个字节,该方法返回读出的字节值;

public int read(byte[], int off, int len) 方法可以顺序地从源中读出参数指定地字节数,并将读出的字节存放到参数b指定的数组中,参数off指定数组b存放读出字节的起始位置,该方法返回实际读出的字节个数。如果未读出字节read方法返回 -1,

ByteArrayOutputStream流的构造方法:

ByteArrayInputStream();ByteArrayInputStream(int size);

第一个构造方法:构造的字节数组输出流指向一个默认大小为32字节的缓冲流,如果输出流向缓冲区写入的字节个数大于缓冲区时,缓冲区的容量会自动增加。

第二个构造方法:构造的字节数组输出流指向的缓冲区的初始大小由参数size指定,如果输出流向缓冲区写入的字节个数大于缓冲区时,缓冲区的容量会自动增加。

字节数组输出流:

调用public void writer(int b) 可以顺序地向缓冲区写入一个字节;

public void write(byte[] b, int off, int len) 将参数b中指定的len个字节顺序地写入缓冲区,参数off指定从b中写出的字节的起始位置 ;

public byte[] toByteArray() 返回输出流写入到缓冲区的全部字节;

2、字符数组流

与字节数组流对应的是字符数组流CharArrayReader和CharArrayWriter类,字符数组流分别使用字符数组作为流的源和目标。

8、数据流

DataInputStream和DataOutputStream类创建的对象称为数据输入流和数据输出流。这两个流很有用,它们允许程序按着机器无关的风格读取Java原始数据。也就是说,当读取一个数值时,不必再关心这个数值应当是多少个字节。

DataInputStream和DataOutputStream的构造方法:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值