Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中使用正则表达式删除文件的特定内容_Java_Regex - Fatal编程技术网

在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?