Inputstream、Outputstream:
- IO流,将不同的输入输出,以相同的方式 *** 作read(),write();创建不同类型的流,有不同的实现方式,不同类型的流,又有各自特有的 *** 作方式。
- 无论内部如何工作,所有IO流呈现的都是相同的,简单的模式,程序中流入或流出的一系列数据。
资源对象的关闭:
- 输入流,输出流的 *** 作超类,支持子类以基本字节的方式 *** 作二进制数据
- java.io.InputStream抽象类:基本子类,ByteArrayInputStream,FileInputStream等;
- int read() throws IOException,抽象方法由具体子类实现,返回流中下一字节(必然是0-255之间的整数表示),如果到达流末没有可读字节,返回-1.
- java.io.OutputStream抽象类:基本子类,ByteArrayOutputStream,FileOutputStream等;
- void write(int b) throws IOException 抽象方法。将十进制按字节写入输出流。
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Paths; public class TestIO { public static void main(String[] args) { try { getByteStreams(); } catch (IOException e) { e.printStackTrace(); } } public static void getByteStreams()throws IOException { FileInputStream in=new FileInputStream("C:/Users/yu/Desktop/a.txt"); FileOutputStream out=new FileOutputStream("C:/Users/yu/Desktop/b.txt"); int c; while((c=in.read())!=-1){ System.out.println("读取字节的10进制整数:"+c); out.write(c); } in.close();//有个问题就在于一旦异常了资源就无法关闭; out.close(); } }
基于字符数组缓冲区的IO *** 作处理:
资源文件的关闭:资源文件,比如IO流不会像其他对象,因失去引用而自动释放占用的资源,因此,必须被正确的关闭,否则会导致内存的溢出,以IO流为例,为确保无论是否出现异常,资源均被关闭,应在finally块中手动关闭资源,但这样会让程序中有大量的冗余 ;
解决办法:引入java.lang.AutoCloseable接口,任何实现AutoCloseable接口的类型,均是支持自动关闭的资源类型。然后采用try-with-resources,在try语句中,声明需要关闭的资源,从而保证,无论try块是否引发异常,资源在try块结束后自动关闭(Java7) ;
java.io.Closeable接口继承AutoCloseable接口。原全部需要手动调用close()方法关闭的资源,全部支持try-with-resources自动关闭。
try-with-resources语句,极大的简化了资源处理代码,使开发者无需关心资源状态,无需关心资源对象的创建顺序,无需关心资源对象的正确关闭方式
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Paths; public class TestIO { public static void main(String[] args) { getByteStreams(); } public static void getByteStreams() { try (FileInputStream in = new FileInputStream("C:/Users/yu/Desktop/a.txt"); FileOutputStream out = new FileOutputStream("C:/Users/yu/Desktop/b.txt");) { int c; while ((c = in.read()) != -1) { System.out.println("读取字节的10进制整数:" + c); out.write(c); } in.close();//有个问题就在于一旦异常了资源就无法关闭; out.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
注意:
(1)资源的自动关闭,与异常无关。异常改怎么处理依然怎么处理。
(2)在try语句中声明使用资源后,执行顺序:
无异常,在try块执行后,自动关闭资源,finally块
- 有异常,自动关闭资源,catch块,finally块
路径:
- 前面说的基于单字节的基本read()/write()方法,仅用于理解IO流执行过程,实际开发不会使用。用的是基于字节数组缓冲区的IO *** 作方法:
int read(byte[] b),InputStream中声明的方法,将流中字节读取到字节数组b中,第1个字节置入数组0位置…,直到读取到数组b长度的字节位置为止;返回读取的字节长度;如果没有可读字节,返回-1。
- write(byte[] b, int off, int len),OutputStream中声明的方法,从字节数组b,off位置开始读取,至长度len结束;
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Paths; public class TestIO { public static void main(String[] args) { getByteStreams(); } public static void getByteStreams() { try (FileInputStream in = new FileInputStream("C:/Users/yu/Desktop/a.txt"); FileOutputStream out = new FileOutputStream("C:/Users/yu/Desktop/b.txt");) { byte []buffer=new byte[2]; int len=0; while((len=in.read(buffer))!=-1){ out.write(buffer,0,len); } in.close();//有个问题就在于一旦异常了资源就无法关闭; out.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
Files工具类:
绝对路径,始终包含根元素和查找文件所需的完整目录列表。 例如,D:/test/a.txt。找到文件所需的所有信息都包含在路径声明中
相对路径,例如,a.txt。没有更多信息,程序将无法访问。即,相对路径,最终也必须基于绝对路径描述。
为什么用NIO:
Java.io.File类,包含耦合了文件路径声明,以及文件 *** 作方法的类;且是同步阻塞的
NIO2 (java8),将文件路径与文件 *** 作,分离;且支持异步非阻塞
java.nio.file.Path接口,表示系统文件/目录的绝对的/相对的路径
java.nio.file.Files工具类,包含处理文件 *** 作的方法,包括文件的,创建,删除,复制,移动等
Path接口:Path代表一个不依赖于系统的文件路径。即运行在不同 *** 作系统下,Path的具体实现不同(windows/linux),但开发者仅需面向Path描述路径,不同系统,而无需关心 *** 作系统差异。
Path get(String path):最常用的方法,把转换路径字符串转为Path对象。
Path定义了许多获取文件数据信息的方法及路径的拼接方法:
Path getFileName(),返回文件名或名称元素序列的最后一个元素。即,最后一个路径描述,可能是文件名也可能是目录名
Path getParent(),返回父目录的路径
Path getRoot(),返回路径的根
Path resolve(Path other)方法,将路径拼接为一个新路径
boolean equals(Object obj):重写了equals判断路径是否相同
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; public class TestIO { public static void main(String[] args) { Path p= Paths.get("C:/Users/yu/Desktop"); Path p1=Paths.get("a.txt"); System.out.println(p.getClass().getName());//Path是一个接口输出实现类的名字 System.out.println(p); System.out.println(p.getFileName());//返回文件名或名称元素序列的最后一个元素。即,最后一个路径描述,可能是文件名也可能是目录名 System.out.println(p.getParent());//返回父目录的路径 System.out.println(p.getRoot());//返回路径的根 p.resolve(p1);//将路径拼接为一个新路径 p.equals(p1);//重写了equals判断路径是否相同 } }
java.nio.file.Files工具类,提供了丰富的基于Path *** 作的静态方法,读取/写入/ *** 作,文件与目录。方法分类:
文件或目录的判断:
boolean exists(Path path)/notExists(Path path),Path路径是否存在
Boolean isDirectory(Path path),path是否为目录
文件或目录的创建:
Path createDirectory(Path dir) throws IOException。目录路径已存在则异常;目录路径为多级目录,异常
Path createDirectories(Path dir) throws IOException。自动创建多级不存在目录;目录已存在,无异常
Path createFile(path) throws IOException。基于指定路径,创建文件。文件存在,异常
文件或目录的复制:
Path copy(Path source, Path target, CopyOption... options) throws IOException,将文件复制到目标文件。默认,如果文件已经存在,异常
如果source为目录,不会复制里面的文件,仅相当于创建一个空目录
java.nio.file.StandardCopyOption枚举,实现了CopyOption接口,复制选项
文件或目录的移动:
Path move(Path source, Path target, CopyOption... options) throws IOException,将文件移动或重命名为目标文件。
默认,如果目标文件存在,则异常,可通过options参数声明移动选项
如果在本目录下移动,相当于文件改名
文件或目录的删除:
void delete(Path path) throws IOException。删除指定路径;路径不存在,异常
boolean deleteIfExists(Path path) throws IOException。路径不存在,不删除。返回是否删除成功
如果路径为目录,目录中包含文件(即不为空),2种删除均异常
指定路径的遍历(Files的方法):
Stream
walk(Path start, int maxDepth) throws IOException:遍历,基于指定深度遍历path路径中的目录和文件 Stream
walk(Path start) throws IOException:遍历path路径中的所有目录和文件,包括子目录的,观察遍历时的输出顺序,按层次输出的。注意返回值是流,后面可以用流的 *** 作,比如过滤,排序等功能。可以借助于此方法删除非空目录 import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.function.Consumer; public class TestIO { public static void main(String[] args) { try { path(); } catch (IOException e) { e.printStackTrace(); } } public static void path() throws IOException { Path p= Paths.get("C:/Users/yu/Desktop"); Path p1=Paths.get("a.txt"); Path p2=Paths.get("C:/Users/yu/Desktop/b.txt"); Path p3=Paths.get("C:/Users/yu/Desktop/a.txt"); // System.out.println(Files.exists(p));//Path路径是否存在 // System.out.println(Files.isDirectory(p));//path是否为目录 // System.out.println(Files.createDirectory(p));//目录的创建,目录路径已存在则异常;目录路径为多级目录,异常 // System.out.println(Files.createDirectories(p));//目录的创建,自动创建多级不存在目录;目录已存在,无异常 // System.out.println(Files.createFile(p2));//文件的创建,基于指定路径,创建文件。文件存在,异常; // Files.copy(p2,p3, StandardCopyOption.REPLACE_EXISTING);/*将文件复制到目标文件。默认,如果文件已经存在,异常 // 如果source为目录,不会复制里面的文件,仅相当于创建一个空目录 // java.nio.file.StandardCopyOption枚举,实现了CopyOption接口,复制选项*/ // Files.move(p2,p3,StandardCopyOption.REPLACE_EXISTING)/*将文件移动或重命名为目标文件。 // 默认,如果目标文件存在,则异常,可通过options参数声明移动选项 // 如果在本目录下移动,相当于文件改名*/ // Files.delete(p2);/*路径不存在,不删除。返回是否删除成功 //如果路径为目录,目录中包含文件(即不为空),2种删除均异常*/ Files.walk(p3).forEach(System.out::println); } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)