有规则存储数据

怎样实现快速定位数据—–让数据有规则的存储;
规定好每个数据存的字节数,这样去找时,只要能找到规律就可以不用将全部数据取出来遍历;

由于我们要规定好每个变量存储的字节数,所以不可以用oblectOutputStream,这个会一次性将对象存进去,但是无法做到精确规定,所以可以用DataOutputStream来存数据,做到把每一个变量所占的空间都精确规定;

写数据时会出现的问题:
写名称时,由于不确定到底名称会占几个字节,所以可以给20个字节的长度来存放;
但是DataOutputStream对于写字符串提供了writeUTF()的方法,可我们要写的是GBK,因为GBK规定了汉字占两个字节,这样比较有规律;所以我们使用write(byte[])将字符串转为byte[]即可;可是转成的byte[]不一定是20个字节,所以我们需要new一个20个字节的数组出来,并且将上个数组的数据拷贝到新数组中,可以使用jdk提供的数组拷贝方式:
System.arraycopy(bytes, 0, b, 0, bytes.length);
括号内第一个参数是被拷贝的原数组,第二个是从原数组下标第几个开始拷贝,第三个是需要拷贝到哪个数组,第四个是目标数组中放数据的起始位置,第五个是拷贝的长度;

存放数据代码如下:
public class SaveData {

public static void main(String[] args) throws Exception {

    Prodcut p0 = new Prodcut(0, "苹果", 10.5f);
    Prodcut p1 = new Prodcut(1, "泰国榴莲", 16.5f);
    Prodcut p2 = new Prodcut(2, "菠萝", 20.5f);
    Prodcut p3 = new Prodcut(3, "菠萝蜜", 30.5f);
    Prodcut p4 = new Prodcut(4, "香蕉", 19.5f);

    save(p0);
    save(p1);
    save(p2);
    save(p3);
    save(p4);

}

public static void save(Prodcut p) throws Exception {

    // 将数据按照既定的规则存入文件中
    // id占4个字节,name占20字节,price占4个字节
    DataOutputStream dout = new DataOutputStream(new FileOutputStream("d:/p.dat",true));

    dout.writeInt(p.getId()); //写入id

    byte[] bytes = p.getName().getBytes("GBK");
    byte[] b = new byte[20];
    // jdk提供的数组拷贝工具方法: 参数1:源数据数组  参数2:从源数组的第几个位置开始拷贝
    // 参数3 :目标数组   参数4:目标数组中放数据的起始位置  参数5:拷贝的长度
    System.arraycopy(bytes, 0, b, 0, bytes.length);
    dout.write(b);  // 将商品名写入文件,占20个字节

    dout.writeFloat(p.getPrice());  //将价格按照float数写入文件,占4个字节

    dout.close();

}

}

读取时的问题,由于用来20个字节存名字,会导致读取后有空格,用trim()去掉空格;
并且要快速定位就不能从头读起了,而是要从某个字节开始读,所以要用RandomAccessFile,
创建方式如下:RandomAccessFile raf = new RandomAccessFile(“d:/p.dat”, “r”);
括号里是文件路径和读取方式,“r”是只读的意思;然后用raf.seek(96)就是跳的96开始读;具体代码如下:
public static Product readDataById(String path,int id) throws Exception{
RandomAccessFile raf = new RandomAccessFile(path, “r”);
//指定查找位置
long pos=id*28;

    File file = new File(path);
    long length = file.length();


    if(pos<length){
    raf.seek(pos);

    int pId = raf.readInt();

    // 再读20个字节
    byte[] b = new byte[20];
    int read = raf.read(b);
    // 然后将这20个字节转成字符串,但是尾部有大量空格
    String string = new String(b);
    // 去掉首尾的空格
    String name = string.trim(); 

    // 再读价格
    float price = raf.readFloat();

    raf.close();


    Product prodcut = new Product(pId, name, price);
    return prodcut;
    }else {
        return null;
    }
}
public static ArrayList<Product> readDataByName(String path,String name) throws Exception{
    RandomAccessFile raf = new RandomAccessFile(path, "r");

    //创建一个list;
    ArrayList<Product> proList = new ArrayList<>();
    File file = new File(path);
    long length = file.length();
    byte[] b = new byte[20];
    //指定查找位置
    for(int i=0;i<length/28;i++){
        raf.seek(4+28*i);
        raf.read(b);
        String str = new String(b);
        if(str.contains(name)){
            String proName = str.trim();
            // 再读价格
            float proPrice = raf.readFloat();
            int proId = i;
            Product pro = new Product(proId, proName, proPrice);
            proList.add(pro);
        }
    }
        return proList;
}
public static ArrayList<Product> readDataByPrice(String path,String price) throws Exception{
    RandomAccessFile raf = new RandomAccessFile(path, "r");

    //创建一个list;
    ArrayList<Product> proList = new ArrayList<>();
    //分割传进来的字符串
    String[] split = price.split("~");
    int minPrice =Integer.parseInt(split[0]);
    int maxPrice =Integer.parseInt(split[1]);
    //判断文件的长度
    File file = new File(path);
    long length = file.length();

    byte[] b = new byte[20];
    //指定查找位置
    for(int i=0;i<length/28;i++){
        raf.seek(24+28*i);
        float proPrice=raf.readFloat();
        if(proPrice>=minPrice&&proPrice<=maxPrice){
            // 再读价格
            int proId = i;
            raf.seek(4+28*i);
            int read = raf.read(b);
            // 然后将这20个字节转成字符串,但是尾部有大量空格
            String string = new String(b);
            // 去掉首尾的空格
            String proName = string.trim(); 
            Product pro = new Product(proId, proName, proPrice);
            proList.add(pro);
        }
    }
        return proList;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值