一、IO流 —— File 概述
1、 File 是文件和目录路径名的抽象表示形式。 作用: 用来将文件或者文件夹封装成对象; 方便对文件与文件夹的属性信息进行操作; File 对象可以作为参数传递给流的构造函数。 java.lang.Object -java.io.File public class File extends Object implements Serializable, Comparable<File> 2、字段摘要: static String separator 与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串。 3、示例代码:import java.io.*; class FileDemo { public static void main(String[] args) { //目录分隔符 String se = File.separator; //将a.txt封装成对象。可以将已有的或未出现的文件和文件夹封装成对象。 File f1 = new File("a.txt"); File f2 = new File("d:"+se+"abc","b.txt"); File d = new File("d:\\abc"); File f3 = new File(d,"c.txt"); //打印:封装的是什么,就打印什么 System.out.println("f1="+f1);// a.txt System.out.println("f2="+f2);// d:\abc\b.txt System.out.println("f3="+f3);// d:\abc\c.txt } }
二、 File 对象功能——创建和删除
File 类的常见方法:
1、创建
boolean createNewFile(); 在指定位置创建文件;如果该文件已经存在,则不创建。该方法会抛出 IOException 。
static File createTempFile(String prefix, String suffix);在默认临时文件目录中创建一个空文件。
static File createTempFile(String prefix, String suffix, File directory); 在指定目录中创建一个新的空文件。
boolean mkdir(); 只能创建一级目录;如果目录已经存在,则不创建。
boolean mkdirs(); 可以创建多级目录,也可以创建一级目录;同上。
2、删除
boolean delete(); 删除文件。注意,如果一个文件正在被使用,或者在读取到delete这段代码之前,程序发生异常;那么有可能删除文件不成功。
对于一些临时文件就可以调用deleteOnExit()方法删除。
void deleteOnExit(); 在退出时删除。
示例代码:import java.io.*; class FileDemo2 { public static void main(String[] args) { method_1(); method_2(); } public static void method_1() throws IOException { File f = new File("file.txt"); //f.deleteOnExit(); boolean bl = f.createNewFile(); System.out.println(bl); System.out.println("delete: "+f.delete()); } public static void method_2() { File dirs = new File("a\\b\\c"); File dir = new File("abc"); System.out.println("dirs: "+dirs.mkdirs()); System.out.println("dir: "+dir.mkdir()); } }
三、 File 对象功能——判断
3、判断
boolean canExecute(); 可否执行
boolean exists(); 文件或文件夹是否存在
boolean isDirectory(); 是否是目录
boolean isFile(); 是否是文件
boolean isHidden(); 是否是隐藏文件
boolean isAbsolute(); 是否是绝对路径名
代码:import java.io.*; class FileDemo3 { public static void main(String[] args) { method_3(); method_4(); } public static void method_3() { File f = new File("file.txt"); sop("exists: "+f.exists()); sop("execute: "+f.canExecute()); } public static void method_4() throws IOException { File f = new File("file.txt"); //f.createNewFile(); sop("mkdir: "+f.mkdir()); //在判断文件对象是否是文件或者目录时,必须先判断该文件对象封装的内容是否存在。 //通过 exists() 判断。 sop("exists: "+f.exists()); sop("dir: "+f.isDirectory()); sop("file: "+f.isFile()); } public static void sop(Object obj) { System.out.println(obj); } }
四、 File 对象功能——获取
4、获取信息
String getName(); 获取文件或者目录名
String getParent(); 获取绝对路径中的父目录,如果此路径名没有指定父目录,则返回 null 。
String getPath(); 获取路径名(封装什么,就返回什么)
String getAbsolutePath(); 获取绝对路径
File getAbsoluteFile(); 获取绝对路径对象
long lastModified(); 获取最后修改时间
long length(); 获取文件的长度,参考 int available()
boolean renameTo(File dest); 重命名文件对象。实际上是创建新文件,并将原文件中的内容复制到新文件中,同时删除原有文件。
功能代码:public static void method_5()throws IOException { //File f = new File("d:\\abc\\a.txt"); File f = new File("file.txt"); f.createNewFile(); sop("path: "+f.getPath()); sop("abspath: "+f.getAbsolutePath()); sop("getNme: "+f.getName()); sop("getParent: "+f.getParent()); sop("lastModefied: "+f.lastModified()); sop("length: "+f.length()); } public static void method_6() { File f1 = new File("d:\\file.txt"); File f2 = new File("rename.txt"); sop("rename: "+f1.renameTo(f2)); } public static void sop(Object obj) { System.out.println(obj); }
五、 File 对象功能——文件列表
static File[] listRoots(); 获取盘符
String[] list(); 列出指定目录中的文件和文件夹,包括隐藏部分。调用该方法的 File 对象必须是封装了一个目录,该目录还必须存在。
功能代码:public static void listRootsDemo() { File[] files = File.listRoots(); /* for (int x=0 ;x<files.length ;x++ ) { System.out.println(files[x]); } */ for(File f : files) { System.out.println(f); } } public static void listDemo() { File f = new File("d:\\"); String[] names = f.list(); for(String name : names) { System.out.println(name); } }
六、 File 对象功能——文件列表
java.io.FilenameFilter
public interface FilenameFilter
该接口只有一个方法: boolean accept(File dir, String name); 测试指定文件是否应该包含在某一文件列表中。
String[] list(FilenameFilter filter); 返回满足指定过滤器的文件名和目录名
File[] listFiles();
File[] listFiles(FileFilter filter);
File[] listFiles(FilenameFilter filter);
返回的是 File 对象。
功能代码:public static void listDemo_2() { File dir = new File("d:\\java\\javadiary\\day20"); String[] arr = dir.list(new FilenameFilter() { public boolean accept(File dir, String name) { //System.out.println("dir: "+dir+"---name: "+name); //return true; return name.endsWith(".java"); } }); System.out.println("length: "+arr.length); for(String name : arr) { System.out.println(name); } } public static void listDemo_3() { File dir = new File("d:\\java\\javadiary\\day20"); File[] files = dir.listFiles(); for(File f : files) { System.out.println(f.getName()+"::"+f.length()); } }
七、列出目录下所有内容——递归
程序调用自身的编程技巧称为递归(recursion)。(来自网络释义)
需求:列出指定目录下的文件或者文件夹,包含子目录中的内容。
也就是列出指定目录下的所有内容。
思路:因为目录中还有目录,只要使用同一个列出目录的功能调用函数即可;在列出过程中出现的还是目录的话,还可以再次调用本功能;也就是函数自身调用自身;这种编程手法称为递归。
代码见下一节。
递归要注意:
1、限定条件;
2、注意递归次数,避免内存溢出。
===当递归次数过多时,栈内存中调用的方法也过多,会出现内存溢出。
代码示例:class RecursionDemo { public static void main(String[] args) { int sum = getSum(5); System.out.println("sum="+sum);//15 toBin(6);//110 } public static int getSum(int n) { if(n==1) return 1; else return n+getSum(n-1); } public static void toBin(int num) { if(num>0) { toBin(num/2); System.out.print(num%2); } } }
八、列出目录下所有内容——带层次
上一节优化后代码:class FileDemo { public static void main(String[] args) { File dir = new File("d:\\java\\javadiary"); showDir(dir,0); } public static void showDir(File dir, int level) { System.out.println(getLevel(level)+dir.getName()); level++; File[] files = dir.listFiles(); for (int x=0 ;x<files.length ;x++ ) { if(files[x].isDirectory()) showDir(files[x],level); else System.out.println(getLevel(level)+files[x]); } } public static String getLevel(int level) { StringBuilder sb = new StringBuilder(); sb.append("|--"); for (int x=0 ;x<level ;x++ ) { sb.insert(0," "); } return sb.toString(); } }
九、删除带内容的目录
删除原理:
在window中,删除目录是从里面往外删除的。
用递归可以解决。
代码:import java.io.*; class RemoveDir { public static void main(String[] args) { File dir = new File("d:\\abc"); removeDir(dir); } public static void removeDir(File dir) { File[] files = dir.listFiles(); for (int x=0 ;x<files.length ;x++ ) { if(files[x].isDirectory()) removeDir(files[x]); else System.out.println(files[x].toString()+":--:"+files[x].delete()); } System.out.println(dir+"::dir::"+dir.delete()); } }
十、创建java文件列表
练习:
将一个指定目录下的java文件的绝对路径,存储到一个文本文件中。
也就是建立一个java文件的列表文件。
思路:
1、对指定的目录进行递归;
2、获取递归过程中所有的java文件路径;
3、将这些路径存储到集合中;
4、将集合中的数据写入到一个文件中。
======将数据存储到硬盘当中,叫数据的持久化。
代码:import java.io.*; import java.util.*; class JavaFileList { public static void main(String[] args) throws IOException { File dir = new File("d:\\java\\javadiary"); List<File> list = new ArrayList<File>(); fileToList(dir,list); //System.out.println(list.size()); File file = new File(dir,"javalist.txt"); writeToFile(list, file.toString()); } public static void fileToList(File dir, List<File> list) { File[] files = dir.listFiles(); for(File file : files) { if(file.isDirectory()) fileToList(file,list); else { if(file.getName().endsWith(".java")) list.add(file); } } } public static void writeToFile(List<File> list, String javaListFile) throws IOException { BufferedWriter bufw = null; try { bufw = new BufferedWriter(new FileWriter(javaListFile)); for(File f : list) { String path = f.getAbsolutePath(); bufw.write(path); bufw.newLine(); bufw.flush(); } } catch (IOException e) { throw e; } finally { try { if(bufw!=null) bufw.close(); } catch (IOException e) { throw e; } } } }
十一、 Properties 简述
java.util.Dictionary
-Hashtable
-Properties
Properties 是 Hashtable 的子类,也就是说它具备 Map 集合的特点,而且它里面存储的键值对都是字符串。
它是集合中和IO技术相结合的集合容器。
该对象的特点:
可以用于键值对形式的配置文件。
在加载数据时,需要数据有固定格式:键=值十二、 Properties 存取
Properties 的基本常用方法:
String getProperty(String key) :用指定的键在此属性列表中搜索属性。
Object setProperty(String key, String value) :调用 Hashtable 的方法 put。也就相当于添加。
Set<String> stringPropertyNames() :返回此属性列表中的键集,其中该键及其对应值是字符串,如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键。
class PerpertiesDemo { public static void main(String[] args) { setAndGet(); } //设置和获取元素 public static void setAndGet() { Properties prop = new Properties(); prop.setProperty("zhangsan","30"); prop.setProperty("lisi","39"); System.out.println(prop); String value = prop.getProperty("lisi"); System.out.println("value="+value); prop.setProperty("lisi",89+""); Set<String> names = prop.stringPropertyNames(); for(String s : names) { System.out.println(s+": "+prop.getProperty(s)); } } }
十三、 Properties 存取配置文件
演示:如何将流中的数据存储到集合中。
将info.txt中键值对数据存到集合中。
思路:
1、用一个流和info.txt文件关联;
2、读取一行数据,将该行数据用"="切割;
3、等号左边作为键,右边作为值,存入到Properties集合中即可。
public static void method_1() throws IOException { BufferedReader bufr = new BufferedReader(new FileReader("info.txt")); String line = null; Properties prop = new Properties(); while((line=bufr.readLine())!=null) { String[] arr = line.split("="); //System.out.println(arr[0]+"...."+arr[1]); prop.setProperty(arr[0],arr[1]); } bufr.close(); System.out.println(prop); }
以上方法为早期做法,JDK1.6版本后, Properties 有一个方法load()可以直接加载文件中的配置信息:
void load(InputStream inStream) :从输入流中读取属性列表(键和元素对)。
void load(Reader reader) :按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
其他常用方法:
void store(OutputStream out, String comments) :将 Properties 表中的属性列表(键和元素对)写入输出流。
void store(Writer writer, String comments) :将 Properties 表中的属性列表(键和元素对)写入输出字符。
代码示例如下:public static void loadDemo() throws IOException { //创建一个字节读取流 FileInputStream fis = new FileInputStream("info.txt"); Properties prop = new Properties(); //将流中的数据加载进集合 prop.load(fis); //更改配置信息 prop.setProperty("wangwu","39"); //将更改后的配置信息持久化存储,需先创建字节写入流 FileOutputStream fos = new FileOutputStream("info.txt"); //将更改后的数据通过流存入硬盘中的文件 prop.store(fos,"haha"); //System.out.println(prop); prop.list(System.out);//列表清单 fos.close(); fis.close(); }
=====凡是每行开头带#的都代表注释信息,不会被 Properties 加载。十四、 Properties 练习
需求:
使用一个配置文件,用于记录应用程序运行次数:
如果使用次数已到,那么给出注册提示。
思路:
用 Propertied 存储计数器的数据。import java.io.*; import java.util.*; class RunCount { public static void main(String[] args) throws IOException { Properties prop = new Properties(); //先将文件封装成对象 File file = new File("count.ini"); if(!file.exists()) file.createNewFile(); FileInputStream fis = new FileInputStream(file); prop.load(fis); int count = 0; String value = prop.getProperty("time"); if(value!=null) { count = Integer.parseInt(value); if(count>=5) { System.out.println("使用次数已到"); return ; } } count++; prop.setProperty("time", count+""); FileOutputStream fos = new FileOutputStream(file); prop.store(fos,""); fos.close(); fis.close(); } }
十五、 PrintWriter
java.lang.Object
-java.io.Writer
java.io.PrintWriter
public class PrintWriter extends Writer
java.lang.Object
-java.io.OutputStream
-java.io.FilterOutputStream
-java.io.PrintStream
public class PrintStream extends FilterOutputStream implements Appendable, Closeable
打印流:
该流提供了打印方法,可以将各种数据类型的数据都原样打印。
PrintStream: 字节打印流
构造函数可以接收的参数类型:
1、file对象: File
2、字符串路径: String
3、字节输出流: OutputStream
PrintWriter: 字符打印流
构造函数可以接收的参数类型:
1、file对象: File
2、字符串路径: String
3、字节输出流: OutputStream
4、字符输出流: Writer
代码:import java.io.*; class PrintStreamDemo { public static void main(String[] args) throws IOException { BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); //PrintWriter out = new PrintWriter(System.out, true); PrintWriter out = new PrintWriter(new FileWriter("a.txt"), true);//构造函数中传入true参数,该流可以自动刷新 String line = null; while((line=bufr.readLine())!=null) { if("over".equals(line)) break; out.println(line.toUpperCase()); //out.write(line.toUpperCase()); //out.write("\r\n"); //out.flush(); } out.close(); bufr.close(); } }
十六、合并流
java.lang.Object
-java.io.InputStream
-java.io.SequenceInputStream
序列流:
SequenceInputStream : 对多个流进行合并。该类是 InputStream 的子类,因此它是一个字节读取流。
构造方法:
SequenceInputStream(Enumeration<? extends InputStream> e);
该构造方法接收一个 Enumeration 对象,该对象中定义的泛型是 InputStream 类型或者子类类型,可用于合并多个字节流。
SequenceInputStream(InputStream s1, InputStream s2);
该构造方法接收两个 InputStream ,用于合并两个字节流。 代码:import java.util.*; import java.io.*; class SequenceDemo { public static void main(String[] args) throws IOException { Vector<FileInputStream> v = new Vector<FileInputStream>(); v.add(new FileInputStream("1.txt")); v.add(new FileInputStream("2.txt")); v.add(new FileInputStream("3.txt")); Enumeration<FileInputStream> en = v.elements(); SequenceInputStream sis = new SequenceInputStream(en); FileOutputStream fos = new FileOutputStream("123.txt"); byte[] buf = new byte[1024]; int len=0; while ((len=sis.read(buf))!=-1) { fos.write(buf,0,len); } fos.close(); sis.close(); } }
十七、IO流——切割文件
import java.io.*; import java.util.*; class SplitFile { public static void main(String[] args) throws IOException { //splitFile(); merge(); } //切割文件 public static void splitFile() throws IOException { FileInputStream fis = new FileInputStream("123.mp3"); FileOutputStream fos = null; byte[] buf = new byte[1024*1024]; int len=0, count=1; while((len=fis.read(buf))!=-1) { fos = new FileOutputStream(count+".part"); count++; fos.write(buf,0,len); fos.close(); } fis.close(); } //文件合并 public static void merge() throws IOException { ArrayList<FileInputStream> al = new ArrayList<FileInputStream>(); for (int x=1 ;x<=3 ;x++ ) { al.add(new FileInputStream(x+".part")); } final Iterator<FileInputStream> it = al.iterator(); Enumeration<FileInputStream> en = new Enumeration<FileInputStream>() { public boolean hasMoreElements() { return it.hasNext(); } public FileInputStream nextElement() { return it.next(); } }; SequenceInputStream sis = new SequenceInputStream(en); FileOutputStream fos = new FileOutputStream("111.mp3"); byte[] buf = new byte[1024]; int len = 0; while((len=sis.read(buf))!=-1) { fos.write(buf,0,len); } fos.close(); sis.close(); } }