2012-07-24 91 views
1

我正在使用groovy,我试图在特定的行中更改文本文件,而无需循环遍历所有以前的行。有没有办法指出你想要改变的文本文件的行?在groovy文本文件的特定行开始循环

例如

文本文件:

1 
2 
3 
4 
5 
6 

我想说

Line(3) = p 

并使其在文本文件更改为:

1 
2 
p 
4 
5 
6 

我不想要做一个循环遍历行来改变值,也就是我不想使用.eachline {line - > ...}方法。

预先感谢您,我真的很感激!

+2

你有3种选择。 1)遍历每一行,直到你到达你的兴趣点。 2)将所有行加载到内存中直接跳到感兴趣的行。 3)将你的大文件分成一大堆已知linecount的小文件,然后做1或2(这可能会更快,因为你可以跳到更接近你想要的位置)。没有办法跳到200000行文件的第13001行(除非每行的长度完全相同)。这不是Groovy的限制......对于我所能想到的所有语言,答案都是一样的 – 2012-07-24 09:47:08

+0

我期望在不需要将其加载到内存中的情况下执行2号操作。我甚至会愿意将数字加载到内存中,但即使这样做,如果不在目标行之前遍历所有行,也是不可能的。 – JohnKubik 2012-07-24 20:34:28

+0

事情是文本文件不严格地说有线条,他们只是在其中标记行结束的字符。因此,为了知道第3行的起始位置,必须在文件中搜索标记前面两行结尾的字符。你能否详细解释一下你试图解决的实际问题?也许有一个更高效的解决方案,不需要首先将文件分割成多行。 – 2012-07-25 18:08:55

回答

2

我不认为你可以跳过线条和遍历这样。你可以通过在java中使用Random Access File来跳过跳过,但是应该指定字节数而不是行。

1

尝试在文件上使用readLines()。它会将你所有的行存储在一个列表中。要更改第n行的内容,请在列表中更改n-1索引处的内容,然后加入列表项。 像这样的事情会做

//We can call this the DefaultFileHandler 

lineNumberToModify = 3 
textToInsert = "p" 

line(lineNumberToModify, textToInsert) 

def line(num , text){ 
    list = file.readLines() 
    list[num - 1] = text   
    file.setText(list.join("\n")) 
} 

编辑:对于非常大的文件,最好是你有一个自定义实现。可能是Tim Yates在对你的问题发表评论时提出的建议。 上述readLines()可以在不到一秒的时间内轻松处理多达100000行的文本。所以,你可以做这样的事情:

if(file size < 10 MB) 
    use DefaultFileHandler() 
else 
    use CustomFileHandler() 


//CustomFileHandler 

- Split the large file into buckets of acceptable size. 
- Ex: Bucket 1(1-100000 lines), Bucket 2(100000-200000 lines), etc. 
- if (lineNumberToModify falls in bucket range) 
     insert into line in the bucket 

没有硬性规定来定义你如何实现你的CustomFileHandler,因为它完全取决于所使用的情况。如果您需要在同一文件中多次执行上述操作,您可以选择首先执行完整的存储桶拆分,将其存储在内存中,然后使用存储桶执行以下操作。或者,如果是一次性操作,则可以避免先操纵所有存储桶,但只处理您需要的操作,并在以后按需处理其他操作。

即使在水桶内,您也可以定义自己的智能来加速工作。假如你想插入99999行的1-100000行的行,你可以利用groovy的方法并将其关闭到最大限度,

file.readLines().reverse()[1] = "some text" 
+0

这种方法在内部遍历文件本身的行,对吧? (假设每行都用'\ n'分隔)并且如果文本文件相当大(假设它是一个大于1GB的日志文件),则可能会遇到内存不足异常,因为您正在加载整个文件立即将文件存入内存。 – srjit 2012-07-24 06:16:13

+0

你是对的,但问题似乎更多的不是通过每个线路使用手动迭代。 – 2012-07-24 06:35:41

+0

所以这个想法是能够立即(ish)修改文本文件的一行,而不必遍历它之前的所有行。我想能够说修改(line3)并且修改了line3。虽然Vamsi做得很好,但如果我有900万行文本文件,它仍然需要循环899998才能获得倒数第二行并对其进行修改。对不起,如果这没有意义。我希望能够将线条点移动到问题的确切位置。 – JohnKubik 2012-07-24 20:33:16