在Java中使用正则表达式删除文件的特定内容
假设我有一个以以下格式存储规则的数据文件:在Java中使用正则表达式删除文件的特定内容,java,regex,Java,Regex,假设我有一个以以下格式存储规则的数据文件: //some header info //more header info //Rule: some_uuid_1234 rule "name" data data data end //Rule: some_uuid_5678 rule "name2" data data data end 现在,我希望能够在给定ID号的情况下读取或删除规则ID。因此,我的问题是,如何使用正则表达式选择和删除规则,然后从文件中删除此特定规则,而
//some header info
//more header info
//Rule: some_uuid_1234
rule "name"
data
data
data
end
//Rule: some_uuid_5678
rule "name2"
data
data
data
end
现在,我希望能够在给定ID号的情况下读取或删除规则ID。因此,我的问题是,如何使用正则表达式选择和删除规则,然后从文件中删除此特定规则,而不改变任何其他内容。只需在select/delete函数中用实际的真实ID号替换即可
//Rule: <some_id>.+?rule.+?end
注意:不要忘记单线选项。我可以想到两种解决方案,它们的性能各不相同,因此您可以选择最适合自己的解决方案 为文件编制索引 您可以为此规则文件编写一个脚本,并对修改该文件的任何操作保持更新。当然,您的单词索引将限于一个文件,其中唯一的单词将是唯一的UUID。您可以使用RandomAccess文件快速读取给定偏移量。删除操作可以覆盖目标规则,直到遇到单词“end”。此解决方案需要更多的工作,但您可以立即检索值 使用正则表达式 您也可以读取文件中的每一行,并将其与与规则UUID匹配的正则表达式模式相匹配。继续阅读,直到找到规则的“结尾”并返回。一旦知道所需的索引,删除将涉及重写规则。这个解决方案很容易编写,但性能很差。IO太多,可能会成为瓶颈。您还可以将整个文件加载到内存中,并对整个字符串运行正则表达式,具体取决于文件/字符串的预期大小。但这很快就会变得难看
无论选择哪种解决方案,您可能还需要考虑文件级锁以及它如何影响CRUD操作。如果这个设计还没有实现,请考虑将规则移到数据库。< P>我不会使用正则表达式来解决这个特殊的问题——它需要将整个文件加载到内存中,处理它并重写它。这本身并不坏,但如果您有足够大的文件,基于流的解决方案可能会更好 您要做的是一次处理一行输入文件,并维护一个布尔值: 当您找到与所需规则的声明标头匹配的行时,将变为true。 当它为真并且您找到一条与结束匹配的线时,它将变为假。 放弃布尔值设置为true时遇到的所有行,将所有其他行写入使用FilecreateTempFile创建的临时输出文件 对于每一行,如果布尔值为true,则忽略它。否则,将其写入临时输出文件 在过程结束时,使用FilerenameTo用临时输出文件覆盖输入文件
注意,此解决方案具有原子的附加优点:如果处理过程中出现错误,则不必对输入文件进行部分写入。它要么被完全覆盖,要么根本不被覆盖,这样可以防止意外的IOException
下面的代码演示了如何实现该功能。它不一定是一个完美的实现,但是它应该说明算法——在所有样板代码中间的某个地方丢失。< /P>public void deleteFrom(String id, File file) throws IOException {
BufferedReader reader;
String line;
boolean inRule;
File temp;
PrintWriter writer;
reader = null;
writer = null;
try {
// Streams initialisation.
temp = File.createTempFile("delete", "rule");
writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(temp), "utf-8")));
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8"));
inRule = false;
// For each line in the file...
while((line = reader.readLine()) != null) {
// If we're parsing the rule to delete, we're only interested in knowing when we're done.
if(inRule) {
if(line.trim().equals("end"))
inRule = false;
}
// Otherwise, look for the beginning of the targetted rule.
else if(line.trim().equals("rule \"" + id + "\""))
inRule = true;
// Normal line, we want to keep it.
else
writer.println(line);
}
}
// Stream cleanup.
finally {
if(reader != null)
reader.close();
if(writer != null)
writer.close();
}
// We're done, copy the new file over the old one.
temp.renameTo(file);
}
文件有多大?文件通常有多少条规则?它实际上是用户定义的,即我有另一个方法,如createRule..-所以它是不确定的,甚至可能是数百!读取和删除操作的速度应该有多快?ON/O1等。这没关系,当然越快越好,但即使是ON也可以。谢谢Nicolas,这似乎是一个很好的解决方案,原因很多。最后,请根据您的解释编写一个Java解决方案。然后我将测试/验证并接受您的解决方案。Thnx@拉里,你为什么不自己写呢?@BartKiers说得好。Larry—您可能需要认真考虑并发性。当同时请求两次删除时会发生什么情况?每个写入请求将配置多少磁盘IO?