注意:这里仅仅描述了基本的使用方法,并无涉及到NIO中的东西,有关于NIO方面的东西,放到以后的博客中描述。RandomAccessFile放到以后再进行描述java
在文件系统中,文件名是用于定位存储位置 元数据:描述数据的数据,在这里咱们将一个文件看成一个数据,那么文件的属性就是元数据。mysql
java.io.File 类表明与当前系统平台无关的文件和目录sql
File 类的一个实例就表明一个文件或目录数组
File 类提供了判断 其实例是文件仍是目录的方法app
File 类提供了能够操做文件系统中的文件和目录的方法dom
File 类仅表明文件或目录,不支持对文件的内容进行修改ide
File( String pathname ) 经过将给定路径名字符串转换为抽象路径名来建立一个新 File 实例 File( String parent , String child ) 根据 parent 路径名字符串和 child 路径名字符串建立一个新 File 实例 File( File parent , String child ) 根据 parent 抽象路径名和 child 路径名字符串建立一个新 File 实例 File( URI uri ) 经过将给定的 file: URI 转换为一个抽象路径名来建立一个新的 File 实例
可是咱们在使用的时候,最常常使用的就是传一个路径的File构造方法。测试
public static final char separatorChar 与系统有关的默认名称分隔符(⽂文件系统中的不不同层次的路路径之间的分隔符) public static final String separator 与系统有关的默认名称分隔符,为了了⽅便,它被表示为一个字符串 public static final char pathSeparatorChar 与系统有关的路路径分隔符(环境变量量PATH的取值中不同部分之间的分隔符) public static final String pathSeparator 与系统有关的路路径分隔符,为了了⽅便,它被表示为一个字符串
String path = "C:/Windows/notepad.exe" ; // 根据给定的目录的路径来建立一个对象 表示该目录的Java对象 File directory = new File(path) ; System.out.println("File所表示的目录或文件是否存在 :" + directory.exists() ); System.out.println("是不是一个文件 : " + directory.isFile() ); System.out.println( "是不是一个目录 : " + directory.isDirectory() ); System.out.println("是不是隐藏的:" + directory.isHidden() ); System.out.println("是不是绝对路径:" + directory.isAbsolute() ); // length方法返回的字节数,若是须要转成KB或其余单位,须要进行换算(仅对文件有效,对目录无效) System.out.println("文件的长度是:" + directory.length()/1024 ); path = "C:\\JavaApplication\\mysql-5.7.17-winx64" ; directory = new File( path ) ; String[] names = directory.list() ; for (String s : names) { System.out.print(s + "\t"); } System.out.println(); File[] fileNames = directory.listFiles() ; for (File f : fileNames) { System.out.print(f.toString() + "\t"); } System.out.println(); path = "C:/Windows/notepad.exe" ; File f = new File(path) ; System.out.println("文件名或目录名: " + f.getName() ); System.out.println("存放路径 : " + f.getParent() ); System.out.println("绝对路径 :" + f.getAbsolutePath() ); System.out.println("最后修改的毫秒 :" + f.lastModified() ); System.out.println( "最后修改的时间 :" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date( f.lastModified() ))); System.out.println("文件或目录是否可读 :" + f.canRead() ); System.out.println("文件或目录是否可写 :" + f.canWrite() ); System.out.println("文件或目录是否能够执行 :" + f.canExecute() ); /** * 在Eclipse环境下运行含有main方法的Java程序,默认的当前路径是当前工程 * 注意路径的规范化形式 */ path = "." ; f = new File( path ) ; System.out.println( f.getAbsolutePath() ); path = "src" ;// 表示当前路径下的src目录 f = new File( path ) ; System.out.println( "获取绝对路径:" + f.getAbsolutePath() ); f = new File(".."); System.out.println( "获取绝对路径:" + f.getAbsolutePath() ); System.out.println("获取规范化形式的路径:" + f.getCanonicalPath() ); f = new File( "/" ) ; System.out.println(f.getAbsolutePath() ); System.out.println(f.getCanonicalFile()); /** * 建立新文件、删除新文件 */ path = "." ; f = new File( path ) ; if( f.canWrite() ) { // 在f对应的目录中建立一个hello.txt文件 // 在内存中建立一个表示f下的hello.txt对应的文件的Java对象 File file = new File( f , "hello.txt") ; if ( file.exists()) { file.delete() ; } // 在磁盘上 建立一个file对象对应的新文件 boolean b = file.createNewFile() ; System.out.println( b );// 若是已经存在或没有权限则建立失败 } /** * 建立目录、删除目录( delete能够删除空目录) */ if( f.canWrite() ) { File file = new File( f , "kaka") ; if( file.exists() && file.isDirectory() ) { boolean b = file.delete() ; System.out.println( b ? "目录删除成功" : "目录删除失败" ); } boolean b = file.mkdir() ; // 建立一个新目录 System.out.println( b ? "目录建立成功" : "目录建立失败"); } /** * mkdir能够建立一个子目录 * mkdirs 能够建立多层子目录 */ if( f.canWrite() ) { File file = new File( "kaka/kakaTM/kakTTMM"); file.mkdirs() ; File dest = new File("kaka/kakaTM/kakTTMMMM") ; // 将file的名称重命名为dest对应的名称 file.renameTo(dest) ; } File s = new File("./hello.txt") ; File d = new File("C:/abc.txt") ; s.renameTo(d) ; // 剪切操做( 强烈不建议操做 ) File kak = new File("kaka") ; kak.deleteOnExit(); // 虚拟机退出以后再删除 Thread.sleep(30000 );// 能够在这里进行测试
文件过滤器this
能够根据条件(最后修改时间、长度、名字等)进行过滤。编码
File dof = new File("C:/test") ; if( dof.exists() && dof.isDirectory() ) { FilenameFilter fnf = new FilenameFilter() { [@Override](https://my.oschina.net/u/1162528) public boolean accept(File dir, String name) { if( name.endsWith("java")) { return true ; } return false; } }; String[] fileList = dof.list(fnf) ; System.out.println( fileList.length ); for (String s : fileList) { System.out.println( s ); } } File dof = new File("C:/test") ; if( dof.exists() && dof.isDirectory() ) { FileFilter fnf = new FileFilter() { [@Override](https://my.oschina.net/u/1162528) public boolean accept(File pathname) { if( pathname.isFile() && pathname.getName().endsWith(".java")) { return true ; } return false; } }; File[] fileList = dof.listFiles(fnf); System.out.println( fileList.length ); for (File s : fileList) { System.out.println( s ); } }
练习:能够经过遍历获取C盘下的全部文件的名字。
InputStream是全部字节输入流的父类。
注意看构造
咱们能够利用FileInputStream来测试InputStream中的方法
File file = new File("out.txt") ; InputStream inStream = null ; System.out.println( inStream ); if( file.exists() && file.isFile() ) { inStream = new FileInputStream(file) ; System.out.println( inStream ); // int b = inStream.read() ; // 范围0~255,将byte数字进行"翻译"成int值 // System.out.println( b ); int b ; do { // read方法负责读取一个字节, // 若是没有到达流的末尾,则返回读取到的数据 // 若是到达流的末尾,则返回-1 b = inStream.read() ; // 一次读取一个字节 System.out.println( b ); }while( b!=-1 ); } inStream.close();
这里一次读取一个字节,解析出来的全是数字,若是转成char类型,看不懂。因此可使用数组,表示一次多读取几个字节的方式来操做。
File file = new File("out.txt") ; InputStream inStream = null ; System.out.println( inStream ); if( file.exists() && file.isFile() ) { inStream = new FileInputStream(file) ; System.out.println( inStream ); // 得到下一次调用方法以前能够不受阻塞的今后输入流中读取估计字节数 int size = inStream.available() ; byte[] bytes = new byte[size] ; int n ; /*do { // read( byte[] bytes )方法负责读取n个字节, // 若是没有到达流的末尾,则返回读取到的字节数(读取到几个字节就返回几) // 若是读取到内容了,则将读取到的字节放入到数组中(读取到几个,就放入几个) // 若是到达流的末尾,则返回-1 n = inStream.read(bytes ) ; // 一次读取一个字节 System.out.println( "读取到的字节数:"+n ); String s = new String(bytes , 0 , n ) ; System.out.println( s ); }while( n!=-1 ); */ while( (n = inStream.read(bytes)) != -1 ) { String s = new String( bytes , 0 , n) ; System.out.println( s ); } } System.out.println( inStream.markSupported() ); inStream.close();
咱们能够看到FileInputStream是不支持作标记的,咱们后续再说。那么咱们的FileInputStream就看完了。
此抽象类是表示输出字节流的全部类的超类。输出流接受输出字节并将这些字节发送到某个接收器。
须要定义 OutputStream 子类的应用程序必须始终提供至少一种可写入一个输出字节的方法。
public static void main(String[] args) throws Exception { File file = new File("file.txt") ;// 第一个参数指示输出到哪里去 boolean append = false ; // 若是第二个参数是true表示追加,若是是false表示覆盖 OutputStream os = new FileOutputStream(file, append) ; // 输出单个字节(若是是int类型的整数,则忽略高24位,只留低8位) os.write(97); os.write(378); byte[] bytes = "卡卡他妈".getBytes() ; System.out.println( bytes.length ); // 将这个字节数组经过输出流 输出到文件中 os.write(bytes); // 将字节数组中的一部分输出到文件中 write( bytes , start, n)[start , start+n) os.write(bytes,3 , 3); os.close(); }
这样咱们就会使用了OutputStream这个类中的方法。
public static void main(String[] args) throws Exception { File source = new File("G:\\一禅壁纸\\电脑壁纸\\桌面背景03.jpg") ; File target = new File( source.getName() ) ; FileInputStream in = new FileInputStream(source) ; FileOutputStream out = new FileOutputStream( target ) ; int n ; // 声明一个变量,用来记录读取到的字节数 byte[] bytes = new byte[128] ; while( (n = in.read(bytes ) ) != -1 ) { // out.write(bytes); out.write(bytes, 0, n); } out.close(); in.close(); }
固然,咱们能够看一下复制时间。
BufferedInputStream 为另外一个输入流添加一些功能,即缓冲输入以及支持 mark 和 reset 方法的能力。在建立 BufferedInputStream 时,会建立一个内部缓冲区数组。
public static void main(String[] args) throws Exception { InputStream in = new FileInputStream("src/bufferedStream/TestBufferedStream1.java") ; // super(in)--->this.in = in ; // this.buf = new byte[8192] ; // 内部有一个字节数组 BufferedInputStream bis = new BufferedInputStream(in) ; byte[] bytes = new byte[100] ; int n; while((n=bis.read(bytes))!=-1 ) { String s = new String( bytes , 0 , n ); System.out.print(s); } bis.close(); in.close(); }
public static void main(String[] args) throws Exception { InputStream in = new FileInputStream("bufferIn.txt") ; BufferedInputStream bis = new BufferedInputStream(in) ; int n; while((n=bis.read())!=-1 ) { char ch = (char)n; System.out.print( ch ); if( bis.markSupported() ) {// 判断是否支持mark和reset操做 if(ch=='s') { // this.marklimit = readlimit;// this.maklimit =250 // this.markpos = pos; bis.mark(250); } } } System.out.println(); if(bis.markSupported() ) { bis.reset(); int b; while((b=bis.read())!=-1 ) { char ch = (char)b; System.out.print( ch ); } } bis.close(); in.close(); }
/** * 向缓冲字节输出流中输出数据,若是没有close和flush方法,可能致使数据不被输出 */ public class TestBufferedStream3 { public static void main(String[] args) throws Exception { OutputStream out = new FileOutputStream("buffer.txt") ; BufferedOutputStream bos = new BufferedOutputStream(out) ; bos.write(97); bos.write('b'); bos.write(100); // 调用flush方法将缓冲区的内容进行刷出 // bos.flush(); bos.close();// close方法中调用了flush方法 } }
用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int) 和 close()。 由于是抽象类,因此不能new对象,能够找它的子类:FileReader
public class TestReader { public static void main(String[] args) throws Exception { String file = "src/reader/TestReader.java" ; // 建立一个字符输入流,一次能够读取一个字符 Reader reader = new FileReader(file) ; int ch ; // Reader中的read()能够返回一个字符(以整数形式返回) // 若是读到流的末尾,返回-1 while( (ch = reader.read() ) != -1 ) { // 将获得的整数形式的字符强制转成char类型 char c = (char)ch ; System.out.print(c); } } }
public static void main(String[] args) throws Exception { String file = "src/reader/TestReader2.java" ; Reader reader = new FileReader(file) ; char[] chars = new char[100] ;// 表示100个字 int ch ; // Reader中的read(char[] charArray)能够从流中读取n个字节到数组中 while( (ch = reader.read( chars ) ) != -1 ) { // 将本次读取到的字符构造称字符串 String s = new String(chars, 0, ch) ; System.out.print(s); } reader.close(); }
public static void main(String[] args) throws Exception { String filename = "writer.txt" ; boolean append = false ; Writer w = new FileWriter(filename , append ) ; w.write(97); w.write('\n'); w.write("helloworld"); w.write('\n'); char[] chars = {'k','k','T','M'} ; w.write(chars); w.write(chars, 2,1 ); w.close(); }
public static void main(String[] args) throws Exception { String filename = "writer.txt" ; boolean append = false ; Writer w = new FileWriter(filename , append ) ; w.append("hello") ; w.append('k') ; w.write("TM"); w.close(); }
public static void main(String[] args) throws Exception { // 建立一个能够读取文件内容的字符输入流( 节点流 ) Reader r = new FileReader("buffer.txt") ; // 建立一个带有缓冲功能的字符输入流( 它提供了额外的功能) // BufferedReader实例内部一个能够容纳8192个字符的char数组 BufferedReader br = new BufferedReader( r ) ; String s ; while( (s = br.readLine() ) != null ) { System.out.println( s ); } br.close(); r.close(); }
public static void main(String[] args) throws Exception { Writer w = new FileWriter("buffer.txt"); // BufferedWriter内部有一个能够容纳8192个字符的char数组 BufferedWriter bw = new BufferedWriter(w) ; bw.write("hello,kaka");// 向缓冲区中写入内容 // 刷出缓冲区的内容到目标输出流 bw.flush(); bw.close(); w.close(); System.out.println( w.toString() ); }
这两个流就是对应的转换流,是字节流和字符流之间的转换。
/** *转换流(InputStreamReader)将字节输入流转换成字符输入流 */ public class TestInputStreamReader1 { public static void main(String[] args) throws Exception { String fileName = "src/conver/TestInputStreamReader1.java"; // 建立一个字节输入流 InputStream in = new FileInputStream(fileName) ; // 将字节输入流转换称字符输入流 InputStreamReader isr = new InputStreamReader(in) ; // byte[] bytes = new byte[8] ; // int b ; // while( (b = in.read(bytes)) != -1 ) { // String s = new String( bytes , 0 , b ); // System.out.print(s); // } int n ; // 一次读取一个字符(以整数形式返回),保存到ch变量中,而后比较是否等于-1(若是是-1,表示结束) while( (n = isr.read()) != -1 ) { System.out.print( (char)n ); } in.close(); } }
public static void main(String[] args) throws Exception { // 将标准输入流存储到变量in中 InputStream in = System.in ; // int n ; // while( (n = in.read() ) != -1 ) { // System.out.println((char)n); // } // 将字节输入流转换成字符输入流 InputStreamReader r = new InputStreamReader(in ) ; int ch ; while( (ch = r.read() ) != -1 ) { System.out.print((char)ch); } r.close(); in.close(); }
public static void main(String[] args) throws Exception { // 将标准输入流存储到变量in中 InputStream in = System.in ; // 将字节输入流转换成字符输入流 InputStreamReader r = new InputStreamReader(in ) ; // 包装一个字符缓冲流 BufferedReader br =new BufferedReader(r) ; String ch ; while( (ch = br.readLine() ) != null ) { System.out.print(ch); if( "byebye".equalsIgnoreCase(ch)) { System.exit(0); } } r.close(); in.close(); }
/** * 将字符输出流转换成字节输出流 */ public class TestOutputStreamWriter { public static void main(String[] args) throws IOException { // 建立一个字节输出流,输出到文本文件中 OutputStream o = new FileOutputStream("convert.txt"); // 将字符输出流转成字节输出流 OutputStreamWriter osw = new OutputStreamWriter( o ) ; osw.write("哈哈哈哈哈"); osw.write('k'); osw.write('\n'); osw.close(); o.close(); } }
/** *读取一个UTF-8编码的文件,将它转成GBK编码后从新输出到另一个文件中 */ public class TestOutputStreamWriter2 { public static void main(String[] args) throws IOException { // 读取一个文本文件 InputStream inStream = new FileInputStream("convert.txt") ; // 建立一个转换流,并指定相应的字节输入流和编码名称 // 在将字节转换成字符时,采用编码名称指定的编码完成 InputStreamReader isr = new InputStreamReader( inStream ,"UTF-8" ) ; // 建立一个能够输出字节到指定文件的字节输出流 OutputStream outputStream = new FileOutputStream("convert-gbk.txt"); // 建立一个以指定字节流为输出目标的转换流( 字节转字符 ) // 并指定将字符转换成字节时,使用的编码名称 OutputStreamWriter osw = new OutputStreamWriter(outputStream, "GBK") ; int ch ; // 从字符输入流中一次读取一个字符 while( ( ch = isr.read() ) != -1 ) { // 经过字符输出流将读取到的字符从新输出 osw.write(ch); // 将单个字符写出到Writer流 } osw.close(); outputStream.close(); isr.close(); inStream.close(); } }
/** * 若是但愿完成序列化操做,须要实现java.io.Serializable接口 */ public class Student implements Serializable{ /** * serialVersionUID 至关于一个类的身份证编号 * 在序列化时,会将该编号一块儿输出到相应的流中 * 等到反序列化时(读取流还原对象),会检查相应的类是否存在(会检查该编号) */ private static final long serialVersionUID = -3227384916215757351L; private Integer id ; private String name ; private char gender ; private Date bithdate ; // getter and setter }
/** * 序列化( Serialization) * 将一个Java对象以特定的字节序列输出到某个流中 * 经过 ObjectOutputStream类的writeObject(obj)来实现 * 被写出的那个对象对应的类须要实现java.io.Serialization接口 */ public class ObjectSerialization1 { public static void main(String[] args) throws IOException { final Calendar c = Calendar.getInstance() ; Student s = new Student() ; s.setId(9527); s.setName("华安"); s.setGender('男'); c.set(1888, 8, 8, 8, 8, 8); s.setBithdate(c.getTime()); OutputStream out = new FileOutputStream("student.obj") ; ObjectOutputStream oos = new ObjectOutputStream(out) ; // 保存学生对象 oos.writeObject(s); oos.close(); out.close(); } }
/** * 反序列化 * 就是读取一个流中的数据,将它还原(重构)成相应的对象 * 重构时,就会检查该对象对应的类的serialVersionUID * 反序列化经过ObjectInputStream来实现 */ public class ObjectDeserialization1 { public static void main(String[] args) throws IOException, ClassNotFoundException { InputStream in = new FileInputStream("student.obj") ; ObjectInputStream ois = new ObjectInputStream(in) ; // 从已知的字节流中读取某个对象对应的数据 Object o = ois.readObject() ; System.out.println( o ); if( o instanceof Student) { Student s = (Student) o ; System.out.println( s.getName() ); } ois.close(); in.close(); } }