HBase读写tif文件/其他格式文件

目录

1 导入包

2 写入到hbase中的函数

3 从hbase到本地

4 main函数

5 完整代码

6 java批量写入

7 spark批量写入到hbase

 

 


写入的基本思路是将文件读取为字节型数组,再插入hbase。

使用java实现将本地图片写入到hbase中,从hbase中读取并写入到本地。以tif格式为例。

写到hbase中再写到本地得到的图和原始图是一致的,也含有地理信息。

此方法不仅可以用于图片文件,对于word pdf 等其他文件也同样可以存入hbase并写出到本地。

一个是java实现,一个是用spark/scala实现

由于本人java水平有限,采用java写for循环逐个插入的效率较低,用spark插入的速度较快。

1 导入包

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.File;

2 写入到hbase中的函数

public static void WriteTif2Hbase(String imgPath,String tableName,String rowKey,String cf,String column) throws IOException{
        //写入
        Configuration configuration = HBaseConfiguration.create();

        HTable table = new HTable(configuration, tableName);

        FileInputStream fis = new FileInputStream(imgPath);
        byte[] bbb = new byte[fis.available()];//读图为流,但字节数组还是空的
        fis.read(bbb);//将文件内容写入字节数组
        fis.close();

        // 002是行键
        Put put = new Put(rowKey.getBytes());
        // cf1是列族,img是列,bbb是插入的值(图片转化成的字节数组)
        put.add(cf.getBytes(), column.getBytes(), bbb);
        table.put(put);
        table.close();
        System.out.println("Write Success");
    }

3 从hbase到本地

    public static void ReadHbase2Local(String outPath,String tableName,String rowKey) throws IOException{
        Configuration configuration = HBaseConfiguration.create();

        HTable table = new HTable(configuration, tableName);

        //读取
        //将hbase获取的二进制流转化成文件夹中的图片

        Get get = new Get(rowKey.getBytes());
        Result rs = table.get(get);
        byte[] bs = rs.value(); //保存get result的结果,字节数组形式
        table.close();
        File file=new File(outPath);//将输出的二进制流转化后的图片的路径
        FileOutputStream fos=new FileOutputStream(file);
        fos.write(bs);
        fos.close();
        System.out.println("Write success");
    }

4 main函数

    public static void main(String[] args) throws IOException{
        //创建表  create 'test','cf1';
        String imgPath="E:\\data\\ser\\20190928T022549_20190928T022549_T51TYJ_S_ABAU.tif";
        String tableName="test";
        String rowKey="002";
        String cf="cf1";
        String column="img";
        WriteTif2Hbase(imgPath,tableName,rowKey,cf,column);

        String outPath="E:\\data\\ser\\test1.tif";
        ReadHbase2Local(outPath,tableName,rowKey);


    }

5 完整代码

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.File;
public class ReadHbase {
    public static void main(String[] args) throws IOException{
        //创建表  create 'test','cf1';
        String imgPath="E:\\data\\ser\\20190928T022549_20190928T022549_T51TYJ_S_ABAU.tif";
        String tableName="test";
        String rowKey="002";
        String cf="cf1";
        String column="img";
        WriteTif2Hbase(imgPath,tableName,rowKey,cf,column);

        String outPath="E:\\data\\ser\\test1.tif";
        ReadHbase2Local(outPath,tableName,rowKey);


    }
    public static void WriteTif2Hbase(String imgPath,String tableName,String rowKey,String cf,String column) throws IOException{
        //写入
        Configuration configuration = HBaseConfiguration.create();

        HTable table = new HTable(configuration, tableName);

        FileInputStream fis = new FileInputStream(imgPath);
        byte[] bbb = new byte[fis.available()];//读图为流,但字节数组还是空的
        fis.read(bbb);//将文件内容写入字节数组
        fis.close();

        // 002是行键
        Put put = new Put(rowKey.getBytes());
        // cf1是列族,img是列,bbb是插入的值(图片转化成的字节数组)
        put.add(cf.getBytes(), column.getBytes(), bbb);
        table.put(put);
        table.close();
        System.out.println("Write Success");
    }
    public static void ReadHbase2Local(String outPath,String tableName,String rowKey) throws IOException{
        Configuration configuration = HBaseConfiguration.create();

        HTable table = new HTable(configuration, tableName);

        //读取
        //将hbase获取的二进制流转化成文件夹中的图片

        Get get = new Get(rowKey.getBytes());
        Result rs = table.get(get);
        //指定列族和列
        //byte[] bs=result.getValue(Bytes.toBytes("cf1"),Bytes.toBytes("001001"));
        //获取
        byte[] bs = rs.value(); //保存get result的结果,字节数组形式
        table.close();
        File file=new File(outPath);//将输出的二进制流转化后的图片的路径
        FileOutputStream fos=new FileOutputStream(file);
        fos.write(bs);
        fos.close();
        System.out.println("Write success");
    }
}

6 java批量写入

对一个文件夹下的所有tif写入到hbase,列族需存在

只用了简单的for循环逐个插入,效率比较低。

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.File;
import java.text.SimpleDateFormat;

public class ReadHbase5 {
    public static void main(String[] args) throws IOException{
        //创建表  create 'test','cf';
        //列出所有行键:count 'test', INTERVAL=>1
        //删除表 disable 'test'   ; drop 'test'
        //增加列族 alter 'test', {NAME=>'cf2'}
        String tableName="test";
        //String rowKey="002";
        String cf="cf2";
        String column="img";
        File file=new File("E:\\data\\ser\\sample");
        File[] tempList = file.listFiles();

        //对所有的tif文件写入
        for (int i = 0; i < tempList.length; i++) {
            if (tempList[i].isFile() && (tempList[i].toString().endsWith(".tif"))) {
                //绝对路径
                String imgPath=tempList[i].toString();
                //文件名作为rowkey
                String rowKey=tempList[i].getName();
                //写入
                WriteTif2Hbase(imgPath,tableName,rowKey,cf,column);
                //时间获取
                SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String strsystime = sf.format(System.currentTimeMillis());//系统当前时间
                System.out.println("Success: "+strsystime+": "+rowKey);

            }
        }
        System.out.println("Success All ");

        //String imgPath="E:\\data\\ser\\20190928T022549_20190928T022549_T51TYJ_S_ABAU.tif";
        //WriteTif2Hbase(imgPath,tableName,rowKey,cf,column);

        //String outPath="E:\\data\\ser\\test1.tif";
        //ReadHbase2Local(outPath,tableName,rowKey);


    }
    public static void WriteTif2Hbase(String imgPath,String tableName,String rowKey,String cf,String column) throws IOException{
        //写入
        Configuration configuration = HBaseConfiguration.create();

        HTable table = new HTable(configuration, tableName);

        FileInputStream fis = new FileInputStream(imgPath);
        byte[] bbb = new byte[fis.available()];//读图为流,但字节数组还是空的
        fis.read(bbb);//将文件内容写入字节数组
        fis.close();

        // 002是行键
        Put put = new Put(rowKey.getBytes());
        // cf1是列族,img是列,bbb是插入的值(图片转化成的字节数组)
        put.add(cf.getBytes(), column.getBytes(), bbb);
        table.put(put);
        table.close();
        System.out.println("Write Success");
    }
    public static void ReadHbase2Local(String outPath, String tableName,  String rowKey) throws IOException{
        Configuration configuration = HBaseConfiguration.create();

        HTable table = new HTable(configuration, tableName);

        //读取
        //将hbase获取的二进制流转化成文件夹中的图片

        Get get = new Get(rowKey.getBytes());
        Result rs = table.get(get);
        byte[] bs = rs.value(); //保存get result的结果,字节数组形式
        table.close();
        File file=new File(outPath);//将输出的二进制流转化后的图片的路径
        FileOutputStream fos=new FileOutputStream(file);
        fos.write(bs);
        fos.close();
        System.out.println("Write success");
    }
}

对于2M大的图 大约2秒插入一个

220个文件前后用时四分钟。

 

Write Success
Success: 2019-10-26 21:19:58: 20190928T022549_20190928T022549_T51TYJ_S_AAAA.tif
Write Success
Success: 2019-10-26 21:20:00: 20190928T022549_20190928T022549_T51TYJ_S_AAAB.tif
Write Success
Success: 2019-10-26 21:20:03: 20190928T022549_20190928T022549_T51TYJ_S_AAAC.tif
Write Success
Success: 2019-10-26 21:20:03: 20190928T022549_20190928T022549_T51TYJ_S_AAAD.tif
Write Success
Success: 2019-10-26 21:20:03: 20190928T022549_20190928T022549_T51TYJ_S_AAAE.tif
Write Success
。。。。。。。。。。。。。。
Success: 2019-10-26 21:22:50: 20190928T022549_20190928T022549_T51TYJ_S_AHAQ.tif
Write Success
Success: 2019-10-26 21:22:53: 20190928T022549_20190928T022549_T51TYJ_S_AHAR.tif
Write Success
。。。。。。。。。。。。。。
Success: 2019-10-26 21:23:51: 20190928T022549_20190928T022549_T51TYJ_S_AQAL.tif
Write Success
Success: 2019-10-26 21:23:51: 20190928T022549_20190928T022549_T51TYJ_S_AQAM.tif
Write Success
Success: 2019-10-26 21:23:51: 20190928T022549_20190928T022549_T51TYJ_S_AQAN.tif
Write Success
Success: 2019-10-26 21:23:53: 20190928T022549_20190928T022549_T51TYJ_S_AQAO.tif
Success All 

Process finished with exit code 0

7 spark批量写入到hbase

对一个文件夹内的所有文件存入到hbase中,行键为文件名,列族:列为cf1:img

主要用到了sc.binaryFiles这个函数,将文件夹下的文件以二进制方式读取,一个文件对应rdd的一个元素。

rdd的每个元素为键值对rdd,类型为(String,org.apache.spark.input.PortableDataStream),其中第一个x._1为文件的路径,第二个 x._2 为PortableDataStream对象,可以通过toArray()方法转换为字节型数组。

字符串转为字节数组下面的两种方法是一样的,但是b2的方法更加通用,对于整数小数的也能使用
 

val b1= "字符串".getBytes

 val b2=Bytes.toBytes("字符串")

b1.mkString == b2.mkString          //res10: Boolean = true

ReadHbase4.scala

import org.apache.hadoop.hbase.{HBaseConfiguration, HTableDescriptor, TableName}
import org.apache.hadoop.hbase.client.{HBaseAdmin, Put, Result}
import org.apache.hadoop.hbase.io.ImmutableBytesWritable
import org.apache.hadoop.hbase.mapreduce.TableInputFormat
import org.apache.spark.{SparkConf, SparkContext}
//import org.apache.hadoop.hbase.mapreduce.TableOutputFormat
import org.apache.hadoop.hbase.mapred.TableOutputFormat
import org.apache.hadoop.hbase.util.Bytes
import org.apache.hadoop.mapred.JobConf
import java.text.SimpleDateFormat
object ReadHbase4{
  def main(args: Array[String]) {
    val conf=new SparkConf().setMaster("local[2]").setAppName("testhbase")
    conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
    val sc=new SparkContext(conf)
//hbase表名
    val tablename = "test"

    val hbaseConf = HBaseConfiguration.create()
    //在Windows系统的本地模式下下面两行不需要也能运行,如果在集群模式下就得需要了
    //设置zooKeeper集群地址,也可以通过将hbase-site.xml导入classpath,但是建议在程序里这样设置
    // hbaseConf.set("hbase.zookeeper.quorum","localhost")
    //设置zookeeper连接端口,默认2181
    //hbaseConf.set("hbase.zookeeper.property.clientPort", "2181")
    hbaseConf.set(TableOutputFormat.OUTPUT_TABLE, tablename)

    // 初始化job,TableOutputFormat 是 org.apache.hadoop.hbase.mapred 包下的
    val jobConf = new JobConf(hbaseConf)
    jobConf.setOutputFormat(classOf[TableOutputFormat])

    //使用sc.binaryFiles将目录下的所有文件读取为二进制数组,也可以加个filter过滤指定后缀的
    val rdd2=sc.binaryFiles("E:\\data\\ser\\sample")

    val rdd3=rdd2.filter(_._1.endsWith(".tif")).map{x=>{        //x._1为文件的路径,x._2 为org.apache.spark.input.PortableDataStream
      val rowkey=x._1.split('/').last      //将路径的文件名提取出来作为行键
      val put = new Put(Bytes.toBytes(rowkey))     //用行键创建一个Put
      put.addColumn(Bytes.toBytes("cf1"),Bytes.toBytes("img"),x._2.toArray()) //指定列族,列和写入的数据
        // println(x._2.toArray().length)
      val sf:SimpleDateFormat =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      val strsystime:String = sf.format(System.currentTimeMillis());//系统当前时间

      println(s"$strsystime : $rowkey : success")
      (new ImmutableBytesWritable, put)
    }}
    rdd3.saveAsHadoopDataset(jobConf)

  }
}

输出信息

对于220个2M大小的文件,可以看到前三个比较慢一点,后面的210+个用时四秒写入成功。

可以看到比第六节的快不少,用java方式的比较原始,还是用spark快一些。

 

 

 

参考

https://blog.csdn.net/login_sonata/article/details/53440059

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

独孤尚亮dugushangliang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值