- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我对 XML 还很陌生,坏消息是我有以下结构的 XML:
<record>
<record_id>200</record_id>
<record_rows>
<record_row>some text</record_row>
.................................
</record_rows>
</record>
每条记录的记录行数不同,因此每条记录的大小也有很大不同。我的任务是将文件(超过 1GB)拆分为指定大小的单独 xml 文件。哪个解析器是最好的?另外,我想我应该采用一些记录选择策略来接近目标大小(考虑到输入文件大小和下一个记录大小的不可预测性,我当时无法想象任何策略)
我的 friend 们,唯一的希望就在你们身上。你会如何处理这个问题?
最佳答案
假设您的记录行不大于单个文件所需的大小,您可以使用 SAX 解析器顺序读取文件并计算读取的字符数,将迄今为止读取的数据存储在缓冲区中。当字符计数达到接近大小限制的值时,它将创建一个仅包含迄今为止读取的记录的新文件,重置缓冲区和字符计数,并将继续读取另一组,直到再次达到限制,并且很快。最后,您将拥有一组大小大致相同的文件(最后一个文件除外,它可能更小)并且包含相同的数据。
要使用 SAX 解析器,您需要一个包含以下代码的可执行文件:
import java.io.*;
import javax.xml.parsers.*;
import org.xml.sax.*;
public class SAXReader {
public static final String PATH = "src/main/resources";
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader reader = sp.getXMLReader();
reader.setContentHandler(new DataSaxHandler()); // need to implement this file
reader.parse(new InputSource(new FileInputStream(new File(PATH, "data.xml"))));
}
}
您的 XML 文件存储在 src/main/resources/data.xml
中(相对于您运行应用程序的位置)。您可能想改变这一点。
如果分割文件是格式良好的 XML,它们还应该有一个根元素,并且可能保留诸如 record_id
之类的信息,以便您可以知道它们来自哪个记录。我添加了一个属性 part
,其中包含对文件片段进行排序的序列号。生成的文件将如下所示:
data_part_1.xml
<record part='1'><record_id>200</record_id><record_rows><record_row>...</record_row><record_row>...</record_row> ... <record_row>...</record_row></record_rows></record>
data_part_2.xml
<record part='2'><record_id>200</record_id><record_rows><record_row>...</record_row><record_row>...</record_row> ... <record_row>...</record_row></record_rows></record>
...
data_part_n.xml
<record part='n'><record_id>200</record_id><record_rows><record_row>...</record_row><record_row>...</record_row><record_row>...</record_row><record_row>...</record_row></record_rows></record>
其中“n”是创建的文件数。
实现此结果的 SAX ContentHandler 实现如下所示。您可能想要更改 DIRECTORY
和 MAX_SIZE
常量:
import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
class DataSaxHandler extends DefaultHandler {
// Change this to the directory where the files will be stored
public static final String DIRECTORY = "target/results";
// Change this to the approximate size of the resulting files (in characters(
public static final long MAX_SIZE = 1024;
public static final long TAG_CHAR_SIZE = 5; //"<></>"
// counts number of files created
private int fileCount = 0;
// counts characters to decide where to split file
private long charCount = 0;
// data line buffer (is reset when the file is split)
private StringBuilder recordRowDataLines = new StringBuilder();
// temporary variables used for the parser events
private String currentElement = null;
private String currentRecordId = null;
private String currentRecordRowData = null;
@Override
public void startDocument() throws SAXException {
File dir = new File(DIRECTORY);
if (!dir.exists()) {
dir.mkdir();
}
}
@Override
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
currentElement = qName;
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (qName.equals("record_rows")) { // no more records - save last file here!
try {
saveFragment();
} catch (IOException ex) {
throw new SAXException(ex);
}
}
if (qName.equals("record_row")) { // one record finished - save in buffer & calculate size so far
charCount += tagSize("record_row");
recordRowDataLines.append("<record_row>")
.append(currentRecordRowData)
.append("</record_row>");
if (charCount >= MAX_SIZE) { // if max size was reached, save what was read so far in a new file
try {
saveFragment();
} catch (IOException ex) {
throw new SAXException(ex);
}
}
}
currentElement = null;
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
System.out.println(new String(ch, start, length));
if (currentElement == null) {
return;
}
if (currentElement.equals("record_id")) {
currentRecordId = new String(ch, start, length);
}
if (currentElement.equals("record_row")) {
currentRecordRowData = new String(ch, start, length);
charCount += currentRecordRowData.length(); // storing size so far
}
}
public long tagSize(String tagName) {
return TAG_CHAR_SIZE + tagName.length() * 2; // size of text + tags
}
/**
* Saves a new file containing approximately MAX_SIZE in chars
*/
public void saveFragment() throws IOException {
++fileCount;
StringBuilder fileContent = new StringBuilder();
fileContent.append("<record part='")
.append(fileCount)
.append("'><record_id>")
.append(currentRecordId)
.append("</record_id>")
.append("<record_rows>")
.append(recordRowDataLines)
.append("</record_rows></record>");
File fragment = new File(DIRECTORY, "data_part_" + fileCount + ".xml");
FileWriter out = new FileWriter(fragment);
out.write(fileContent.toString());
out.flush();
out.close();
// reset fragment data - record buffer and char count
recordRowDataLines = new StringBuilder();
charCount = 0;
}
}
关于java - 将 XML 拆分为指定大小的较小 XML 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21688898/
这个问题在这里已经有了答案: C sizeof a passed array [duplicate] (7 个回答) 8年前关闭。 在一个函数中,我声明了一个数组: int char_count_ar
简而言之,文件系统如何与 block 设备通信? 最佳答案 我对 block 大小不太了解。我认为 ext4(Linux)的文件系统的 block 大小是 4KB,考虑到现代处理器的页面大小(4KB)
我知道 tinyint(1) 和 tinyint(2) 具有相同的存储空间范围。 唯一的区别是显示宽度不同。这是否意味着 tinyint(1) 将存储所有类型的整数但只正确显示 0 到 9 的范围?而
今晚我已经研究了以下代码几个小时,但我只是摸不着头脑。 当使用函数从标准输入填充数组时,我不断收到“大小 8 的无效写入”和“大小 8 的无效读取”。 如有任何帮助,我们将不胜感激...我知道 Sta
我有一个 valgrind 错误,我不知道如何摆脱它们: ==5685== Invalid read of size 8 ==5685== at 0x4008A1: main (in /home
我对 Hadoop 的概念有点困惑。 Hadoop block 大小、拆分大小和 block 大小 之间有什么区别? 提前致谢。 最佳答案 block 大小和 block 大小相同。 拆分大小 可能与
我想不出一个好的标题,所以希望可以。 我正在做的是创建一个离线 HTML5 webapp。 “出于某些原因”我不希望将某些文件放在缓存 list 中,而是希望将内容放在 localStorage 中。
无法将 xamarin apk 大小减少到 80 MB 以下,已执行以下操作: 启用混淆器 配置:发布 平台:事件(任何 CPU)。 启用 Multi-Dex:true 启用开发人员检测(调试和分析)
我正在开发一个程序,需要将大量 csv 文件(数千个)加载到数组中。 csv 文件的尺寸为 45x100,我想创建一个尺寸为 nx45x100 的 3-d 数组。目前,我使用 pd.read_csv(
Hello World 示例的 React Native APK 大小约为 20M (in recent versions),因为支持不同的硬件架构(ARMv7、ARMv8、X86 等),而同一应用程
我有一个包含 n 个十进制元素的列表,其中每个元素都是两个字节长。 可以说: x = [9000 , 5000 , 2000 , 400] 这个想法是将每个元素拆分为 MSB 和 LSB 并将其存储在
如何设置 GtKTextView 的大小?我想我不能使用 gtk_widget_set_usize。 最佳答案 您不能直接控制小部件的大小,而是由其容器完成。您可以使用 gtk_widget_set_
这个问题在这里已经有了答案: c++ sizeof() of a class with functions (7 个答案) 关闭 5 年前。 结果是 12。 foobar 函数存储在内存中的什么位置
当我在 ffmpeg(或任何其他程序)中使用这样的命令时: ffmpeg -i input.mp4 image%d.jpg 所有图像的组合文件大小总是比视频本身大。我尝试减少每秒帧数、降低压缩设置、模
我是 clojurescript 的新手。 高级编译后出现“77 KB”的javascript文件是否正常? 我有一个 clojurescript 文件: 我正在使用 leinigen: lein c
我想要一个 QPixmap尺寸为 50 x 50。 我试过 : QPixmap watermark(QSize(50,50)); watermark.load(":/icoMenu/preparati
我正在尝试从一篇研究论文中重新创建一个 cnn,但我对深度学习还是个新手。 我得到了一个大小为 32x32x7 的 3d 补丁。我首先想执行一个大小为 3x3 的卷积,具有 32 个特征和步幅为 2。
我一直在尝试调整 View Controller 内的 View 大小,但到目前为止没有运气。基本上,我的 View 最底部有一个按钮,当方向从纵向更改为横向时,该按钮不再可见,因为它现在太靠下了。
如何使用此功能检查图像的尺寸?我只是想在上传之前检查一下... $("#LINK_UPLOAD_PHOTO").submit(function () { var form = $(this);
我用 C++ 完成了这个,因为你可以通过引用传递参数。我无法弄清楚如何在 JavaScript 中执行此操作。我的代码需要更改什么?我的输出是1 this.sizeOfBst = function()
我是一名优秀的程序员,十分优秀!