欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java基础知识 27(随机访问文件流,序列化流和反序列化流,属性集合properties,SequenceInputStream,压缩流和解压流)

程序员文章站 2022-07-09 23:09:08
...

Java基础知识 27

随机访问文件流

RandomAccessFile概述:最大的特点:能读能写而且有一个文件指针,可以控制指针的位置。
此类的实例支持对于随机访问文件的读取和写入。
随机访问文件的行为类似存储在文件系统中的一个大型byte数组。
存在指向该隐含数组的光标或者索引,成为文件指针
输入操作从文件指针开始读取字节。
并随着对字节的读取而前移此文件指针
RandomAccessFile(String name,String mode)
创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称。
public class Mytest {
    public static void main(String[] args) throws IOException {
        //writeData();
        RandomAccessFile read = new RandomAccessFile("f.txt", "rw");
        //怎么写入的就怎么读取,顺序不能乱
        int i1 = read.readInt();
        System.out.println(i1);
        long filePointer = read.getFilePointer();
        System.out.println("文件指针的位置:"+filePointer);
        boolean b = read.readBoolean();
        System.out.println(b);
        long filePointer2 = read.getFilePointer();
        System.out.println("文件指针的位置:"+filePointer2);
        double v = read.readDouble();
        System.out.println(v);
        long filePointer3 = read.getFilePointer();
        System.out.println("文件指针的位置:"+filePointer3);
        String s1 = read.readUTF();
        System.out.println(s1);
        long filePointer4 = read.getFilePointer();
        System.out.println("文件指针的位置:"+filePointer4);
        //我们可以移动文件位置
        read.seek(0);
        int i = read.readInt();
        System.out.println(i);
        read.seek(13);//设置文件指针的位置
        String s = read.readUTF();
        System.out.println(s);
        read.close();
    }

    private static void writeData() throws IOException {
        RandomAccessFile write = new RandomAccessFile("f.txt", "rw");
        write.writeInt(1000);
        write.writeBoolean(true);
        write.writeDouble(3.14);
        //首先,把两个字节从文件的当前文件指针写入到此文件,类似于使用 writeShort 方法并给定要跟随的字节数。
        write.writeUTF("你好");
        write.close();
    }
}

序列化流和反序列化流

序列化和反序列化:这对流能够对Java中的对象进行操作
序列化:就是把Java对象通过流的方式存储到文件中
反序列化:就是把文件中存储的对象通过流的方式又还原成对象
序列化流:ObjectOutputStream
反序列化流:ObjectInputStream
注意:此对象要重写Serializable接口才能被序列化
public class Mytest2 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //写入
        Student student = new Student("杨超越", 22);
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("student1.txt"));
        out.writeObject(student);
        out.close();

        //读取
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("student1.txt"));
        Object obj = in.readObject();
        Student student1= (Student) obj;
        System.out.println(student1);
    }
}
--------------------------------
public class Student implements Serializable {
    //当你实现了Serializable接口后,再给他一个标记。
    private static final long serialVersionUID = -2209825693344822359L;
    /*
     *我们的一个类可以被序列化的前提就是需要这个类实现Serializable接口,就需要给这个类加上一个标记。
     * 在完成序列化以后,序列化文件还存在一个标记,然后在进行反序列化的时候
     * 会验证这个标记和序列化前的标记是否一样,如果一直就进行正常的反序列化。
     * 如果不一致,就报错。而现在我们把这个类做了修改,就相当于更改了标记,而导致这两个标记不一样,就报错。
     */
    private String name;
    //transient 不要序列化该字段,使用transient关键字声明不需要序列化的成员变量。
    //transient private int age;
    private int age;

    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    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;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

属性集合:properties

属性集合
Properties继承自Hashtable 是一个双列集合
我们经常使用这个集合来读取配置文件
Properties规定了键和值都是String类型
public class Mytest {
    public static void main(String[] args) {
        //属性集合
        //Properties继承自Hashtable 是一个双列集合
        //我们经常使用这个集合来读取配置文件
        //Properties规定了键和值都是String类型
        Properties properties = new Properties();
        /*properties.put("张三",23);
        properties.put("李四",24);
        String value = (String) properties.get("李四");
        System.out.println(value);*/
        //我们推荐使用它特有的方法来存储数据
        properties.setProperty("username","张三");
        properties.setProperty("password","123456");

        String username = properties.getProperty("username");
        String password = properties.getProperty("password");
        System.out.println(username);
        System.out.println(password);
        System.out.println("----------------------");
        //键没有找到值,返回null
        String user = properties.getProperty("user");
        System.out.println(user);
        System.out.println("----------------------");
        //参数2:是一个默认值,如果通过键没有找到这个对应的值,就返回这个默认值
        String property = properties.getProperty("name", "word");
        System.out.println(property);
    }
}

SequenceInputStream

SequenceInputStream表示其他输入流的逻辑串联,它从输入流的有序集合开始,
并从第一个输入流开始读取,直到到达文件末尾
接着从第二个输入流读取,以此类推,直到到达包含的最后一个输入流的文件末尾为止。
SequenceInputStream(InputStream s1,InputStream s2)
通过记住这两个参数来初始化新创建的SequenceInputStream
(将按照顺序读取这两个参数,先读取s1,后读取s2),以提供从此SequenceInputStream读取的字节
public class Mytest {
    public static void main(String[] args) throws IOException {
        //将a.txt文本文件和b.txt文本文件合并成一个c.txt文件

        FileInputStream in1 = new FileInputStream("user.properties");
        FileInputStream in2 = new FileInputStream("yonghu.properties");
        SequenceInputStream in = new SequenceInputStream(in1, in2);
        FileOutputStream out = new FileOutputStream("all.properties");
        int len=0;
        byte[] bytes = new byte[1024];
        while ((len=in.read(bytes,0,len))!=-1){
            out.write(bytes,0,len);
        }
        in.close();
        out.close();
    }
}

压缩流ZipOutputStream和解压流ZipInputStream

压缩流思路:
(1)需要压缩的文件A
(2)压缩后压缩包B存放位置,及名字
(3)用FileInputStream 接A
(4)用ZipOutputStream 接B
(5)ZipOutputStream.putNextEntry(new ZipEntry("newzipone.txt")) 对准一个压缩包中将要产生的 (压缩体 ZipEntry)
(6)while ((temp = input.read()) != -1) {   zipOut.write(temp);  }  //开始将文件压缩进对应的 (压缩体上面已经定好)
//压缩单个文件
public class IOTest {
	public static void main(String[] args) throws IOException {
		String path = "C:/Users/liuyan/Desktop/one.txt";
		String zippath = "C:/Users/liuyan/Desktop/"; //压缩文件保存路径
		File file = new File(path);
		File zipFile = new File(zippath + "one.zip"); //给压缩包起名
		InputStream input = new FileInputStream(file);
		ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
		zipOut.putNextEntry(new ZipEntry("newzipone.txt")); //给压缩内容文件起名(给one.txt起名)
		// 设置注释
		zipOut.setComment("i am ly");
		int temp = 0;
		while ((temp = input.read()) != -1) {
			zipOut.write(temp);
		}
		input.close();
		zipOut.close();
	}
}
解压流思路:
(1)需要压缩的文件夹 A ,里面有三个文件
(2)压缩后压缩包B存放位置,及名字
(3)用ZipOutputStream 接B
(4)File[] files = file.listFiles(); 得到文件夹下的文件
(5)通过循环进行第6,7,8步 ,将文件夹下文件一个个压缩进压缩包
(6)用FileInputStream 接files[i]
(7)ZipOutputStream.putNextEntry(new ZipEntry("newzipone.txt")) 对准一个压缩包中将要产生的 (压缩体 ZipEntry)
(8)while ((temp = input.read()) != -1) {   zipOut.write(temp);  }  //开始将文件压缩进对应的 (压缩体上面已经定好)
//一次性压缩多个文件
public class IOTest1 {
	public static void main(String[] args) throws IOException {
		// 要被压缩的文件夹,里面有三个文件
		String path = "C:/Users/liuyan/Desktop/test";
		String zippath = "C:/Users/liuyan/Desktop/"; //压缩文件保存路径
		File file = new File(path);
		File zipFile = new File(zippath + "newzip.zip"); //压缩包起名
		InputStream input = null;
		ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
		zipOut.setComment("hello"); //压缩包设置注释
		if (file.isDirectory()) {
			File[] files = file.listFiles(); //没有加过滤器,得到文件夹下所有文件
			for (int i = 0; i < files.length; ++i) { //通过循环将文件夹下文件一个个压缩进压缩包
				input = new FileInputStream(files[i]);
				//zipOut.putNextEntry(new ZipEntry(files[i].getName())); //压缩包里只有三个文件,没有test文件夹
				zipOut.putNextEntry(new ZipEntry(file.getName()+"/" + files[i].getName())); //有test文件
				int temp = 0;
				while ((temp = input.read()) != -1) {
					zipOut.write(temp);
				}
				input.close();
			}
		}
		zipOut.close();
	}
}