Java编程那些事儿87——文件操纵之读取文件
副标题#e#
11.3.1.3 读取文件
固然前面先容了流的观念,可是这个观念对付初学者来说,照旧较量抽象的,下面以实际的读取文件为例子,先容流的观念,以及输入流的根基利用。
凭据前面先容的常识,将文件中的数据读入措施,是将措施外部的数据传入措施中,应该利用输入流——InputStream或Reader。而由于读取的是特定的数据源——文件,则可以利用输入对应的子类FileInputStream或FileReader实现。
在实际书写代码时,需要首先熟悉读取文件在措施中实现的进程。在Java语言的IO编程中,读取文件是分两个步调:1、将文件中的数据转换为流,2、读取流内部的数据。个中第一个步调由系统完成,只需要建设对应的流工具即可,工具建设完成今后步调1就完成了,第二个步调利用输入流工具中的read要领即可实现了。
利用输入流举办编程时,代码一般分为3个部门:1、建设流工具,2、读取流工具内部的数据,3、封锁流工具。下面以读取文件的代码示例:
import java.io.*;
/**
* 利用FileInputStream读取文件
*/
public class ReadFile1 {
public static void main(String[] args) {
//声明流工具
FileInputStream fis = null;
try{
//建设流工具
fis = new FileInputStream("e:\\a.txt");
//读取数据,并将读取到的数据存储到数组中
byte[] data = new byte[1024]; //数据存储的数组
int i = 0; //当前下标
//读取流中的第一个字节数据
int n = fis.read();
//依次读取后续的数据
while(n != -1){ //未达到流的末端
//将有效数据存储到数组中
data[i] = (byte)n;
//下标增加
i++;
//读取下一个字节的数据
n = fis.read();
}
//理会数据
String s = new String(data,0,i);
//输出字符串
System.out.println(s);
}catch(Exception e){
e.printStackTrace();
}finally{
try{
//封锁流,释放资源
fis.close();
}catch(Exception e){}
}
}
}
在该示例代码中,首先建设一个FileInputStream范例的工具fis:
fis = new FileInputStream("e:\\a.txt");
这样成立了一个毗连到数据源e:\a.txt的流,并将该数据源中的数据转换为流工具fis,今后措施读取数据源中的数据,只需要从流工具fis中读取即可。
读取流fis中的数据,需要利用read要领,该要领是从InputStream类中担任过来的要领,该要领的浸染是每次读取流中的一个字节,假如需要读取流中的所有数据,需要利用轮回读取,当达到流的末端时,read要领的返回值是-1。
在该示例中,首先读取流中的第一个字节:
int n = fis.read();
并将读取的值赋值给int值n,假如流fis为空,则n的值是-1,不然n中的最后一个字节包括的时流fis中的第一个字节,该字节被读取今后,将被从流fis中删除。
#p#副标题#e#
然后轮回读取流中的其它数据,假如读取到的数据不是-1,则将已经读取到的数据n强制转换为byte,即取n中的有效数据——最后一个字节,并存储到数组data中,然后挪用流工具fis中的read要领继承读取流中的下一个字节的数据。一直这样轮回下去,直到读取到的数据是-1,也就是读取到流的末端则轮回竣事。
这里的数组长度是1024,所以要求流中的数据长度不能高出1024,所以该示例代码在这里具有必然的范围性。假如流的数据个数较量多,则可以将1024扩大到符合的个数即可。
颠末上面的轮回今后,就可以将流中的数据依次存储到data数组中,存储到data数组中有效数据的个数是i个,即轮回次数。
其实停止到这里,IO操纵中的读取数据已经完成,然后再凭据数据源中的数据名目,这里是文件的名目,理会读取出的byte数组即可。
该示例代码中的理会,只是将从流工具中读取到的有效的数据,也就是data数组中的前n个数据,转换为字符串,然后举办输出。
在该示例代码中,只是在catch语句中输出异常的信息,便于代码的调试,在实际的措施中,需要按照环境举办必然的逻辑处理惩罚,譬喻给出提示信息等。
最后在finally语句块中,封锁流工具fis,释放流工具占用的资源,封锁数据源,实现流操纵的竣事事情。
上面具体先容了读取文件的进程,其实在实际读取流数据时,还可以利用其它的read要领,下面的示例代码是利用别的一个read要领实现读取的代码:
#p#分页标题#e#
import java.io.FileInputStream;
/**
* 利用FileInputStream读取文件
*/
public class ReadFile2 {
public static void main(String[] args) {
//声明流工具
FileInputStream fis = null;
try{
//建设流工具
fis = new FileInputStream("e:\\a.txt");
//读取数据,并将读取到的数据存储到数组中
byte[] data = new byte[1024]; //数据存储的数组
int i = fis.read(data);
//理会数据
String s = new String(data,0,i);
//输出字符串
System.out.println(s);
}catch(Exception e){
e.printStackTrace();
}finally{
try{
//封锁流,释放资源
fis.close();
}catch(Exception e){}
}
}
}
该示例代码中,只利用一行代码:
int i = fis.read(data);
就实现了将流工具fis中的数据读取到字节数组data中。该行代码的浸染是将fis流中的数据读取出来,并依次存储到数组data中,返回值为实际读取的有效数据的个数。
利用该中方法在举办读取时,可以简化读取的代码。
虽然,在读取文件时,也可以利用Reader类的子类FileReader举办实现,在编写代码时,只需要将上面示例代码中的byte数组替换成char数组即可。
利用FileReader读取文件时,是凭据char为单元举办读取的,所以更适合于文本文件的读取,而对付二进制文件或自界说名目标文件来说,照旧利用FileInputStream举办读取,利便对付读取到的数据举办理会和操纵。
读取其它数据源的操纵和读取文件雷同,最大的区别在于成立流工具时选择的类差异,而流工具一旦成立,则根基的读取要领是一样,假如只利用最根基的read要领举办读取,则利用根基上是一致的。这也是IO类设计的初志,使得对付流工具的操纵保持一致,简化IO类利用的难度。