基于所述列中的一个将输入文件划分为多个文件



我有一个分号分隔的输入文件,其中第一列是一个3个字符的固定宽度代码,而其余列是一些字符串数据。

001;first_data_str;second_data_str;third_data_str;fourth_data_str
001;first_data_str;second_data_str;third_data_str;fourth_data_str
002;first_data_str;second_data_str;third_data_str;fourth_data_str
003;first_data_str;second_data_str;third_data_str;fourth_data_str
001;first_data_str;second_data_str;third_data_str;fourth_data_str
003;first_data_str;second_data_str;third_data_str;fourth_data_str
001;first_data_str;second_data_str;third_data_str;fourth_data_str
002;first_data_str;second_data_str;third_data_str;fourth_data_str
002;first_data_str;second_data_str;third_data_str;fourth_data_str
003;first_data_str;second_data_str;third_data_str;fourth_data_str
003;first_data_str;second_data_str;third_data_str;fourth_data_str
003;first_data_str;second_data_str;third_data_str;fourth_data_str
002;first_data_str;second_data_str;third_data_str;fourth_data_str
001;first_data_str;second_data_str;third_data_str;fourth_data_str

我想根据第一列的不同值将上述文件划分为多个文件。

例如,在上面的例子中,第一列有三个不同的值,所以我将把文件分为三个文件,即001.txt、002.txt、003.txt

输出文件应包含作为第一行的项目计数和作为剩余行的数据。

所以有5 001行,所以001.txt将是:

5
first_data_str;second_data_str;third_data_str;fourth_data_str
first_data_str;second_data_str;third_data_str;fourth_data_str
first_data_str;second_data_str;third_data_str;fourth_data_str
first_data_str;second_data_str;third_data_str;fourth_data_str
first_data_str;second_data_str;third_data_str;fourth_data_str

类似地,002文件的第一行将为4,然后是4行数据,003文件的第一行将为5,然后是5行数据。

考虑到大于100000行的非常大的输入文件,实现这一点的最有效方法是什么?

我写了以下代码来读取文件中的行:

try{
FileInputStream fstream = new FileInputStream(this.inputFilePath);
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
while ((strLine = br.readLine()) != null)   {
String[] tokens = strLine.split(";");
}
in.close();
}catch(IOException e){
e.printStackTrace();
}
每行的
  • 提取区块名称,例如001
  • 查找名为"001 tmp.txt"的文件
  • 如果存在,请读取第一行-它将为您提供行数,然后增加值并使用参数为0的seek函数写入同一文件,然后使用writeUTF覆盖字符串。也许这里必须应用一些字符串长度计算,例如,将占位符保留为10个空格
  • 如果一个不存在,则创建一个,并将1写为第一行,用10个空格填充
  • 将当前行追加到文件
  • 关闭当前文件
  • 继续源文件的下一行

想到的解决方案之一是保留一个"Map",并且只打开每个文件一次。但您无法做到这一点,因为您有大约1个lac行,所以没有一个操作系统会允许您有那么多打开的文件描述符。

因此,其中一种方法是以追加模式打开文件,并不断写入并关闭它。但由于大量的文件打开-关闭调用,过程可能会变慢。不过你可以自己测试一下。

如果上述方法不能提供令人满意的结果,您可以尝试方法1和方法2的组合,其中您在任何时候只打开100个打开的文件,并且只有在需要将尚未打开的新文件写入…时才关闭文件

首先,创建HashMap<String, ArrayList<String>> map以收集文件中的所有数据。其次,使用strLine.split(";",2)而不是strLine.split(";")。结果将是长度为2的数组,第一个元素是代码,第二个元素是数据。然后,将解码字符串添加到地图:

ArrayList<String> list=map.get(tokens[0]);
if (list==null) {
map.put(tokens[0], list=new ArrayList<String>();
}
list.add(tokens[1]);

最后,扫描map.keySet(),为每个密钥创建一个名为该密钥的文件,并将列表的大小和内容写入其中

对于每三个字符的代码,您将有一个输入行列表。对我来说,显而易见的解决方案是使用MapString键(三个字符的代码)指向包含所有行的相应List

对于这些键中的每一个,您将创建一个具有相关名称的文件,第一行将是列表的大小,然后您将对其进行迭代以写入其余行。

我想您还没有固定到三个文件,所以我建议您创建一个以三个字符的代码为键、以编写器为值的编写器映射。

对于您阅读的每一行,您都可以选择或创建所需的读卡器,并将行写入其中。此外,您还需要第二个映射来维护所有文件的行计数值。

读取完源文件后,刷新并关闭所有写入程序,然后逐个重新读取文件。这一次,您只需在文件前面添加行数。据我所知,没有其他方法,只能重写整个文件,因为在不缓冲和重写整个文件的情况下,不可能直接在文件开头添加任何内容。我建议你用一个临时文件。

这个答案只适用于文件太大而无法完全存储在内存中的情况。如果存储是可能的,有更快的解决方案。类似于在将文件写入文件之前将文件的内容完全存储在StringBuffer对象中。

最新更新