zoukankan      html  css  js  c++  java
  • bson文件的切分

    描述

    最近遇到问题需要将较大的bson文件(MongoDB导出的二进制json文件)按文档(记录)进行切分,网上这方面的资料实在太少,弄了一天多终于达到了基本要求(还不知道有没有BUG)

    代码

    package splitbson;
    
    import java.io.*;
    import java.util.Scanner;
    
    /**
     * 每条文档的前四个字节表示该文档的字节数,因此只需要读取4个字节数,计算该文档大小。然后用字节流读取即可。
     */
    public class SplitBsonUtils {
        // 输入流
        private static BufferedInputStream bis;
        // 输出结果文件的命名编号
        private static int fileNameCount = 1;
        // 带缓冲区的输出流
        private static BufferedOutputStream bos;
        // 记录当前文件已写文档(记录)数
        private static int documentCount = 0;
    
        /**
         * 切分bson文件
         *
         * @param sourceFilePath  源bson文件
         * @param fileDocumentNum 每个文件的文档数
         * @param targetFilePath  目标文件目录
         */
        public static void splitBson(String sourceFilePath, int fileDocumentNum, String targetFilePath) {
            if (fileDocumentNum < 0) fileDocumentNum = 100;
            try {
                // 构建输入流
                bis = new BufferedInputStream(new FileInputStream(sourceFilePath));
                File dir = new File(targetFilePath);
                if (!dir.exists()) {
                    dir.mkdir();
                }
                // 构建可缓冲的输出流
                bos = new BufferedOutputStream(new FileOutputStream(targetFilePath + "/file" + fileNameCount++ + ".bson", true));
                // 获取下一条记录的字节数
                int documentSize = getSize(sourceFilePath);
                // 减4是因为getSize方法已经读写了四个字节
                byte[] arr = new byte[documentSize - 4];
                // 开始读源bson文件
                while (bis.read(arr) != -1) {
                    // 写入到新的文件
                    bos.write(arr);
                    documentCount++;
                    // 判断当前文件记录数是否达到自定义文档数
                    if (documentCount == fileDocumentNum) {
                        // 创建新的输出流
                        bos = new BufferedOutputStream(new FileOutputStream(targetFilePath + "/file" + fileNameCount++ + ".bson", true));
                        documentCount = 0;
                    }
                    documentSize = getSize(sourceFilePath);
                    // 表示已经到了文件结尾
                    if (documentSize == -1) break;
                    arr = new byte[documentSize - 4];
                }
                bos.flush();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    bis.close();
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 获取源bson文件正被读取文档的字节数
         *
         * @param filePath
         * @return
         */
        public static int getSize(String filePath) {
            byte[] arr = new byte[4];
            int size = 0;
            try {
                bis.read(arr);
                size = byte2DecStr(arr);
                if (size - 4 < 0) return -1;
                bos.write(arr);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return size;
        }
    
        /**
         * byte数组转换成十进制字符串
         *
         * @param b
         * @return
         */
        public static int byte2DecStr(byte[] b) {
            String stmp = "";
            StringBuilder sb = new StringBuilder("");
            for (int n = b.length - 1; n >= 0; n--) {
                stmp = Integer.toHexString(b[n] & 0xFF);
                sb.append((stmp.length() == 1) ? "0" + stmp : stmp);
            }
            return Integer.parseInt(sb.toString(), 16);
        }
    
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            System.out.println("请传入三个参数进行bson文件的切分:");
            System.out.println("1. 原bson文件绝对路径(无需引号),如:E:/ld_FamilySearch_detail.bson");
            String sourceFilePath = scanner.nextLine();
            System.out.println("2. 切分后每个文件所要存储的文档(记录)条数,如:100");
            int fileDocumentNum = scanner.nextInt();
            scanner.nextLine();
            System.out.println("3. 切分后文件存储的目录(无需引号),如:E:/result");
            String targetFilePath = scanner.nextLine();
            System.out.println(sourceFilePath + fileDocumentNum + targetFilePath);
            System.out.println("正在进行切分...");
            long start = System.currentTimeMillis();
            splitBson(sourceFilePath, fileDocumentNum, targetFilePath);
            long end = System.currentTimeMillis();
            System.out.println("切分完成!共耗时:" + (end - start) + "毫秒");
        }
    }
    
    
  • 相关阅读:
    Fix Installing .NET Framework 3.5 failed Error Code 0x800F0954 on Windows 10
    RHEL8安装五笔输入法
    Enable EPEL and Local Repository on RHEL8
    Why is Yum Replaced by DNF?
    检查Linux服务器是否被攻击的常用命令及方法
    IDEA 主题
    IDEA 如何显示一个类中所有的方法
    Appium 安装以及安装过程中遇到的问题
    Maven 如何发布 jar 包到 Nexus 私库
    java泛型的基本使用
  • 原文地址:https://www.cnblogs.com/zyoung/p/7803347.html
Copyright © 2011-2022 走看看