文件和io流

file类

  • boolean createNewFile():创建当前File对象所描述的路径的文件

  • boolean mkdirs():创建当前File对象所描述的路径的文件夹(如果父级路径不存在,那么自动创建父级路径)

  • delete在删除文件夹的时候,只能删除空文件夹

  • renameTo(File dest)重命名
    如果在同一个文件夹下,修改路径,就是重命名
    如果在不同文件夹下,修改路径,就是剪切

  • exists():判断当前调用者File对象,是否存在
    isFile():判断当前调用者File对象,是否是文件
    isDirectory():判断当前调用者File对象,是否是文件夹

  • getAbsolutePath():获取当前File对象的绝对路径
    getPath():获取的就是在构造方法中封装的路径
    getName():获取最底层的简单的文件或者文件夹名称(不包含所造目录的路径)
    length():获取文件的字节个数

  • String[] list():获取当前文件夹下的所有文件和文件夹的名称,到一个字符串数组中
    File[] listFiles():获取当前文件夹下的所有文件和文件夹的File对象,到一个File对象数组中

* 案例

递归方式列出某个目录下的所有文件夹名和文件名?

public void print(File f){
        File[] files = f.listFiles();
        for (File ff:files){
            if(ff.isDirectory()){
                System.out.println("当前目录:"+ff.getName());
                print(ff);
            }else{
                System.out.println("当前文件:"+ff.getName());
            }
        }
    }

* 文件过滤

FilenameFilter过滤器中的accept方法接收两个参数,一个当前文件或文件夹所在的路径,一个是当前文件或文件夹对象的名称。
FileFilter 过滤器中的accept方法接受一个参数,这个参数就当前文件或文件夹对象
当我们需要过滤文件名称时就可以使用FilenameFilter这个过滤器,当我们想对当前文件和文件夹进行过滤,就可以使用FileFilter
获得F:/test目录下所有以a开头的文件

public void filterFile(File file){
        File[] files = file.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                if (name.startsWith("a")) {
                    return true;
                }
                return false;
            }
        });
        for (File f:files){
            System.out.println(f.getName());
        }
    }

获得F:/test目录下所有以b开头的文件夹

public void filterDir(File file){
        File[] files = file.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                if (pathname.isDirectory()){
                    if (pathname.getName().startsWith("b")) {
                        return true;
                    }
                }
                return false;
            }
        });

        for (File f:files){
            System.out.println(f.getName());
        }
    }

io流

* io缓冲流高效原因及读写原理

* 字符流

@Test
    public void test4(){
        BufferedReader reader=null;
        BufferedWriter writer=null;
        try {
            reader = new BufferedReader(new FileReader("E:/java/m.txt"));
            writer = new BufferedWriter(new FileWriter("E:/java/rr.txt"));
            String data;
            while ((data=reader.readLine())!=null){
                writer.write(data);
                writer.newLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(writer!=null){
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader!=null){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

* 字节流

@Test
    public void test5(){
        BufferedInputStream is=null;
        BufferedOutputStream os=null;
        try {

            is = new BufferedInputStream(new FileInputStream("E:/java/b.txt"));
            os = new BufferedOutputStream(new FileOutputStream("E:/java/bb.txt"));
            byte[] bytes = new byte[1024];
            int len;
            while ((len=is.read(bytes))!=-1){
                os.write(bytes,0,len);
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(os!=null){
                try {
                    os.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
            if (is!=null){
                try {
                    is.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }


    }

* 转换流

字节流转换为字符流。

有时,我们需要将字节流转换为字符流,使用InputStreamReader和OutputStreamWriter。

io流中拷贝uft-8格式文件举例

PrintStream(字节打印流)

输出

注意事项:

1、如果直接使用System.out的方式来获取PrintStream的对象,这个对象默认关联的输出目的地就是控制台;如果手动创建PrintStream的对象,那么关联的就是指定的设备。

2、PrintStream中重载了很多print和println的方法,有两个比较特殊,print(char[] arr)、print(Object obj)。一般的数组使用print方法,会直接打印数组的地址,唯独字符数组打印之后出现的是数组的内容。普通的数组走的都是println(Object obj)方法,先获取了数组的toString的内容,也就是数组的地址,而字符数组走的是println(char[] arr)方法,直接调用了write方法用于输出字符内容

PrintWriter(字符打印流)

public static void main(String[] args) throws Exception{
		BufferedReader br = new BufferedReader(new FileReader("c:/bbb.txt"));
		PrintWriter pw = new PrintWriter("D:/bbb.txt");
		
		String str = "";
		
		while((str =br.readLine())!=null){
			pw.println(str);
		}
		pw.close();
		br.close();
	}

Properties

(1)概述

Properties对象表示一个持久的属性集
属性集:属性名称和属性值的对应关系,其实还是一个双列集合
持久的:可以保存到流中,也可以从流中读取。可以很方便和文件进行交互
Properties没有泛型,因为表示一个配置文件中的信息,而配置文件中都是字符串,所以Properties类型不需要使用广泛的类型,存储的键和值都是字符串类型
Properties是Hashtable的子类,所以可以当做普通的Map来使用

(2)Properties中的特有方法

1、getProperty(String propertyName):根据一个字符串类型的属性名称,获取一个对应的属性值
2、setProperties(String propertyName, String propertyValue):将一个属性名和对应的属性值添加到当前对象中
3、stringPropertyNames():获取当前属性集对象中的所有属性名称的Set集合

示例代码

public class Demo08_Properties{
	
	public static void main(String[] args) {
		Properties p = new Properties();
		p.setProperty("id","111");   // 和Map的put类似
		p.setProperty("name", "zhangsan");
		p.setProperty("address","beijing");
		System.out.println(p.getProperty("id"));   //和Map的get类似
		System.out.println(p.getProperty("name"));
		System.out.println(p.getProperty("address"));
		Set<String> set = p.stringPropertyNames();  //和Map中的keySet()类似
		for(String name:set){
			System.out.println(name);
		}
	}
}

(3)Properties和配置文件交互的方式

load(InputStream is)
从流is中,加载配置文件的信息,到内存的Properties对象中,形成双列集合
load(Reader r)
从流r中,加载配置文件的信息,到内存的Properties对象中,形成双列集合
说明:无论是is和r,关联的都是对应的配置文件
store(OutputStream os)
将内存中的Properties对象中键值对信息,写出到流os中
store(Writer w)
将内存中的Properties对象中键值对信息,写出到流w中
说明:无论是os还是w,关联的都是对应的配置文件

注意事项

1、使用prop修改了属性值之后,文件中的属性值不会发生变化,因为prop只修改了内存中的对象数据,没有同步到文件中。必须调用store方法之后,才能将变化同步到文件。

2、调用store方法时,一般需要指定更新属性的原因,即第二个参数comments,如果没有注释,可以传入null;如果有注释,必须是纯英文注释。

示例代码

public class Demo09_Properties操作properties文件 {
	public static void main(String[] args) {
		Properties p = new Properties();
		InputStream is;
		try {
			is = new FileInputStream("test.properties");
			p.load(is);  // 加载properties文件
/*			String id = p.getProperty("user.id");      //读取文件内容
			String name = p.getProperty("user.name");
			String address = p.getProperty("address");
			
			System.out.println(id);
			System.out.println(name);
			System.out.println(address);
*/
			p.setProperty("user.name","李四");     // 向文件中设置值
			p.setProperty("address","shanghai");
			p.setProperty("user.age","22");
			// 以上代码只是把值设置到了内存中的p对象中,还没有向文件中写
			OutputStream os = new FileOutputStream("test.properties");
			p.store(os, "zhushishuomingneirong");
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

3、对象序列化(对象流)

当创建对象时,程序运行时它就会存在,但是程序停止时,对象也就消失了.
但是如果希望对象在程序不运行的情况下仍能保存其信息,将会非常有用,对象将被重建并且拥有与程序上次运行时拥有的信息相同。可以使用对象的序列化。
对象的序列化: 将内存中的对象直接写入到文件设备中或在网络上传输。
对象的反序列化: 将文件设备中持久化的数据转换为内存对象。
基本的序列化由两个方法产生:一个方法用于序列化对象并将它们写入一个流,另一个方法用于读取流并反序列化对象。

(1)ObjectOutputStream

构造方法:ObjectOutputStream(OutputStream os):将一个普通的字节输出流包装成对象输出流
最常用方法:writeObject(Object obj):这个过程叫做序列化

(2)ObjectInputStream

readObject() 这个过程叫做反序列化

注意事项

1、连续序列化对象

当连续两次序列化同一对象引用时,并不会有两个对象被序列化。即使当第一次序列化完成后,修改了对象的值,再次进行序列化,被序列化对象的值也不会发生变化。
第2次和第1次写的是同一个对象,第2次序列化时并不会有两个对象被序列化。第2次只是输出一个序列号编号

版本号问题

在这里插入图片描述

修改了本地的User代码,新的类型和文件中对象的类型已经不一致,所以两个版本冲突了,标志就是两个版本的序列化版本id不同。

解决:不要使用自动生成的序列化版本ID,手动给定一个序列化版本ID,将来这个类型是否发生了版本变化,主要取决于程序员是否手动修改了这个类型的版本ID,如果修改了,那么文件中的对象类型和本地类型就不兼容,如果没有修改这个版本ID,那么无论怎样修改了类型内容,都可以做到文件对象类型和本地类型兼容。

案例

class User implements Serializable{
	
	private static final long serialVersionUID = 1L;
// 手动设置序列化版本——解决版本冲突问题
	
	private int id;
	private String name;
	private int age;
	private String address;
	public User() {
		super();
	}
	public User(int id, String name) {
		super();
		this.id = id;
		this.name = name;
	}
	
	public User(int id, String name, int age) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
	}
	
	public User(int id, String name, int age, String address) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
		this.address = address;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public static long getSerialversionuid() {
		return serialVersionUID;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", age=" + age + ", address=" + address + "]";
	}
}
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("objs.txt"));
Student stu = new Student(1,"zhangsan",20);
oos.writeObject(stu);
stu.setName("李四");  
oos.writeObject(stu);   // 和第1次写的是同一个对象,第2次序列化时并不会有两个对象被序列化。第2次只是输出一个序列号编号
oos.close();

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("objs.txt"));
Student stu1 = (Student)ois.readObject();
System.out.println(stu1);
		
Student stu2 = (Student)ois.readObject();
System.out.println(stu2);
		
Student stu3 = (Student)ois.readObject();
System.out.println(stu3);  // 只存了两次,第3次读取时报错
		
ois.close();
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值