输入/输出(I/O)操作的例子包括:
- 创建和删除文件
- 从一个文件或者网络套接字中读取内容,或者向其写入内容
- 把对象序列化(或保存)到持久内存中,并且获取保存的对象
使用过旧的File类就会发现他的很多方法都无法抛出异常,delete方法常常工作失败但原因非常让人费解,rename方法也无法在不同的操作系统上一致的工作。所以JDK引入了一组名为NIO.2的包,作为技术补充,这些新的类型和子包能在java.nio.file中找到。其中的Path接口用来取代java.io.File类,好在后者现在已经被废弃了。
需要注意的是Files中对于读取和写入只支持较小的文件,所以对于较大的文件就需要使用一个流。流包括以下四种:InputStream,OutputStream,Reader和Writer。同时我们会遇到一些类来包装这些流和在读写时缓存数据。当对流进行读写操作时要求必须是顺序的,对于非顺序的操作,可以使用java.io.RandomAccessFile或者java.nio.channels.SeekableByteChannel。
1.
文件系统和路径
在JAVA中的文件或者路径是使用java.io.File对象表示的,但它有很多缺陷,建议使用java.nio.Path替代。常用的FileSystem类就是在后者中。下面介绍一点该类常用的函数。
FileSystem filesyatem = FileSyatem.getDefault();//返回当前文件系统
Path Path= Paths.get("/home/images");//创建一个Path实例
path.getName(0);//返回home
2.
文件的读写
Files类提供了从一个小的二进制文件或文本文件读写内容的方法。readAllBytes和readAllLines分别中一个二进制文件和文本文件读取内容。返回类型分别为byte[] 和List<String
>。
下面是一个实例:
Path path = Paths.get("C://speech.txt");
Charset charset = Charset.forName("US-ASCII");//当针对字节编码和字节解码的时候需要制定使用的字符集
String str1 = "String1";
String str2 = "String";
List<String> lines = Arrays.asList(str1,str2);
try{
Files.write(path,lines,charset);//写入
}catch(Exception e){
e.printStackTrace();
}
//读回
List<String> linesRead = null;
try{
linesRead = Files.readAllLines(path,charset);
}catch(Exception e){
e.printStackTrace();
}
if(linesRead!=null){
for(String str:linesRead)
System.out.print(str);
}
再次提醒,read和write方法自适用于较小的文件,大一点的使用流来替代。
3.输入/输出流
数据可以分为二进制和字符,对应
I/O流也分别有两种
·Reader,从一个池中读取字符的流
·Writer,向一个池中写入数据的流
·InputStream,从一个池中读取二进制数据的流
·OutputStream,向一个池写入二进制数据的流。
使用流,个人受益很多的是他的方法,不管什么数据源和目标都能实现。
4.读二进制数据
从NIO.2之后,就可以调用Files.newInputStream从一个文件池获取InputStream。下面是一个模板代码:
Path path = ...;
try(InputStraem is = Files.newInputStream(path,StanderdOpenOption.READ);
BufferInputStream buffer = new BufferInputStream(is)){
...
}catch(Exception e){
...
}
由于InputStream实现了AutoCloseable,因此在try—catch语句中不需要显式的关闭它。否者一定要用流的close方法来关闭流。
InputStream类中的的read方法一共有三种:
第一个无参数的是最好用的,他从InputStream中每次读取一个字节,并且返回一个int型值,再把这个值强制转换为byte类型,结合while语句块保持循环就可以读取文件。
int i = inputStream.read();
while(i!=-1){
byte b = (byte)i;
...
i = inputStream.read();
}
如果inputStream1和inputStream2分别读取两个文件的流,通过下面代码就可以比较两个文件内容是否相同:
int n,m;
do{
n = inputstream1.read();
m = inputstream2.read();
if(n!=m){
return false;
}
}while(n!=-1)
return true;
5.写二进制数据
介绍过了InputStream,同理OutputStream的相关内容类比即可,不在介绍。
下面展示一个复制文件的范例:
byte[] reads = new byte[1024];//存储InputStream读取的数据
try(InputStream is = Files.newInputStream(originPath,,StandardOpenOption.Read);
OutputStream os =Files.newOutputStream(destinationPath,,StandardOpenOption.CREATE)){
int i = is.read(reads);
while(i!=-1){
os.write(reads,0,i);
i = is.read(reads);
}
}catch(Exception e){
....
}