第10章 输入、输出流
从外部的储存媒介或其他程序中读入所需要的数据,需要输入流,输入流的指向为它的源。
将处理的结果写入永久的储存媒介中或传送给其他的应用程序,需要输出流。输出流的指向称为它的目的地。
java.io包(I/O流库)提供大量的流类,所有输入流都是抽象类InputStream(字节输入流)或抽象类Reader(字符输入流的子类),所有输出流都是抽象类OutputStream(字节输出流)或抽象类Writer(字符输出流)的子类。
10.1 File类
需要获取磁盘上的文件的有关信息或在磁盘上创建新的文件等,这就需要File类。
File类的对象主要用来获取文件本身的一些信息,例如文件的所在的目录、文件的长度或文件的读写权限等,不涉及对文件的读写操作。
创建一个File对象的构造方法有3个:
File(String filename)
File(String directoryPath,String filename)
File(File dir,String filename)
filename是文件名,directoryPath是文件路径,dir为一个目录。使用File(String filename)创建文件时,该文件被认为与当前应用程序在同一目录。
10.1.1 File的方法:
-
- public String getName() 获取文件的名字。
- public boolean canRead() 判断文件是否是可读的。
- public boolean canWrite() 判断文件是否可被写入。
- public boolean exits() 判断文件是否存在。
- public long length() 获取文件的长度(单位是字节)。
- public String getAbsolutePath() 获取文件的绝对路径。
- public String getParent() 获取文件的父目录。
- public boolean isFile() 判断文件是否是一个普通文件,而不是目录。
- public boolean isDirectroy() 判断文件是否是一个目录。
- public boolean isHidden() 判断文件是否是隐藏文件。
- public long lastModified() 获取文件最后修改的时间。
10.1.2 目录
File对象调用方法public boolean mkdir()创建一个目录,如果创建成功返回ture。
如果File对象是一个目录,那么该对象调用下述方法列出该目录的文件和子目录。
-
- public String[] list() 用字符串形式返回目录下的全部文件。
- public File [] listFiles() 用File对象形式返回目录下的全部文件。
- public String[] list(FilenameFilter obj) 用字符串形式返回目录下的指定类型的所有文件。
- public File [] listFiles(FilenameFilter obj) 用File对象形式返回目录下的指定类型所有文件。
- 上述两方法的参数FilenameFilter是一个接口,该接口有一个方法:
- public boolean accept(File dir,String name);
File对象dirFile调用list方法时,需要该方法传递一个实现FilenameFilter接口的对象,list方法执行时,参数obj不断回调接口方法accept(File dir,Stirng name),该方法中的dir为调用list的当前目录dirFile,参数name被实例化为dirFile目录中的一个文件名,当接口方法返回ture时,list方法就将名字name的文件存放返回的数组中。
10.1.3 文件的创建与删除
当使用File类创建一个文件对象后,例如
-
- File file=new File("c:\\myletter","letter.txt");
- 如果c:\myletter目录中没有名字为letter.txt文件,文件对象file调用方法public boolean createNewFile();
- 文件对象调用方法 public boolean delete()可以删除当前文件,
- 例如:file.delete();
10.1.4运行可执行文件
当要执行一个本地机器上的可执行文件时,可以使用java.lang包中的Runtime类。使用getRuntime静态方法创建对象。
例如:
Runtime ec = Runtime.getRuntime();
ec调用exec(String command)方法打开本地机器上的可执行文件或执行一个操作。
10.2 文件字节输入流
使用输入流通常包括下列4个步骤:
-
- 设定输入流的源
- 创建指向流的输入流
- 让输入流读取源中的数据
- 关闭输入流
如果对文件读取需求比较简单,那么使用FileInputStream类(文件字节输入流),该类是InputStream类的子类。
构造方法:
FileInputStream(String name)
FileInputStream(File file)
第一个构造方法使用给定的文件夹名name创建FileInputStream流,第二个构造方法使用File对象创建FileInputStream流。
创建输入流时,可能会出现异常,因此必须在try-catch语句的try部分创建输入流创建输入流,在catch(捕获)块检测并处理异常。
使用输入流读取字节
输入流的目的是提供读取源中数据的通道,出现可以通过这个跳刀读取源中的数据。
字节输入流的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方法就顺序读取源中其余的内容,直到源的末尾或流被关闭。
关闭流:close(),虽然程序结束时,会自动关闭所有流,但显式关闭输入流是一个良好的习惯。
10.3 文件字节输出流
- 使用输出流通常包括4个基本步骤:
(1)给出输出流的目的地
(2)创建指向目的地的输出流
(3)让输出流把数据写入到目的地
(4)关闭输出流。
使用FileOutputStream类的下列具有刷新功能的构造方法创建指向文件的输出流。
FileOutputStream(String name);/FileOutputStream(String name,boolean append)
FileOutputStream(File file);/ FileOutputStream(File file,boolean append)
其中:参数name和file指定的文件称为输出流的目的地,append取值为true,输出流不会刷新所指向的文件,而是在文件末尾写入。
第一个构造方法使用给定的文件夹名name创建FileOutputStream流,第二个构造方法使用File对象创建FileOutputStream流。
如果输出流不存在,则创建文件,如果存在,刷新该文件(使文件长度为0)
创建输出流时,可能会出现异常,因此必须在try-catch语句的try部分创建输出流,在catch(捕获)块检测并处理异常。
输出流的write方法以字节单位向目的地写数据。
void write(int n) 向目的地写入单个字节。
void write(byte b[]) 向目的地写入一个字节数组。
void write(byte b[],int off,int len) 从字节数组中偏移量off处取len个字节写到目的地。
void close()关闭输出流,通过调用close()方法,可以保证操作系统把流缓冲区的内容写到它的目的地,即关闭输出流可以把该流所用的缓冲区的内容冲洗掉(通常冲洗到磁盘文件上)。
FileOutputStream流顺序地写文件,只要不关闭流,每次调用write方法就顺序地向目的地写入内容,直到流被关闭。
10.4 文件字符输入、输出流
FileReader、FileWriter字符流(文件字符输入、输出流)
流调用flush()方法可以立刻冲洗当前缓冲区,即将当前缓冲区的内容写入目的地。
10.5 缓冲流
BufferdReader和BufferedWriter类创建的对象称为缓冲输入、输出流。
- 构造方法:
- BufferedReader(Reader in);
- BufferedWriter (Writer out);
- 2.BufferedReader和BufferedWriter类读写文件的方法:
- readLine() 读取文本行
- write(String s,int off,int len) 把字符串s写到文件中
- newLine(); 向文件写入一个回行符
10.6随机流
- 使用RandomAccessFile类来创建一个随机访问文件流。RandomAccessFile类创建的流的指向既可以作为源也可以作为目的地。
- 构造方法:
- RandomAccessFile(String name,String mode) ;
- RandomAccessFile(File file,String mode) ;
- 相关方法:
1.读取 String str=in.readLine();
2.用“iso-8859-1”重新编码 byte b[]=str.getBytes("iso-8859-1");
3.使用当前机器的默认编码将字节数组转化为字符串
String content=new String(b);
1.字节数组流
- 字节数组输入流ByteArrayInputStream和字节数组输出流ByteArrayOutputStream分别使用字节数组作为流的源和目标。
- ByteArrayInputStream构造方法及常用方法
- ByteArrayInputStream(byte[] buf);
- ByteArrayInputStream(byte[] buf,int offset,int length);
- public int read();顺序地从源中读出一个字节
- public int read(byte[] b,int off,int len);顺序地从源中读出参数len指定的字节数
- ByteArrayOutputStream流构造方法及常用方法
- ByteArrayOutputStream();
- ByteArrayOutputStream(int size);
- public void write(int b); 顺序地向缓冲区写入一个字节
- public void write(byte[] b,int off,int len); 将参数b中指定的len个字节顺序地写入缓冲区
- public byte[] toByteArray(); 返回输出流写入到缓冲区的全部字节
2.字符数组
-
- CharArrayReader和CharArrayWriter类是字符数组流,使用字符数组作为流的源和目标。例子10 向内存(输出流的缓冲区)写入字符串 。
10.8数据流
- DataInputStream和DataOutputStream类创建的对象称为数据输入流和数据输出流。
- 构造方法:
- DataInputStream(InputStream in)创建的数据输入流指向一个由参数in指定的底层输入流
- DataOutputStream(OutnputStream out)创建的数据输出流指向一个由参数out指定的底层输出流
10.9 对象流
- ObjectInputStream和ObjectOutputStream类创建的对象称为对象输入流和对象输出流。
- 它的构造方法是:
- ObjectInputStream(InputStream in)
- ObjectOutputStream(OutputStream out)
- 相关方法:
- writeObject(Object obj) 将一个对象obj写入到一个文件
- readObject() 读取一个对象到程序中
- 所谓序列化:一个类如果实现了Serializable接口,那么这个类创建的对象就是所谓序列化的对象。
10.10 序列化与对象克隆
- 如果一个“复制品”实体的变化不会引起原对象实体发生变化,反之亦然。这样的复制品称为原对象的一个克隆对象或简称克隆。
- 一个对象调用clone()方法就可以获取该对象的克隆对象。
- 对象输入流通过对象的序列化信息来得到当前对象的一个克隆。
10.11 使用Scanner解析文件
使用Scanner类和正则表达式来解析文件。
1.使用默认分隔标记解析文件
创建Scanner对象,并指向要解析的文件,例如:
File file = new File("hello.java");
Scanner sc = new Scanner(file);
sc将空白作为分隔标记
相关方法 next()依次返回file中的单词
hasNext()判断file最后一个单词是否已被next()方法返回.
2.使用正则表达式作为分隔标记解析文件 : 创建Scanner对象,指向要解析的文件,并使用useDelimiter方法指定正则表达式作为分隔标记,例如:
File file = new File("hello.java");
Scanner sc = new Scanner(file);
sc.useDelimiter(正则表达式);
sc将正则表达式作为分隔标记
相关方法 next() 依次返回file中的单词
hasNext() 判断file最后一个单词是否已被next()方法返回
10.14 文件锁
- FileLock、FileChannel类处理Java提供的文件锁功能。它们分别在java.nio和java.nio.channels包中。
- 输入、输出流读写文件时可以使用文件锁。
- RondomAccessFile创建的流在读写文件时使用文件锁的步骤如下:
1.先使用RondomAccessFile流建立指向文件的流对象,该对象的读写属性必须是rw,例如:
RandomAccessFile input=new
RandomAccessFile("Example.java","rw");
2.input流调用方法getChannel()获得一个连接到地层文件的FileChannel对象(信道),例如
FileChannel channel=input.getChannel();
3.信道调用tryLock()或lock()方法获得一个FileLock(文件锁)对象,这一过程也称作对文件加锁.
例如:FileLock lock=channel.tryLock();