Java核心技术:随机访问文件

import java.io.*;
import java.time.LocalDate;
import java.util.Scanner;

public class Test {
    public static void main(String[] args){
//        TextFileTest.test();
        RandomAccessTest.test();
    }
}

class Employee {
    private String name;
    private double salary;
    private LocalDate hireDay;
    public static final int NAME_SIZE = 30;
    public static final int RECORD_SIZE = 50;

    public Employee(String name, double salary, LocalDate hireDay) {
        this.name = name;
        this.salary = salary;
        this.hireDay = hireDay;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public LocalDate getHireDay() {
        return hireDay;
    }

    public void setHireDay(LocalDate hireDay) {
        this.hireDay = hireDay;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name=‘" + name + ‘\‘‘ +
                ", salary=" + salary +
                ", hireDay=" + hireDay +
                ‘}‘;
    }
}

class TextFileTest {

    public static void test() {
        Employee[] staff = new Employee[]{
                new Employee("A", 10, LocalDate.now()),
                new Employee("B", 20, LocalDate.now()),
                new Employee("C", 30, LocalDate.now())
        };

        try(PrintWriter out = new PrintWriter("employee.dat","UTF-8")) {

            writeData(staff,out);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        try (Scanner in = new Scanner(new FileInputStream("employee.dat"))) {

            Employee[] newStaff = readData(in);

            for (Employee e : newStaff) {
                System.out.println(e);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

    }

    private static void writeData(Employee[] employees, PrintWriter out) {
        out.println(employees.length);
        for (Employee e : employees) {
            writeEmployee(out,e);
        }
    }

    private static void writeEmployee(PrintWriter out, Employee employee) {
        out.println(employee.getName()+"|"+employee.getSalary()+"|"+ employee.getHireDay());
    }

    private static Employee[] readData(Scanner in) {
        int n = in.nextInt();
        in.nextLine();

        Employee[] employees = new Employee[n];
        for (int i = 0; i < n; i++) {
            employees[i] = readEmployee(in);
        }
        return employees;
    }

    private static Employee readEmployee(Scanner in) {
        String line = in.nextLine();
        String[] tokens = line.split("\\|");

        String name = tokens[0];
        double salary = Double.parseDouble(tokens[1]);
        LocalDate hire = LocalDate.parse(tokens[2]);

        return new Employee(name, salary, hire);
    }
}

/*
    写了大半天,突然发现这个实验好像不是太严谨:
        1.RandomAccessFile算长度时,应该是根据字节数算出来的
        2.写字符串时,我们只是指定了码元数量,我们写的是固定码元数量的字符串
        3.这样的化,我们记录的Employee.RECORD_SIZE根本就代表不了一条记录的长度
        4.但是我们最后又通过RandomAccessFile的长度和Employee.RECORD_SIZE来计算记录数量
        5.我觉得这个实验有问题,以后研究吧
 */

class DataIO {
    //Java核心技术 卷二 第十版 2.3.2节
    //写出从字符串开头开始的指定数量的码元,如果码元过少,该方法会用‘0’来补齐字符串
    public static void writeFixedString(String s, int size, DataOutput output) throws IOException {
        for (int i = 0; i < size; i++) {
            char ch =0;
            if(i<s.length())
                ch = s.charAt(i);
            output.write(ch);
        }
    }

    //Java核心技术 卷二 第十版 2.3.2节
    //从输入流中读入字符,直至读入size个码元,或者直至遇到具有0值的字符串,然后跳出输入字段中剩余的0值。
    public static String readFixedString1(int size, DataInput in) throws IOException {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < size; i++) {
            char c;
            if ((c = in.readChar()) != 0) {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    //功能和上一个方法是一样的,但是这个效率会高那么一点点
    public static String readFixedString2(int size, DataInput in) throws IOException {
        StringBuilder sb = new StringBuilder();
        /*
        int i;
        for (i = 0; i < size; i++) {
            char c;
            if ((c = in.readChar()) == 0) {
                break;
            }
            sb.append(c);
        }
        in.skipBytes(2*(size-i));   //这个地方不是太严谨
        */

        //用书中代码测试一下
        int i =0;
        boolean more = true;
        while (more && i < size) {
            char ch = in.readChar();
            i++;
            if (ch == 0) {
                more = false;
            } else {
                sb.append(ch);
            }
        }
        in.skipBytes(2 * (size - i));

        return sb.toString();
    }
}

class RandomAccessTest {
    public static void test() {
        Employee[] staff = new Employee[]{
                new Employee("A", 10, LocalDate.now()),
                new Employee("B", 20, LocalDate.now()),
                new Employee("C", 30, LocalDate.now())
        };

        //写入
        try(DataOutputStream out = new DataOutputStream(new FileOutputStream("employee1.dat"))) {

            for (Employee e : staff) {
                writeData(out, e);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //读取

        try(RandomAccessFile in = new RandomAccessFile("employee1.dat","r")) {
            int n = (int) (in.length() / Employee.RECORD_SIZE);
            Employee[] newStaff = new Employee[n];

            for (int i = n - 1; i >= 0; i--) {
                in.seek(i*Employee.RECORD_SIZE);
                newStaff[i] = readDate(in);
            }

            for (Employee e : newStaff) {
                System.out.println(e);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private static void writeData(DataOutput out, Employee employee) throws IOException {
        DataIO.writeFixedString(employee.getName(), Employee.NAME_SIZE, out);
        out.writeDouble(employee.getSalary());

        LocalDate hireDay = employee.getHireDay();
        out.writeInt(hireDay.getYear());
        out.writeInt(hireDay.getMonthValue());
        out.writeInt(hireDay.getDayOfMonth());
    }

    private static Employee readDate(DataInput input) throws IOException {
        String name = DataIO.readFixedString2(Employee.NAME_SIZE, input);
        double salary = input.readDouble();
        int
                y= input.readInt(),
                m= input.readInt(),
                d= input.readInt();
        return new Employee(name, salary, LocalDate.of(y, m, d));
    }
}

原文地址:https://www.cnblogs.com/junjie2019/p/10543843.html

时间: 2024-08-02 11:55:28

Java核心技术:随机访问文件的相关文章

Java I/O---RandomAccessFile类(随机访问文件的读取和写入)

1.JDK API中RandomAccessFile类的描述 此类的实例支持对随机访问文件的读取和写入.随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组.存在指向该隐含数组的光标或索引,称为文件指针:输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针.如果随机访问文件以读取/写入模式创建,则输出操作也可用:输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针.写入隐含数组的当前末尾之后的输出操作导致该数组扩展.该文件指针(实现数组随机读写)可以通过

随机访问文件RandomAccessFile 与 内存映射文件MappedByteBuffer

一.RandomAccessFile RandomAccessFile是用来访问那些保存数据记录的文件的,你就可以用seek( )方法来访问记录,并进行读写了.这些记录的大小不必相同:但是其大小和位置必须是可知的.但是该类仅限于操作文件. RandomAccessFile不属于InputStream和OutputStream类系的.实际上,除了实现DataInput和DataOutput接口之外(DataInputStream和DataOutputStream也实现了这两个接口),它和这两个类系

《七》随机访问文件流

1.什么是 随机访问文件流 RandomAccessFile? 该类的实例支持读取和写入随机访问文件. 随机访问文件的行为类似于存储在文件系统中的大量字节. 有一种游标,或索引到隐含的数组,称为文件指针 ; 输入操作读取从文件指针开始的字节,并使文件指针超过读取的字节. 如果在读/写模式下创建随机访问文件,则输出操作也可用; 输出操作从文件指针开始写入字节,并将文件指针提前到写入的字节. 写入隐式数组的当前端的输出操作会导致扩展数组. 文件指针可以通过读取getFilePointer方法和由设置

Java基础知识强化之IO流笔记63:随机访问流RandomAccessFile

1. 随机访问流RandomAccessFile RandomAccessFile类不属于流,是Object类的子类.但它融合了InputStream和OutputStream的功能.支持对随机访问文件的读取和写入. RandomAccessFile的构造方法: 构造方法摘要 RandomAccessFile(File file, String mode)           创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定. RandomAccessFile(St

Java API —— IO流(数据操作流 &amp; 内存操作流 &amp; 打印流 &amp; 标准输入输出流 &amp; 随机访问流 &amp; 合并流 &amp; 序列化流 &amp; Properties &amp; NIO)

1.操作基本数据类型的流 1) 操作基本数据类型 · DataInputStream:数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型.应用程序可以使用数据输出流写入稍后由数据输入流读取的数据. · DataOutputStream:数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中.然后,应用程序可以使用数据输入流将数据读入. package datastreamdemos; import java.io.*; /** * Created b

《Java核心技术卷二》笔记(一)流与文件

一.流的概念 在Java中,可以提供字节序列的对象,或者可以接收字节序列的对象,都可以抽象成流.系统中的文件,网络,内存这些设备都可以读入或者写入字节,自然也可以用流的方式来操作.能向程序中提供字节序列,即可以从其中读入字节序列,这样的对象显然就是输入流.相反的,能够接收程序送来的字节序列,也就是可以向其中写入字节序列,就是输出流. Java提供丰富的流类家族,实现了各种常用的输入输出操作功能,如文件.内存读写等.InputStream和OutputStream类分别是字节输入/输出流继承体系的

Java核心类库-IO-随机访问文件(RandomAccessFile)

随机访问文件:表示可以在该文件任何位置读取数据. public class RandomAccessFileDemo { public static void main(String[] args) throws Exception { File f = new File("raf.txt"); //write(f); read(f); } private static void read(File f) throws Exception { //r表示只读 RandomAccessF

《Java核心技术 卷II 高级特性 原书第10版》高清pdf

<Java核心技术 卷II 高级特性 原书第10版> 本书是Java领域有影响力和价值的著作之一,由拥有20多年教学与研究经验的Java技术专家撰写(获Jolt大奖),与<Java编程思想>齐名,10余年全球畅销不衰,广受好评.第10版根据JavaSE8全面更新,同时修正了第9版中的不足,系统全面讲解了Java语言的核心概念.语法.重要特性和开发方法,包含大量案例,实践性强. ? 百度网盘链接: https://pan.baidu.com/s/1aZ9KUgxwHNQJMH6X7h

Java:IO流与文件基础

Java:IO流与文件基础 说明: 本文所有内容包含图片均为MrSaber自己编写,转载请练习我哦. 本章内容将会持续更新,大家可以关注一下并给我提供建议,谢谢啦. 走进流 什么是流 流:从源到目的地的字节的有序序列. 在Java中,可以从其中读取一个字节序列的对象称作 输入流,可以向其中写入一个字节序列的对象称作 输出流. ? 这些字节序列的来源可以是:文件.网络连接.内存块等. ? 抽象类InputStream和OutputStream是构成输入/输出(I/O)的基础. ? 因为面向字节的流