我有什么
我有很多CSV文件,如下所示:
const regKey = `SOFTWARE\Microsoft\Windows NT\CurrentVersion`
func getSettingsFromRegistry() (settings map[string]string) {
settings = make(map[string]string)
k, err := registry.OpenKey(registry.LOCAL_MACHINE, regKey, registry.QUERY_VALUE)
if err != nil {
self.Log.Println("Can't open registry key " + regKey , err)
return
}
defer k.Close()
params, err := k.ReadValueNames(0)
if err != nil {
self.Log.Printf("Can't ReadSubKeyNames %s %#v", psaConfRegistry32, err)
return
}
for _, param := range params {
val, err := getRegistryValueAsString(k, param)
if err != nil {
self.Log.Println(err)
return
}
settings[param] = val
}
self.Log.Printf("%#v\n", settings)
return
}
func getRegistryValueAsString(key registry.Key, subKey string) (string, error) {
valString, _, err := key.GetStringValue(subKey)
if err == nil {
return valString, nil
}
valStrings, _, err := key.GetStringsValue(subKey)
if err == nil {
return strings.Join(valStrings, "\n"), nil
}
valBinary, _, err := key.GetBinaryValue(subKey)
if err == nil {
return string(valBinary), nil
}
valInteger, _, err := key.GetIntegerValue(subKey)
if err == nil {
return strconv.FormatUint(valInteger, 10), nil
}
return "", errors.New("Can't get type for sub key " + subKey)
}
第二行不是错误 - 日期是“随机”,在2014年和2016年之间。幸运大多数日期与最后两行类似。但上面的序列就是一个真实的例子。
文件怎么样以及为什么要并行?
每年有5000个文件。每一个都是gziped。所以IO不是问题。 CPU现在很无聊。
我需要什么
来自上述文件的行在分隔文件中按天分组。我不在乎里面的订单。
我在想什么
使用Java并行流来读取文件。但我不知道如何将线程安全写入多个文件? 我找到了类似的内容:Write to text file from multiple threads?和Threads and file writing但我不确定这是不是一种方法?
答案 0 :(得分:0)
有很多可能性:
线程池。每个线程读取一个输入文件并写入多个输出文件(取决于输出文件的数量 - 也许您可以打开所有输出文件,可能只有一些输出文件由于许多打开文件的限制)< / p>
Map<Int, ArrayBlockingQueue>
+ IO方法用于读取文件的线程池。每个线程解析数据并将结果放入ArrayBlockingQueue实例,该实例在日期使用哈希函数找到。对于每个ArrayBlockingQueue,都有一个负责写入输出文件的线程。
一个线程从众多输入文件中读取并使用NIO写入多个输出文件。
所选择的解决方案取决于许多因素:
答案 1 :(得分:0)
我的直觉不是要过度思考这些事情。我的方法是:
虽然易于实施和调试,但这种方法不是防弹的,也不提供最佳性能。 缺点是:
如果性能是主要问题,我会提倡map-reduce方法,其中每个文件处理线程产生一些日期隔离文件,然后另一个进程连接这些文件。