我有一个非常长的字符串/数据块,我想在其中搜索/ grep。
示例:...AAABBAAAAVAACCDE...
在这个例子中,我想搜索AVA。
字符串的长度是GB的百分之
我的问题是,当我将字符串拆分为xxMB块(以允许并行执行)时,搜索将在边界上失败。
示例
[Block 1] ...AAABBAAAA
[Block 2] VAACCDE...
在上面的例子中,我永远找不到字符串AVA。
方法或辅助函数是否能解决这个边界问题?
感谢您的帮助
答案 0 :(得分:1)
在Spark中,并不是每个人都能阅读这些自定义格式,特别是那些没有被换行符分隔的文件,非常高效的开箱即用。
从本质上讲,你需要原始文件中的FileInputStream(带有大字符串的文件),并且对于每个块,你希望每条记录都作为流读取
例如,您可以保留每个chuck / record中最后一个 n
字符的缓存,并将其连接到下一条记录,从而有效地创建重叠。
例如:
val fileIn = "hugeString.txt"
val fileOut = "sparkFriendlyOutput.txt"
val reader = new FileInputStream(fileIn)
val writer = new BufferedOutputStream(new FileOutputStream(fileOut))
val recordSize = 9
val maxSearchLength = 3
val bytes = Array.fill[Byte](recordSize)(0)
val prefix = Array.fill[Byte](maxSearchLength)(' ')
Stream
.continually((reader.read(bytes),bytes))
.takeWhile(_._1 != -1)
.foreach{
case (_, buffer) => {
writer.write(prefix ++ buffer :+ '\n'.toByte)
Array.copy(buffer.toList.takeRight(maxSearchLength).toArray,0,prefix,0,maxSearchLength)
}}
writer.close()
reader.close()
这会变成这个字符串
... 1234567890123456789012345678901234567890123456789012345
进入此文件:
123456789
789012345678
678901234567
567890123456
...
这确实需要您选择您想要搜索的最大长度,因为这是重叠的目的。
这个文件很容易在Spark中读取
另一方面,如果您没有足够的奢侈品将其存储在磁盘(或内存)中,也许您可以考虑创建自定义火花流解决方案,您可以在其中实现自定义流媒体源(结构化流媒体) )或通过类似的FileInputStream +缓冲前缀解决方案读取文件的自定义接收器(Dstream)。
PS。你可以用重叠做更聪明的事情(至少除以2,所以不是整个可能的长度重复,
PS我认为你不关心绝对位置。如果这样做,那么我会将原始偏移量存储为每行旁边的长