毕向东之IO与File类
/*IO流: java对数据的操作是通过流的方式 流按照操作数据分为:字节流与字符流 流按流向分为:输入流与输出流 字节流的抽象基类:InputStream,OutputStream 字符流的抽象基类:Reader,Writer */ import java.io.*; public class Test1 { public static void main(String[] args)throws IOException { //创建一个写文件对象,该对象一被初始化就必须要指明被操作的文件 //而且该文件会被创建到指定的目录下,同名文件将覆盖 FileWriter fw=new FileWriter("F:\\QQ文件\\demo1.txt"); fw.write("aaaa");//将数据写入流中 fw.flush();//刷新流的缓冲,将数据刷到目的地中 fw.write("ccc");//其实是调用系统的方法来写数据,所以会有异常 fw.close();//关闭之前会调用刷新 //流关闭后不能直接再写数据 必须有流对象才能写 //对已有文件进行数据续写 FileWriter fw1=new FileWriter("F:\\QQ文件\\demo1.txt",true); fw1.write("\r\n续写");//换行 fw1.close(); } }
/*对IO异常的处理 */ import java.io.*; public class Test2 { public static void main(String[] args) { FileWriter fw=null;//让fw的作用域变大 try{ fw=new FileWriter("F:\\QQ文件\\demo1.txt"); fw.write("yichang"); }catch(IOException e){ System.out.println("写入异常"); }finally{//一定要关闭 if(fw!=null){ try{ fw.close(); }catch(IOException e){ System.out.println("流关闭异常"); } } } } }
import java.io.*; public class Test3 { public static void main(String[] args)throws IOException{ //创建一个文件读取流对象和指定名称的目录 FileReader fr=new FileReader("F:\\QQ文件\\demo1.txt"); FileReader fr1=new FileReader("F:\\QQ文件\\demo1.txt"); int ch=0; while((ch=fr.read())!=-1){//一次读一个字符且自动往下读 System.out.print((char)ch);//返回的数据是int型 } fr.close(); //第二种读取方式 int num=0; char[] arr=new char[2]; while((num=fr1.read(arr))!=-1){//read返回的是读取的个数 System.out.print(new String(arr,0,num));//只截取读到的数据,避免输出重复 }//利用数组的重装 fr1.close(); } }
/*复制文件的原理: 1.定义流与被复制文件相关联 2.读取再写入 */ import java.io.*; public class Test4 { public static void main(String[] args)throws IOException { FileReader fr=new FileReader("F:\\QQ文件\\demo1.txt"); FileWriter fw=new FileWriter("F:\\QQ文件\\fuzhi.txt"); int num=0; char[] arr=new char[1024]; while((num=fr.read(arr))!=-1){ fw.write(arr,0,num); } fr.close(); fw.close(); } }
/*字符流的缓冲区:为了提高对数据的读写效率 所以在创建缓冲区之前,必须要先有流对象 对应类:BufferedWriter,BufferedReader:利用的装饰模式(传对象而不是继承) */ import java.io.*; public class Test5 { public static void main(String[] args)throws IOException { FileWriter fw=new FileWriter("F:\\QQ文件\\demo1.txt",true); //缓冲区背后其实就是加入了数组 BufferedWriter bw=new BufferedWriter(fw); bw.newLine();//换行,\r\n只适用于wendows bw.write("abcdef"); bw.close();//关闭缓冲区就是在关闭缓冲区的流对象(内部调用) FileReader fr=new FileReader("F:\\QQ文件\\demo1.txt"); BufferedReader br=new BufferedReader(fr); String str; while((str=br.readLine())!=null){//不包括\r\n System.out.println(str); } br.close(); } }
import java.io.*; public class Test6 { public static void main(String[] args) { BufferedWriter bw=null; BufferedReader br=null; try{ bw=new BufferedWriter(new FileWriter("F:\\QQ文件\\fuzhi.txt")); br=new BufferedReader(new FileReader("F:\\QQ文件\\demo1.txt")); String str; while((str=br.readLine())!=null){ bw.write(str); bw.newLine(); } }catch(IOException e){ System.out.println("读写异常"); }finally{ if(bw!=null){ try{ bw.close(); }catch(IOException e){ System.out.println("关闭失败"); } } if(br!=null){ try{ br.close(); }catch(IOException e){ System.out.println("关闭失败"); } } } } }
//LineNumberReader extends BufferedReader import java.io.*; public class Test7 { public static void main(String[] args)throws IOException{ LineNumberReader lnr=new LineNumberReader(new FileReader("F:\\QQ文件\\fuzhi.txt")); String str; //lnr.setLineNumber(100);//行号默认从0开始 while((str=lnr.readLine())!=null){ System.out.println(lnr.getLineNumber()+":"+str); } lnr.close(); } } class MyLineNumberReader{//LineNumberReader的原理 private FileReader fr; private int count=0; public MyLineNumberReader(FileReader fr){ this.fr=fr; } public int getLineNumber(){ return count; } public String readLine()throws IOException{ StringBuilder sb=new StringBuilder(); int ch; count++; while((ch=fr.read())!=-1){//一行行读 if(ch=='\r') continue; if(ch=='\n') return sb.toString(); sb.append((char)ch); } if(sb.length()!=0) return sb.toString(); return null; } public void close()throws IOException{ fr.close(); } }
/*字节流:字符流用于操作文本,字节操作图片等等 LineNumberReader extends BufferedReader InputStream 读 -->Reader OutputStream 写 -->Writer FileInputStream -->FileReader FileOutputStream -->FileWrider BufferedInputStream -->BufferedReader BufferedOutputStream -->BufferedWrider */ import java.io.*; public class Test8 { public static void main(String[] args)throws IOException{ FileInputStream fis=new FileInputStream("F:\\图片\\tupian.jpg"); FileOutputStream fos=new FileOutputStream("F:\\图片\\fuzhi.jpg"); int len; byte[] arr=new byte[1024];//字节流写入字节数组 while((len=fis.read(arr))!=-1){ fos.write(arr,0,len); } fos.close(); fis.close(); } }
/*自定义字节流的缓冲区时需要注意: while条件里面的-1代表数据都读完了 而字节里面的数据都是由零一组成,所以要避免读到8个1(-1); 处理方法: 1111-1111 一个字节,等于负一 1111-1111-1111-1111 提升为int型的再与上 & 0000-0000-1111-1111 也就是与上0xff; 0000-0000-1111-1111 这样就不再等于负一 也就避免了把八个数据1当成了负一来处理 */ import java.io.*; public class Test9 { public static void main(String[] args) { long start=System.currentTimeMillis(); BufferedInputStream bis=null; BufferedOutputStream bos=null; try{ bis=new BufferedInputStream(new FileInputStream("F:\\图片\\美女.jpg")); bos=new BufferedOutputStream(new FileOutputStream("F:\\图片\\复制.jpg")); int count; byte[] arr=new byte[1024]; while((count=bis.read(arr))!=-1){ bos.write(arr, 0, count); } }catch(IOException e){ throw new RuntimeException("读取失败"); }finally{ if(bis!=null){ try{ bis.close(); }catch(IOException e){ throw new RuntimeException("读取关闭失败"); } } if(bos!=null){ try{ bos.close(); }catch(IOException e){ throw new RuntimeException("写入关闭失败"); } } } long end=System.currentTimeMillis(); System.out.println((end-start)+"毫秒"); } }
//键盘录入 import java.io.*; public class Test10 { public static void main(String[] args)throws Exception{ InputStream in=System.in;//标准的输入流 StringBuilder sb=new StringBuilder(); int ch; while(true){ ch=in.read(); if(ch=='\r') continue; if(ch=='\n'){ if(sb.toString().equals("over")) break; System.out.println(sb.toString()); sb.delete(0, sb.length()); } else{ sb.append((char)ch); } } } }
/*键盘录入的原理其实就是读一行数据的原理也就是readLine方法 又因为readLine方法是字符流BufferedReader类的方法 所以需要将字节流转换成字符流才能使用readLine方法(缓冲区的) */ import java.io.*; public class Test11 { public static void main(String[] args)throws IOException{ InputStream in=System.in;//获取键盘录入对象 //将字节流对象转换成字符流对象,使用转换流 InputStreamReader isr=new InputStreamReader(in); //为了提高效率,将字符流进行缓冲区高效操作(一个一个读变为一行行读) BufferedReader bufr=new BufferedReader(isr); OutputStream out=System.out; OutputStreamWriter osw=new OutputStreamWriter(out); BufferedWriter bufw=new BufferedWriter(osw); String line; while((line=bufr.readLine())!=null){ if(line.equals("over")) break; bufw.write(line); bufw.newLine();//缓冲区的方法 bufw.flush(); } bufr.close(); } }
/*需求:将键盘录入的数据存入文件中 1.明确源和对象: 源:输入流 InputStream,Reader 目的:输出流 OutputStream,Writer 2.操作数据是纯文本用字符流,否则字节流 目的:想要把录入的数据按照指定的编码表(UTF-8),将数据存到文件中. 但是FileWriter使用的是默认编码表GBK,而只有转换流才能指定编码表 */ import java.io.*; public class Test12 { public static void main(String[] args)throws IOException{ BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in)); BufferedWriter budw=new BufferedWriter(new FileWriter("F:\\QQ文件\\1.txt")); String line; while(true){ line=bufr.readLine(); if(line.equals("over")) break; budw.write(line); budw.flush(); } } }
/*改变默认的输入输出 */ import java.io.*; public class Test13{ public static void main(String[] args)throws IOException { System.setIn(new FileInputStream("F:\\QQ文件\\1.txt")); System.setOut(new PrintStream("F:\\QQ文件\\2.txt")); BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in,"GBK")); BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out)); String line; while((line=bufr.readLine())!=null){ if(line.equals("over")) break; bufw.write(line); bufw.flush(); } } }
//异常的日志文件处理 import java.io.*; import java.text.*; import java.util.*; public class Test14 { public static void main(String[] args) { int[] arr=new int[2]; try{ System.out.println(arr[3]); }catch(Exception e){ try{ PrintStream ps=new PrintStream("F:\\QQ文件\\Exception.log"); System.setOut(ps);//整个主函数的out都变了 Date da=new Date();//大写HH为24时制 SimpleDateFormat sd=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String str=sd.format(da); e.printStackTrace(ps); ps.print(str); ps.flush(); }catch(IOException io){ System.out.println("日志文件创建异常"); } } System.out.println("打印在日志文件中了"); } }
import java.util.*; import java.io.*; public class Test15 { public static void main(String[] args)throws IOException{ Properties p=System.getProperties();//获取系统性能 PrintStream ps=new PrintStream("F:\\QQ文件\\1.txt"); p.list(ps);//列表的形式打印 } }
/*File类:用来将文件或文件夹封装成对象 File类常见方法: 1.创建: boolean createNewFile();在指定位置创建文件,不存在时才创建,而输出流对象一建立就会创建文件,存在时会覆盖 boolean mkdir();创建文件夹 boolean mkdirs();创建多级文件夹 2.删除: boolean delete();立马删除 void deleteOnExit();虚拟机结束后删除 3.判断: boolean canExecute();能否执行 boolean exists();文件是否存在 boolean isFile();是不是文件 boolean isDirectory();是不是文件夹 boolean isAbsolute();是否是绝对路径(路径全名) boolean isHidden();是否是隐藏文件 4.获取信息: String getName();获取文件目录或文件的名称 String getPath();//父目录不存在时返回null String getParent();返回此抽象路径名父目录的路径名字符串 String getAbsoluteParh();返回此抽象路径名的绝对路径名字符串。 File getAbsoluteFile();返回此抽象路径名的绝对路径名形式。 long lastModified();文件最后一次被修改的时间 long length();文件里面内容的长度 */ import java.io.*; public class Test16 { public static void main(String[] args)throws IOException { File f1=new File("F:\\QQ文件");//将文件夹封装成对象 File f2=new File("F:\\QQ文件","1.txt");//文件夹中的文件 File f3=new File(f1,"2.txt");// 由于\\不能跨平台 File f4=new File("F:"+File.separator+"QQ文件"+File.separator+"4.txt"); //注意:以上并不是创建文件,而只是封装 sop(f1); sop(f2.createNewFile());//创建新文件 sop(f2.delete()); sop(f2.canExecute());//判断文件f2能不能执行 sop(f2.exists()); sop(f2.mkdir()); sop(f2.length()); f2.renameTo(f3);//f2名称改为f3 } public static void sop(Object obj){ System.out.println(obj); } }
这个只能过滤一层,如果文件夹中包含文件夹就不行了,所以需要用到递归,见下面
//接口 FilenameFilter:文件名的过滤器(选该名字的文件) //接口 FileFilter:路径名的过滤器(选该路径名的文件) import java.io.*; public class Test17 { public static void main(String[] args) { File f=new File("c:"); File[] arr=File.listRoots(); arr=f.listFiles();//所以文件或文件夹的对象,与list的区别 // for(File name:arr){ // System.out.println(name); // } File[] fileArr=f.listFiles(new FilenameFilter(){ public boolean accept(File dir,String name){ return name.endsWith(".ini");//只选.ini的文件存到fileArr里 }//dir=f,返回为真时存入fileArr中 }); for(File name:fileArr){ System.out.println(name); } } }
/** * 获取指定路径中的视频文件 * @param list 装扫描出来的视频文件实体类 * @param file 指定的文件 */ public static void getVideoFile(final List<VideoInfo> list, File file) {// 获得视频文件 file.listFiles(new FileFilter() { @Override public boolean accept(File file) { // sdCard找到视频名称 String name = file.getName(); int i = name.indexOf('.'); if (i != -1) { name = name.substring(i);//获取文件后缀名 if (name.equalsIgnoreCase(".mp4") //忽略大小写 || name.equalsIgnoreCase(".3gp") || name.equalsIgnoreCase(".wmv") || name.equalsIgnoreCase(".ts") || name.equalsIgnoreCase(".rmvb") || name.equalsIgnoreCase(".mov") || name.equalsIgnoreCase(".m4v") || name.equalsIgnoreCase(".avi") || name.equalsIgnoreCase(".m3u8") || name.equalsIgnoreCase(".3gpp") || name.equalsIgnoreCase(".3gpp2") || name.equalsIgnoreCase(".mkv") || name.equalsIgnoreCase(".flv") || name.equalsIgnoreCase(".divx") || name.equalsIgnoreCase(".f4v") || name.equalsIgnoreCase(".rm") || name.equalsIgnoreCase(".asf") || name.equalsIgnoreCase(".ram") || name.equalsIgnoreCase(".mpg") || name.equalsIgnoreCase(".v8") || name.equalsIgnoreCase(".swf") || name.equalsIgnoreCase(".m2v") || name.equalsIgnoreCase(".asx") || name.equalsIgnoreCase(".ra") || name.equalsIgnoreCase(".ndivx") || name.equalsIgnoreCase(".xvid")) { VideoInfo vi = new VideoInfo(); vi.displayName = file.getName();//文件名 vi.filePath = file.getAbsolutePath();//文件路径 list.add(vi); LogUtils.i("tag","文件名:"+vi.displayName+",路径:"+vi.filePath); return true; } } else if (file.isDirectory()) { getVideoFile(list, file); } return false; } }); }
/*输出指定路径的所有文件夹和文件(Test17只能输出父目录) 因为目录中还有目录,只要使用同一个列出目录的功能函数就可以完成 也就是利用递归的思想 */ import java.io.*; public class Test18 { public static void main(String[] args) { File f=new File("E:\\郭天祥视频"); File[] farr=f.listFiles(); showDir(farr); } public static void showDir(File[] farr){ for(int i=0;i<farr.length;i++){ if(farr[i].isDirectory()){//判断是不是目录 System.out.println(farr[i]); showDir(farr[i].listFiles()); }else System.out.println(farr[i]); } } }
/*文件删除原理:先删除里面的再删除外面的, 如果某文件夹里面有文件,该文件不能直接删除,必须先删除里面的才能删除外面的 文件便利的时候要注意隐藏文件:f.isHidden() */ import java.io.*; public class Test19 { public static void main(String[] args) { File f=new File("F:\\QQ文件\\111"); deleteDir(f);//删除f文件夹 } public static void deleteDir(File file){ File[] arr=file.listFiles(); for(int i=0;i<arr.length;i++){ if(arr[i].isDirectory()){ deleteDir(arr[i]); }else//不是目录就删除 System.out.println(arr[i].delete()); }//文件夹中的文件删除后再删除该文件夹 System.out.println(file.delete());//删除当前目录 } }
/*需求:将一个指定目录下的java文件的绝对路径存储到一个文本文件中 思路:1.通过递归找出所有.java文件,并把它的绝对路径存入集合中 2.将集合中的数据写入文件中 */ import java.io.*; import java.util.*; public class Test20 { public static void main(String[] args) throws IOException { File f1=new File("E:\\学习文件"); File f2=new File("F:\\QQ文件\\22.txt"); List<File> list=new ArrayList<File>(); fileToList(f1,list);//将f1文件里的java文件路径存入集合 listToFile(list,f2);//将list中的内容写入文本文件中 } public static void fileToList(File file,List<File> list){ File[] farr=file.listFiles(); for(int i=0;i<farr.length;i++){ if(farr[i].isDirectory()){ fileToList(farr[i],list); }else{ if(farr[i].getName().endsWith(".java")){ list.add(farr[i].getAbsoluteFile()); } } } } public static void listToFile(List<File> list,File file)throws IOException{ BufferedWriter bufw=null; try{ bufw=new BufferedWriter(new FileWriter(file)); for(File f:list){//f为绝对路径 bufw.write(f.toString()); bufw.newLine(); bufw.flush(); } }catch(IOException e){ throw e;//抛出去交给调用者处理 }finally{ if(bufw!=null){ try{ bufw.close(); }catch(IOException e){ throw e; } } } } }
/*Properties是hashtable的子类,也就是说它具备map集合的特点 而且它里面存储的键值对都是字符串,它是集合中和IO技术相结合的集合容器 注意:如果一流对象指向的路径相同(如下fis,fos)在进行集合加载时,如果这两个流对象都写在load之前, 集合将加载不成功,还会把原有的数据删掉 */ import java.util.*; import java.io.*; public class Test21 { public static void main(String[] args)throws IOException{ Properties prop=new Properties(); FileInputStream fis=new FileInputStream("F:\\QQ文件\\11.txt"); prop.load(fis);//将fis的内容加载到prop集合中 prop.setProperty("wangwu", "15");//修复集合的内容 FileOutputStream fos=new FileOutputStream("F:\\QQ文件\\11.txt"); prop.store(fos, "zhushi");//将prop集合的内容存储到fos中 prop.list(System.out); fis.close(); fos.close(); } public static void setPrinit(){ Properties prop=new Properties();//性能 prop.setProperty("zhangshan","3"); prop.setProperty("lisi","4"); prop.setProperty("lisi","5"); for(String name:prop.stringPropertyNames()){ System.out.println(name+"--"+prop.getProperty(name)); } } }
/*需求:记录一应用程序运行的次数,超过一定的次数给出注册提示 思路:只有在程序运行时先执行配置文件,读取运行的次数进行判断 而程序一关闭数据也就清除了,所以必须用到文件对数据进行记录; 即:集合处理文件,IO存储数据,Map+IO=Properties 步骤:1.判断配置文件存不存在,不存在则创建,并创建集合加载文件数据 2.通过集合判断配置文件中记录次数的数据是否存在,不存在就设置 3.获取次数并进行次数自增,将次数写入集合中,再通过集合存储到配置文件中 */ import java.io.*; import java.util.*; public class Test22 { public static void main(String[] args)throws IOException{ File file=new File("F:\\QQ文件\\properties.ini");//ini文件为配置文件 if(!file.exists()){//判断文件是否存在 file.createNewFile();//不存在则创建 } FileInputStream fis=new FileInputStream(file); Properties prop=new Properties(); prop.load(fis);//加载 fis.close();//加载后就关闭,免得读写流错乱 if(prop.getProperty("time")==null){//如果配置文件不存在time prop.setProperty("time","0");//就创建一个值 }//time作为文件中描述次数的Key System.out.println(prop); int count=Integer.parseInt(prop.getProperty("time")); count++;//获取次数并自增 prop.setProperty("time", count+"");//将改变的次数设置到集合中 FileOutputStream fos=new FileOutputStream(file); prop.store(fos, "zhushi");//将集合数据存储到文件中,注释 if(count>=5){ System.out.println("次数已到,请交钱购买"); return ;//方法结束 } System.out.println("已使用"+count+"次"); fos.close(); } }