描述

最近遇到问题需要将较大的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. Jmeter--HTTPS请求

    (1)新建threadGroup:                               (2)设置并发用户数量:                                     (3) ...

  2. 【转载】python发送邮件实例

    本文转自:http://www.cnblogs.com/lonelycatcher/archive/2012/02/09/2343463.html 这几天要用python发送邮件,上网找到这篇文章感觉 ...

  3. java8的新特性,Collections.sort(排序的List集合)的使用,对list封装Map里面的某个值进行排序

    --------------------------对简单list的排序---------------------------------- List<Integer> list = ne ...

  4. js函数和window对象

  5. PHP 通过命令异步执行PHP程序

    通过PHP执行系统命令调用PHP执行程序,让进程挂起到后台执行,不影响用户页面交互. 控制器调用命令,不用等待,后台创建一个进程执行程序. system(“nohup php command.php ...

  6. excel 开头 结尾,中间 类似 SQL like ab% ,%ab ,%ab%

    excel  开头 结尾,中间  类似 SQL like 'ab%'  ,'%ab'  ,'%ab%' 在R2 单元格  查找   ab开头,ab结尾 =Search("ab",R ...

  7. sample采样倾斜key并单独进行join代码

    /** * sample采样倾斜key单独进行join */ JavaPairRDD<Long, String> sampledRDD = userid2PartAggrInfoRDD.s ...

  8. vmware 虚拟机设置 redhat 桥接模式

    1.设置 vmware 网络模式 2.设置 linux 网络模式

  9. ES基础知识与高频考点梳理

    知识点梳理目录列表 变量类型 JS的数据类型分类和判断 值类型和引用类型 原型与原型链(继承) 原型和原型链的定义 继承写法 作用域和闭包 执行上下文 this 闭包是什么 异步 同步VS异步 异步和 ...

  10. python学习——单例模式

    在python中,单例模式在面试中非常重要.下面来给大家推荐一个Python中实现单例模式的博客地址. https://www.cnblogs.com/huchong/p/8244279.html