在hive udf中加载外部数据到内存中

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.fs.FileSystem;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 在udf中加载外部数据到内存中。
 */
public class UdfDriverExternalDataDemo extends UDF {
    
    
    List<String> list = new ArrayList<>();
    int driverDataOff = 0;

    /**
     * 因为这是要注册的udf,直接在hive中运行。
     * 所以下面的路径:/udf/hive/aaa.dat 就是hvie所在hdfs路径。
     * 在这里也可以加载本地的文件:
     *     private void driverData(String path) {
     *         try {
     *             BufferedReader bf = new BufferedReader(new FileReader(path));
     *             String line = "";
     *             while ((line = bf.readLine()) != null) {
     *                 list.add(line);
     *             }
     *         } catch (IOException e) {
     *             e.printStackTrace();
     *         }
     *     }
     */
    private void driverData() {
    
    
        FSDataInputStream fsDataInputStream = null;
        InputStream in = null;
        ByteArrayOutputStream stream = null;
        try {
    
    
            Configuration conf = new Configuration();
            FileSystem fileSystem = FileSystem.get(conf);
            Path path = new Path("/udf/hive/aaa.dat");
            fsDataInputStream = fileSystem.open(path);
            in = fsDataInputStream.getWrappedStream();

            int count = 0;
            // 有可能会因为某些原因返回大小延迟,所以用while循环等待。
            while (count == 0) {
    
    
                count = in.available();
            }

            // b 作为缓冲区,即便给的 count 参数很大,在下面的 stream.write() 每次也最多能存。。。(忘了,想知道可以试一下)
            byte[] b = new byte[count];
            int len = -1;
            stream = new ByteArrayOutputStream();
            while ((len = in.read(b)) != -1) {
    
    
                stream.write(b, 0, len);
            }

            String[] strs = new String(stream.toByteArray()).split("\n");
            for (String s : strs) {
    
    
                String[] elements = s.split(",");
                for (String ele : elements) {
    
    
                    if (ele.trim().length() > 0) {
    
    
                        list.add(ele);
                    }
                }
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            try {
    
    
                if (in != null) {
    
    
                    in.close();
                }
                if (stream != null) {
    
    
                    stream.close();
                }
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
            if (fsDataInputStream != null) {
    
    
                IOUtils.closeStream(fsDataInputStream);
            }
        }
    }

    public String evaluate(String ip) {
    
    

        // 让加载数据的方法只运行一次
        if (driverDataOff == 0) {
    
    
            driverData();
            driverDataOff = 1;
        }

        // TODO 计算逻辑

        return "计算结果";
    }

}

猜你喜欢

转载自blog.csdn.net/weixin_44651989/article/details/108491321