我有一个以分号分隔的输入文件,其中第一列是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行数据。
考虑到大于100,000行的非常大的输入文件,实现这一目标的最有效方法是什么?
我在下面写了代码来读取文件中的行:
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();
}
答案 0 :(得分:1)
答案 1 :(得分:1)
想到的解决方案之一是保留“地图”并且只打开每个文件一次。但是你无法做到这一点,因为你有大约1个lac行,所以没有OS会允许你那么多打开文件描述符。
所以其中一种方法是以附加模式打开文件并继续写入并关闭它。但由于大量文件打开了近距离通话,这个过程可能会放慢速度。你可以为自己测试它。
如果以上结果不能提供令人满意的结果,您可以尝试混合使用方法1和方法2,其中您只能在任何时间打开100个打开的文件,如果尚未打开的新文件需要关闭文件写信给....
答案 2 :(得分:0)
对于每个三个字符的代码,您将获得一个输入行列表。对我来说,显而易见的解决方案是使用Map
,String
个键(您的三个字符代码)指向包含所有行的相应List
。
对于每个键,你要创建一个具有相关名称的文件,第一行是列表的大小,然后你将迭代它以写出剩余的行。
答案 3 :(得分:0)
我猜你没有固定三个文件所以我建议你创建一个作家地图,你的三个字符代码作为键,作者作为值。
对于您阅读的每一行,您可以选择或创建所需的阅读器并将行写入。您还需要第二个映射来维护所有文件的行计数值。
完成阅读源文件后,您将刷新并关闭所有编写器并再次逐个读取文件。这次您只需在文件前添加行数。除了根据我的知识重写整个文件之外别无他法,因为它不能直接在文件的开头添加任何内容而不需要缓冲和重写整个文件。我建议你使用一个临时文件。
此答案仅适用于文件太大而无法完全存储在内存中的情况。如果可以存储,可以有更快的解决方案。就像在将文件内容写入文件之前将文件内容完全存储在StringBuffer
个对象中一样。
答案 4 :(得分:0)
首先,创建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()
并为每个键创建一个名为该键的文件,并将列表的大小和列表内容写入其中。