描述

最近遇到问题需要将较大的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) + "毫秒");
}
}

bson文件的切分的更多相关文章

  1. 通过 bsondump 命令工具 解析备份产生的bson文件

    bsondump命令是将BSON格式的文件转换为可读性更强的文件格式,例如转为为JSON 格式的文档,bsondump默认转换为json格式的文档. 当通过mongodump命令进行备份时,如果有参数 ...

  2. Python将mongodb导出的bson文件转为字典对象

    Python将mongodb导出的bson文件转为字典对象 安装bson包, sudo pip install bson 示例 # 解决编码问题 import sys reload(sys) sys. ...

  3. MongoDB导入bson文件(元数据),mongorestore命令行方式导入

    MongoDB导入bson文件(元数据),mongorestore命令行方式导入 不推荐使用MongoDB Compass等图形化数据库管理软件,例如MongoDB Compass只能导入json和c ...

  4. MongoDB从bson文件中恢复数据

    首先需要到mangodb的安装目录的bin下面找到mongorestore.exe WIN10系统MongoDB安装目录bin文件夹下没有mongorestore.exe 先下载工具  https:/ ...

  5. 如何将mongodb bson文件转成json文件

    使用mongodb自带的命令 bsondump collection.bson > collection.json

  6. MongoDB导入文件夹(内含json和bson文件)

    1. 使用mongo命令将数据库删除: mongo命令: use db_name; db.dropDatabase() 2. 导入(指定文件夹)数据: linux命令: mongorestore -d ...

  7. hadoop拾遗(一)---- 避免切分map文件

    有些程序可能不希望文件被切分,而是用一个mapper完整处理每一个输入文件.例如,检查一个文件中所有记录是否有序,一个简单的方法是顺序扫描第一条记录并并比较后一条记录是否比前一条要小.如果将它实现为一 ...

  8. sql脚本长度限制及linux下文件切分

    无意翻出以前笔记,切分sql文件,每10万条加一个commit.半天都想不起来应用的场景,能想起来的再加上查的资料记录一下. 在Oracle数据库中,频繁的commit会引起大量Redo Log的物理 ...

  9. [Linux] 随机切分文件内容

    1.从原文件中随机选出若干行 可以直接用shuf命令就可以完成: $ shuf -n source.txt > target.txt shuf命令的说明: $ shuf --help Usage ...

随机推荐

  1. 如何遍历Map操作总结

    Map<Integer, String> map = new HashMap<Integer, String>(); map.put(1, "123"); ...

  2. NHibernate学习过程笔记

    NHbernate自动生成数据库的方法: using NHibernate; using NHibernate.Tool.hbm2ddl; namespace Test { public class ...

  3. EF Core如何输出日志到Visual Studio的输出窗口

    我们在使用EF Core的时候,很多时候需要在Visual Studio的输出窗口中知道EF Core在后台生成的SQL语句是什么,这个需求可以通过自定义EF Core的ILoggerFactory和 ...

  4. js判断值是不是全是数字

    if(isNaN(value)){ 不是数字 }else{ 全是数字 }

  5. NodeJs——入门

    关于NPM: npm 是 nodejs 的包管理和分发工具.它可以让 javascript 开发者能够更加轻松的共享代码和共用代码片段,并且通过 npm 管理你分享的代码也很方便快捷和简单. 一 No ...

  6. mysql 配置安装

    1.     下载: mysql-5.7.20是解压版免安装的,mysql-5.7.20下载地址:http://dev.mysql.com/downloads/mysql/ 直接下载,无需注册和登录. ...

  7. 05.odoo12开源框架学习

    博客为日常工作学习积累总结: 1.odoo12学习 参考博客:https://alanhou.org/centos-odoo-12/ CentOS 7快速安装配置 Odoo 12 添加新用户必做,不然 ...

  8. URL参数获取/转码

    JS中对URL进行转码与解码 1.escape 和 unescape escape()不能直接用于URL编码,它的真正作用是返回一个字符的Unicode编码值. 采用unicode字符集对指定的字符串 ...

  9. 在vue中如何实现购物车checkbox的三级联动

    最近用vue写一个电商项目,自然就少不了要写一个购物车的相关页面,功能完整的购物车的checkbox应该是三级联动的,1级checkbox是选中购物车中所有的商品,2级checkbox是选中某个店铺下 ...

  10. 使用百度编辑器--ueditor,后台接收提交编辑的内容,HTML不见了, 赋值不了,赋值之后,html暴露出来了??

    1.提交编辑好的内容, 后台post 接收发现 html 不见了,这个时候也许就是转义的问题, 既可以试试 $content = htmlspecialchars(stripslashes(input ...