------Java培训、Android培训、iOS培训、.Net培训、期待与您交流!-------
一、File类
用来将文件和文件夹封装成对象
方便对文件和文件夹的属性进行操作
File对象可以作为参数传递给流的构造函数
流对象:
FileReader
FileWriter
FileOutputStre
FileInputStream
常用的方法:
1.构造方法和字段
//1.可以将一个已存在或者不存在的文件或者目录封装成对象
File f1 = new File("f:\\a.txt");
//2.这个和1比较可以改变目录和目录下的其他文件,不局限于f盘和f盘下的a.txt
File f2 = new File("f:\\","a.txt");
//3.和2比较可以对f进行file对象操作,原来只能按照字符串进行操作
File f = new File("f:\\");
File f3 = new File(f,"a.txt");
//4.字段摘要
/*File f4 = new File("f:\\abc\\a.txt");在UNIX下不可以,
UNIX只认同“/”所以可以用file.separator*/
File f4 = new File("f:"+File.separator+"abc"+File.separator+"a.txt");
2.常用的方法
(1)获取
File file = new File("gbk_3.txt");
//获取名称
String name = file.getName();
//获取文件的路径
String path = file.getAbsolutePath();//绝对路径
String path1 = file.getPath();//相对路径
//文件大小
long len = file.length();
//获取文件的修改时间
long time = file.lastModified();
补充:获取有效的时间(*)
long time = file.lastModified();
Date date = new Date(time);
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG);
String str_time = dateFormat.format(date);
(2)创建和删除
文件的创建和删除
File file = new File("file.txt");
// 1.文件的创建,和输出流不一样,如果文件存在则不创建,反之则创建
file.createNewFile();
//2.文件的删除
file.delete();
文件夹的创建和删除
//1.单目录文件夹
File dir1 = new File("nba");
dir1.mkdir();//创建
dir1.delete();//删除
//2.多级目录文件夹
File dir = new File("abc\\v\\c\\d\\v\\h\\j\\k\\l");//将“l”封装成了对象
dir.mkdirs();
dir.delete();//删除的是“l”文件夹
注意:windows删除是从内往外删除,如果目录中有内容目录则不会被删除
(3)判断
File file = new File("a.txt");
//判断文件是否存在
file.exists();
//判断是否是文件
file.isFile();
//判断是否是目录
file.isDirectory();
注意:最好先判断文件是否存在,如果文件不存在,判断的结果都是false
(4)重命名
File file = new File("f:\\0.jpg");
File file2 = new File("f:\\3.jpg");
File file3 = new File("d:\\aa.jpg");
//重命名
file.renameTo(file2);
//剪切
file.renameTo(file3);
(5)获取系统的根目录及容量的获取
File file = new File("d:\\");
//可用空间,迅雷看看下载就选择最大空闲的盘符
System.out.println(file.getFreeSpace());
//总容量
System.out.println(file.getTotalSpace());
//虚拟机可用空间(不常用)
System.out.println(file.getUsableSpace());
(6)获取目录内容
/*
* 获取当前目录下文件以及文件夹名称,包含隐藏的文件,调用list方法
* 的file对象中封装的必须是目录,否则会发生空指针异常,如果访问的
* 系统级目录也会发生空指针异常,如果目录存在但是没有内容,会返回
* 一个数组,但是长度为0。
*/
File file = new File("f:\\");
String[] names = file.list();
for(String name:names){
System.out.println(name);
}
(7)过滤器
过滤器1的定义:
public class FileByJava implements FilenameFilter { @Override public boolean accept(File dir, String name) { //遍历数组,进行运算,只要返回的是true,就存储文件 return name.endsWith(".java"); } } 过滤f盘下的".java"文件: File file = new File("f:\\"); String[] names = file.list(new FileByJava()); for(String name:names){ System.out.println(name); }
过滤器2的定义:(过滤隐藏文件)
public class FilterByHidden implements FileFilter { @Override public boolean accept(File pathname) { return !pathname.isHidden(); } }
过滤器3的定义:(根据后缀名过滤)
public class SuffixFilter implements FilenameFilter { private String suffix; private SuffixFilter(String suffix) { super(); this.suffix = suffix; } @Override public boolean accept(File dir, String name) { return name.endsWith(suffix); } }
例子:
1.深度遍历文件夹 ,并且有层级显示
import java.io.File; public class TestDemo6 { /** * @param args */ public static void main(String[] args) { File dir = new File("f:\\demodir"); listAll(dir,0); } private static void listAll(File dir,int level) { System.out.println(getSpace(level)+dir.getName()); level++; //获取指定目录下的当前的所有文件夹或者文件对象 File[] files = dir.listFiles(); for(int x = 0; x<files.length; x++){ if(files[x].isDirectory()) listAll(files[x],level); else System.out.println(getSpace(level)+files[x].getAbsolutePath()); } } private static String getSpace(int level) { StringBuilder sb = new StringBuilder(); for(int x=0; x<level; x++){ sb.append(" "); } return sb.toString(); } }
2.递归
定义:函数自身或者间接的调用了自身
注意:(1)递归一定要明确条件,否则容易栈溢出,(2)注意递归的次数,防止栈溢出
求二进制
private static void toBin(int num) { if(num>0) toBin(num/2); System.out.print(num%2); }
求和
private static int getSum(int num) { if(num==1) return 1; return num+getSum(num-1); }
3.删除目录
需要深度遍历目录,必须从里面往外删除
import java.io.File; public class TestDemo8 { /** * @param args */ public static void main(String[] args) { File dir = new File("f:\\demodir"); removeDir(dir); } private static void removeDir(File dir) { File[] files = dir.listFiles(); for(File file : files){ if(file.isDirectory()) removeDir(file); else System.out.println(file+" "+file.delete()); } System.out.println(dir+" "+dir.delete()); } }
二、Properties
特点:
1.该集合中的键和值嗾使字符串类型
2.该集合中的数据可以保存到流中,或者从流中获取
通常该集合用于操作以键值对形式存在的配置文件
1.Properties集合的存和取
Properties prop = new Properties(); //存储元素,用到setProperty方法 prop.setProperty("zhangsan", "31"); prop.setProperty("lisi", "28"); prop.setProperty("xiaoqiang", "15"); //修改元素,键不变值改变 prop.setProperty("zhangsan", "39"); //取元素,用到setProperty方法 Set<String> names = prop.stringPropertyNames(); for(String name : names){ String value = prop.getProperty(name); System.out.println(name+":"+value); }
2.list方法
Properties prop = new Properties(); prop.setProperty("zhangsan", "31"); prop.list(System.out);
3.store方法
Properties prop = new Properties(); prop.setProperty("zhangsan", "31"); prop.setProperty("lisi", "28"); prop.setProperty("xiaoqiang", "15"); //想要持久化存储信息需要关联流 FileOutputStream fos = new FileOutputStream("info.txt"); prop.store(fos, "info"); fos.close();
4.修改配置信息
load方法:
//集合中的数据来源于一个文件,注意必须要保证该文件中的数据时键值对,需要用到读取流 Properties prop = new Properties(); FileInputStream fis = new FileInputStream("info.txt"); //使用load方法 prop.load(fis); prop.list(System.out); fis.close();
修改配置文件
/* * 1.读取这个文件,并将这个文件中的键值数据存储到集合中 * 2.在通过集合对数据进行修改 * 3.在通过流将修改后的数据存储到文件中 */ //读取文件 File file = new File("info.txt"); if(!file.exists()) file.createNewFile(); FileReader fr = new FileReader("info.txt"); //创建集合存储数据 Properties prop = new Properties(); //将流中的数据存储到集合中 prop.load(fr); //修改信息 prop.setProperty("zhangsan", "100"); //将修该后的数据存储 FileWriter fw = new FileWriter(file); prop.store(fw, "info1"); fr.close(); fw.close();
注意:
不要紧跟着输入流创建后创建输出流,将输出流在修改配置文件后再创建,因为原来的数据会被覆盖。
练习1:获取一个应用程序运行次数,如果超过5次,给出使用次数已到请注册的提示,并不要运行程序
思路:
1.应该有计数器
每次程序的启动都需要计数一次,并且是在原有的次数上进行计数
2.计数器是一个变量
程序启动时进行计数,计数器必须存在于内存并进行运算,而我们需要多次启动同一个应用程序,使用同一个计数器。而这就需要计数器的生命周期变长,从内存存储到硬盘文件中。
3.如何使用这个计数器呢?
首先,程序启动时,应该先读取这个用于记录计数器信息的配置文件,获取上一次计数器次数,并进行使用次数的判断。其次,对该次数进行自增,并自增后的次数重新存储到配置文件中。
4.文件中的信息该如何存储并体现呢?
直接存储数值可以,但不明确该数据的含义,所以起名字就显得比较重要。这就有了名字和值得对应,所以可以使用键值对,可用映射关系map集合搞定,又需要读取硬盘上的数据,所以map+io=properties
//将配置文件封装成file对象 File confile = new File("count.properties"); if(!confile.exists()) confile.createNewFile(); FileInputStream fis = new FileInputStream(confile); Properties prop = new Properties(); prop.load(fis); //从集合中通过键获取次数 String value = prop.getProperty("time"); int count = 0; if(value!=null){ count=Integer.parseInt(value); if(count>=5) throw new RuntimeException("使用次数已到,请注册,购买正版!!"); } count++; //将改变后的次数重新存储到集合中 prop.setProperty("time", count+""); FileOutputStream fos = new FileOutputStream(confile); prop.store(fos, ""); fos.close(); fis.close(); }
练习2:建立指定扩展名的文件清单列表
思路:
1.必须进行深度遍历
2.要在遍历的过程中进行过滤,将符合条件的内容都存储到容器中
3.对容器中的这些内容进行遍历,并将绝对路径写入到文件中
import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.FilenameFilter; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class TestDemo9 { /** * @param args */ public static void main(String[] args) { File dir = new File("F:\\Workspaces\\MyEclipse 10\\Review\\src"); FilenameFilter filter = new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.endsWith(".java"); } }; List<File> list = new ArrayList<File>(); getFile(dir, filter, list); File destFile = new File(dir,"test.txt"); write2File(list, destFile); } public static void getFile(File dir ,FilenameFilter filter,List<File> list){ File[] files = dir.listFiles(); for(File file : files){ if(file.isDirectory()){ getFile(file, filter, list); } else{ if(filter.accept(dir, file.getName())){ list.add(file); } } } } public static void write2File(List<File> list,File destFile){ BufferedWriter bufw = null; try { bufw = new BufferedWriter(new FileWriter(destFile)); for(File file :list){ bufw.write(file.getAbsolutePath()); bufw.newLine(); bufw.flush(); } } catch (IOException e) { throw new RuntimeException("写入失败"); }finally{ if(bufw!=null) try { bufw.close(); } catch (IOException e) { throw new RuntimeException("关闭失败"); } } } }
三、IO包中的其他类
1.打印流
PrintStream
(1)提供了打印的方法可以对多种数据类型值进行打印,并保持数据的表示形式
(2)它不抛IoException
构造函数,接受三种不同的类型的值
(1)字符串路径
(2)File对象
(3)字节输出流
PrintStream out = new PrintStream("print.txt"); //out.write(97);结果是a,只写最低八位 out.print(97);//将97先变成字符,保持原样的数据打印到目的地 out.close();
PrintWriter
构造函数参数:
(1)字符串路径
(2)File对象
(3)字节输出流
(4)字符输出流
例1
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); PrintWriter out = new PrintWriter(System.out); String line = null; while((line=bufr.readLine())!=null){ if("over".equals(line)) break; out.println(line.toUpperCase()); out.flush(); } out.close(); bufr.close();
例2
PrintWriter out = new PrintWriter(System.out,true); 替换上面的 PrintWriter out = new PrintWriter(System.out); //可以不用刷新,即可以不用写out.flush();
例3
PrintWriter out = new PrintWriter(new FileWriter("out.txt"),true); 替换上面的 PrintWriter out = new PrintWriter(System.out,true); //可以实现自动刷新
2.序列流-SequenceInputstream
对多个流进行合并
例子1:将1.txt,2.txt,3.txt文件中的数据合并成一个文件中
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>(); for(int x=1; x<=3; x++){ al.add(new FileInputStream(x+".txt")); } Enumeration<FileInputStream> en = Collections.enumeration(al); SequenceInputStream sis = new SequenceInputStream(en); FileOutputStream fos = new FileOutputStream("4.txt"); byte[] buf = new byte[1024]; int len=0; while((len=sis.read(buf))!=-1){ fos.write(buf,0,len); } fos.close(); sis.close(); }
例子2:文件的切割
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class TestDemo10 { /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { File file = new File("f:\\1.mp3"); spiltFile(file); } private static void spiltFile(File file) throws IOException { FileInputStream fis = new FileInputStream(file); byte[] buf = new byte[1024*1024]; FileOutputStream fos = null; int len = 0; int count = 1; File dir = new File("f:\\properties"); if(!dir.exists()) dir.mkdir(); while((len=fis.read(buf))!=-1){ fos=new FileOutputStream(new File(dir,(count++)+".part")); fos.write(buf,0,len); } fis.close(); fos.close(); } }
例子3:文件的切割加配置文件
切割文件是,必须记录住被切割文件的名称,以及切割出来的碎片文件的个数,以便于合并。这个信息为了描述,使用键值对的方式,用到了properties对象
package io; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.Properties; public class TestDemo10 { /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { File file = new File("f:\\1.flv"); spiltFile(file); } private static void spiltFile(File file) throws IOException { FileInputStream fis = new FileInputStream(file); byte[] buf = new byte[1024*1024]; FileOutputStream fos = null; int len = 0; int count = 1; Properties prop = new Properties(); File dir = new File("f:\\properties"); if(!dir.exists()) dir.mkdir(); while((len=fis.read(buf))!=-1){ fos=new FileOutputStream(new File(dir,(count++)+".part")); fos.write(buf,0,len); fos.close(); } prop.setProperty("partCount", count+""); prop.setProperty("fileName", file.getName()); fos=new FileOutputStream(new File(dir, (count)+".properties")); prop.store(fos, "info"); fis.close(); fos.close(); } }
例子4 文件的合并加配置文件
package io; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.SequenceInputStream; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.Properties; import filter.SuffixFilter; public class TestDemo11 { /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { File dir = new File("f:\\properties"); //因为该目录不知道有“x.properties”x是多少,但是只有一个扩展名为properties文件所以用到过滤器 File[] files = dir.listFiles(new SuffixFilter(".properties")); if(files.length!=1){ throw new RuntimeException(dir+",该目录下没有properties文件或者不唯一"); } //记录配置文件对象 File confile = files[0]; //获取该文件中的信息 Properties prop = new Properties(); FileInputStream fis = new FileInputStream(confile); prop.load(fis); String fileName = prop.getProperty("fileName"); int count = Integer.parseInt(prop.getProperty("partCount")); //获取该目录下的所有碎片文件 File[] partFiles = dir.listFiles(new SuffixFilter(".part")); if(partFiles.length!=(count-1)){ throw new RuntimeException("碎片文件不符文要求,个数不对,应该为"+count+"个"); } ArrayList<FileInputStream> al = new ArrayList<FileInputStream>(); for(int x=1; x<partFiles.length; x++){ al.add(new FileInputStream(partFiles[x])); } Enumeration<FileInputStream> en = Collections.enumeration(al); SequenceInputStream sis = new SequenceInputStream(en); FileOutputStream fos = new FileOutputStream(fileName); byte[] buf = new byte[1024]; int len = 0; while((len=sis.read(buf))!=-1){ fos.write(buf,0,len); } fos.close(); sis.close(); } }
3.对象的序列化-ObjectInputStrea和ObjectOutputStream
对象的序列化:将数据作为对象放入硬盘进行持久化存储
//一般存储对象的文件的后缀名用object ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.object")); //对象的序列化,被序列化的对象必须实现Serializable接口 oos.writeObject(new Person("小强",25)); oos.close();
对象的反序列化:对象被序列化存储后,读取序列化的对象
ObjectInputStream对以前ObjectOutputStream写入的基本数据和对象进行反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.object")); //因为知道文件对象是Person、,所以可以强转 Person p = (Person) ois.readObject(); System.out.println(p.getName()+":"+p.getAge());
Serializable接口
如果读取序列化对象文件,而反序列化过程中对象变了,则会放生异常。
解释:例如Person实现了Serializable接口,此时该Person具备了ID号,而序列化过程,序列化和这个来相关联,而反序列化过程中Person类改变了,所以ID号变了,因此放生了异常。
总的来说:Serializable就是给序列化的类加上一个ID号,用于判断类和对象是否是同一个版本
怎么给可序列化类声明一个ID号呢?
public class Person implements Serializable{
private static final long serialVersionUID =125845641651L;
后面代码略
序列化这个知识点在以后的web开发中会用到。
transient关键字
比如:有些数据,不是公共数据,对象特有的,不能静态
例如:不想将name这个非静态的数据序列化。
private transient String name;
private static int age;
结果反序列化的结果是:
null:0
4.RandomAccessFile-随机访问文件
不是IO体系的子类
特点:
1.该对象既能读又能写
2.该对象内部维护了一个byte数据,并通过指针操作数组中的元素
3.可以通过getFilePointer方法获取指针的位置,和通过get方法设置指针的位置
4.其实该对象就是讲字节输入流和输出进行了封装
5.该对象的源和吗目的只能是文件
1.写数据
//如果文件不存在,则创建;如果存在则不会创建 RandomAccessFile raf = new RandomAccessFile("ranacc.txt", "rw"); raf.write("张三".getBytes()); //raf.write(97);只写最低8位 raf.writeInt(97);//按4个字节写,先写高位 raf.write("小王".getBytes()); raf.writeInt(25); raf.close();
2.读取或随机读取
ranacc.txt文件内容
读取:
RandomAccessFile raf = new RandomAccessFile("ranacc.txt", "r"); byte[] buf = new byte[4]; raf.read(buf); String name = new String(buf); //因为年龄是整数,用readInt更方便 int age = raf.readInt(); System.out.println(name); System.out.println(age); raf.close();
随机读取:
RandomAccessFile raf = new RandomAccessFile("ranacc.txt", "r"); //通过seek来设置指针的位置 raf.seek(1*8);//随机的读取,只要指定指针的位置即可 byte[] buf = new byte[4]; raf.read(buf); String name = new String(buf); int age = raf.readInt(); System.out.println("name="+name); System.out.println("age="+age); //指针的位置 System.out.println("pos:"+raf.getFilePointer()); raf.close();
3.随机写
紧接着rannac.txt后面写入
RandomAccessFile raf = new RandomAccessFile("ranacc.txt", "rw"); raf.seek(raf.length()); raf.write("哈哈".getBytes()); raf.close();
用处:多线程写入用到RandomAccessFile。
5.管道流-PipedInputStream和PipedOutputStream
不能单线程使用,不然会死锁
例子:
package io; import java.io.IOException; import java.io.PipedInputStream; import java.io.PipedOutputStream; public class PipedDemo { /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { PipedInputStream input = new PipedInputStream(); PipedOutputStream output = new PipedOutputStream(); input.connect(output); new Thread(new Input(input)).start(); new Thread(new Output(output)).start(); } } class Input implements Runnable{ private PipedInputStream in; Input(PipedInputStream in) { super(); this.in = in; } @Override public void run() { try { byte[] buf = new byte[1024]; int len = in.read(buf); String s = new String(buf,0,len); System.out.println(s); in.close(); } catch (IOException e) { e.printStackTrace(); }; } } class Output implements Runnable{ private PipedOutputStream out; Output(PipedOutputStream out) { super(); this.out = out; } @Override public void run() { try { Thread.sleep(5000); out.write("s=hi,管道来了".getBytes()); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } }
6.操作基本数据类型:DataOutputStream 和DataInputStream
写数据
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt")); dos.writeUTF("你好"); dos.close();
读数据
DataInputStream dis = new DataInputStream(new FileInputStream("data.txt")); String str = dis.readUTF(); System.out.println(str); dis.close();
7.操作字节数组
不需要关闭流,此类中的close方法在关闭此流后仍可被调用。该对象一创建必须要有源,源是字节数组。
ByteArrayInputStream bis = new ByteArrayInputStream("abcd".getBytes()); ByteArrayOutputStream bos = new ByteArrayOutputStream(); int ch=0; while((ch=bis.read())!=-1){ bos.write(ch); } System.out.println(bos.toString());
8.操作字符数组
CharArrayReader;
CharArrayWriter
类似上,源是字符数组。
9.操作字符串
StringReader;
StringWriter
类似上,源是字符串。
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流!-------
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。