简体   繁体   English

用Java替换文件中的文本

[英]Replacing text from a file in Java

I've been trying to create a simple program, in java, that replaces some words into a file. 我一直在尝试用Java创建一个简单的程序,该程序将某些单词替换为文件。 To change the text into the file I created, I create a String and set it to the file text: 要将文本更改为我创建的文件,请创建一个String并将其设置为文件文本:

Path path = Paths.get("somePath/someFile.someExtension");
Charset charset = StandardCharsets.UTF_8;
String s = new String(Files.readAllBytes(path), charset);

EDIT: To save to the file with s , I used Files.write(path, s.getBytes(charset)); 编辑:要使用s保存到文件,我使用了Files.write(path, s.getBytes(charset)); .

Then I change the String with commands like s.replaceAll("A", "B") . 然后,我使用s.replaceAll("A", "B")类的命令更改String。 But now, I'm stuck. 但是现在,我被困住了。 I want to make a more complicated then just replacing "A" with "B". 我想变得更复杂,然后仅将“ A”替换为“ B”。 I'll try to explain has best I can: 我将尽力说明我所能做到的:

I need to find at the file if wall someNumber someNumer someNumber is in there, and if there are three arguments ( someNumber someNumber someNumber ), then get the value of " someNumber " at the center. 我需要在文件中查找wall someNumber someNumer someNumber是否在其中,并且是否有三个参数( someNumber someNumber someNumber ),然后在中心获取“ someNumber ”的值。 For example: 例如:

If the commands are: 如果命令是:

wall 200 500 100
wall 200 500 100

Then I want to get the argument from the center (in the first case 500 and in the second 500), and store it into a variable, then delete it from the String. 然后,我想从中心获取参数(在第一种情况下为500,在第二种情况下为500),并将其存储到变量中,然后从字符串中将其删除。 After that, on the top of these commands (in the example wall 200 500 100 wall 200 500 100 ), I want to write: 之后,在这些命令的顶部(在示例wall 200 500 100 wall 200 500 100 ),我要编写:

usemtl texture
ceil (someNumber that we stored, in the case, 500)

Note that if the arguments wall wall don't have any kind of separation (for example #other wall ), then the someNumber at the center will be equal (500 and 500 are equal). 请注意,如果参数wall wall没有任何分隔(例如#other wall ),则中心的someNumber将相等(500和500相等)。 So, the command below will just appear per group (if wall wall wall... isn't separed with #other wall , for example). 因此,下面的命令将仅按组显示(例如,如果wall wall wall...#other wall不分隔)。

Other example, this would be the file before / after: 其他示例,这将是之前/之后的文件:

Before: 之前:

wall 100 300 50
wall 100 300 100
wall 100 300 400

After: 后:

usemtl texture
ceil 300

wall 100 50
wall 100 100
wall 100 400

So, how can I make this replace? 那么,我该如何替换呢?

Please answer! 请回答! I have no idea how! 我不知道如何!

EDIT: question to @Roan, owner of most of this code: 编辑:向@Roan提问,此代码大部分是所有者:

Now, after the answers @Roan code transformed into: 现在,在答案之后,@ Roan代码转换为:

package com.fileConverter.main;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

import javax.swing.JFileChooser;

public class FileReplace extends JFileChooser {
    private static final long serialVersionUID = -254322941935132675L;

    private static FileReplace chooser = new FileReplace();

    public static void main(String[] args) {
        chooser.showDialog(chooser, "Open");
    }

    public void cancelSelection() {
        System.exit(0);
    }

    public void approveSelection() {
        super.approveSelection();
        System.out.println("starting...");

        // The path were your file is
        String path = chooser.getSelectedFile().getAbsolutePath();
        File file = new File(path);

        // try to create an inputstream from the file
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            // If we are here the file is not found
            e.printStackTrace();
        }

        // make it a buffered reader
        BufferedReader bufferedReader = new BufferedReader(
                new InputStreamReader(fis));

        // to store the current line
        String line;

        // array to store the different words
        String[] words;

        // create a second temporally file that will replace the original file
        File file2 = new File(chooser.getSelectedFile().getParentFile()
                + "$$$$$$$$$$$$$$$.tmp");
        try {
            file.createNewFile();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        // and create the streams
        FileOutputStream file2Os = null;
        try {
            file2Os = new FileOutputStream(file2);
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        }
        PrintWriter writer = new PrintWriter(file2Os);
        try {
            System.out.println("replacing code...");
            writer.println("mtllib textures.mtl");
            // loop through all lines and
            while ((line = bufferedReader.readLine()) != null) {
                line = line
                        .replace("//", "#")
                        .replace("(", "wall")
                        .replace(")", "\n")
                        .replace("{", "")
                        .replace("}", "")
                        .replace("# brush from cube",
                                "room cube" + countWords(line, "cube"))
                        .replace(" NULL 0 0 0 1 1 0 0 0", "")
                        .replace("\"classname\"", "")
                        .replace("\"worldspawn\"", "");

                // get all the diffent terms
                words = line.split(" ");

                // see if there are 4 terms in there: wall x x x
                // and if the first term equals wall28
                // and if the middle number is the number you want to delete
                // if not just copy the line over

                if (words.length == 4 && words[0].contains("wall")) {
                    double doubleVal = Double.parseDouble(words[2]);
                    int val = (int) doubleVal;
                    // now modify the line by removing the middel number
                    String newLine = words[0] + " " + words[1] + " " + words[3];
                    String valInsert = null;

                    if (val >= 0)
                        valInsert = "\n" + "usemtl texture" + "\n" + "ceil "
                                + val;
                    else if (val < 0)
                        valInsert = "\n" + "usemtl texture" + "\n" + "floor "
                                + val;

                    // write this to the new file
                    writer.println(valInsert);
                    writer.println(newLine);
                } else {
                    // copy the old line
                    writer.println(line);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        // close our resources
        writer.close();
        try {
            bufferedReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // now we rename the temp file and replace the old file
        // with the new file with the new content
        file.delete();
        file2.renameTo(file);

        System.out.println("done!");
    }

    public int countWords(String string, String word) {
        int lastIndex = 0;
        int count = 0;

        while (lastIndex != -1) {

            lastIndex = string.indexOf(word, lastIndex);

            if (lastIndex != -1) {
                count++;
                lastIndex += word.length();
            }
        }
        return count;
    }
}

The problem is that this part doesn't make any replaces: 问题在于,这部分没有任何替换:

if (words.length == 4 && words[0].contains("wall")) {
    double doubleVal = Double.parseDouble(words[2]);
    int val = (int) doubleVal;
    // now modify the line by removing the middel number
    String newLine = words[0] + " " + words[1] + " " + words[3];
    String valInsert = null;

    if (val >= 0)
        valInsert = "\n" + "usemtl texture" + "\n" + "ceil "
                + val;
    else if (val < 0)
        valInsert = "\n" + "usemtl texture" + "\n" + "floor "
                + val;

    // write this to the new file
    writer.println(valInsert);
    writer.println(newLine);
}

How can I fix it? 我该如何解决? Other thing, this part is suppose to create a number that grows after checking how many times cube is wrote, but it doesn't works too :( 另一件事,这部分是假定创建一个数字,该数字在检查了写入多维数据集的次数之后会增加,但是它也不起作用:(

.replace("# brush from cube", "room cube" + countWords(line, "cube"))

The countWords method: countWords方法:

public int countWords(String string, String word) {
    int lastIndex = 0;
    int count = 0;

    while (lastIndex != -1) {

        lastIndex = string.indexOf(word, lastIndex);

        if (lastIndex != -1) {
            count++;
            lastIndex += word.length();
        }
    }
    return count;
}

Many Thanks 非常感谢

To analyse a string and see if it matches ("wall" number number number), you can use a REGEX expression: see the doc here . 要分析字符串并查看它是否匹配(“墙壁”数字编号),您可以使用REGEX表达式:请参见此处的文档。

To use the regex expression, just apply .matches() on your String variable and it'll return true or false depending on if the format is verified. 要使用正则表达式,只需在您的String变量上应用.matches(),它将根据格式是否经过验证返回true或false。

If the format is verified, then just use the SubString function, specify the start and end index so you get the middle number. 如果格式经过验证,则只需使用SubString函数,指定开始和结束索引,即可获得中间编号。 To take it out, you could do the opposite. 要删除它,您可以相反。 SubString the start (everything until middle number), then SubString the end (everything after the middle number), and then create a new string using those 2. SubString开头(一切直到中间数字),然后SubString结尾(一切在中间数字之后),然后使用那些2创建一个新字符串。

A simple solution without using (explicitly) regex is to split the String using token (in your case it's a white space. 一个不使用(显式)正则表达式的简单解决方案是使用标记(在您的情况下为空白)分割String

line = "wall 100 300 50";
String[] words = line.split("\\s+");

You can then get the words[2] convert to an int etc. Then you can write back to a new file (or the same if you have read all file contents). 然后,您可以将单词[2]转换为int等。然后您可以写回新文件(如果已读取所有文件内容,则写回相同的文件)。

Regex are more powerful but to me a bit more intimidating so you can pick whatever matches your needs. 正则表达式功能更强大,但对我来说更令人生畏,因此您可以选择满足您需求的任何东西。

Ok I'm very unsure if I understood this correctly. 好吧,我不确定我是否理解正确。
This is my interpretation of wat your question is: 这是我对wat的解释,您的问题是:
You have a file with lines that say: wall [number] [number] [number] 您有一个带有以下行的文件:wall [number] [number] [number]
Now you want to check if there there are 3 numbers and then delete the middle number if it's the number you're searching for. 现在,您要检查是否有3个数字,如果要搜索的是中间数字,则将其删除。

So I would do this like this: 所以我会这样:
Befor you run the programm you'll need a folder on your C: drive with the name "text" and inside that folder you'll need a file called text.txt with you format in it so: for example: 在运行程序之前,您将在C:驱动器上需要一个名为“文本”的文件夹,并且在该文件夹内,您将需要一个名为text.txt的文件,其格式如下:例如:
wall 123 300 320 墙123300320
If you change the value of number you can specify wich number the middle number has to be in oder for it to be deleted. 如果您更改数字的值,则可以指定中间数字,中间的数字必须在中间才能删除。

public class FileReplace {

public static void main(String[] args){
    //The path were your file is
    String path = "C:\\text\\text.txt";
    File file = new File(path);

    //The number you want to delete
    int number = 300;

    //try to create an inputstream from the file
    FileInputStream fis = null;
    try {
        fis = new FileInputStream(file);
    } catch (FileNotFoundException e) {
        //If we are here the file is not found
        e.printStackTrace();
    }

    //make it a buffered reader
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fis));

    //to store the current line
    String line;

    //array to store the different words
    String[] words;

    //create a second temporally file that will replace the original file
    File file2 = new File("C:\\text\\$$$$$$$$$$.tmp");
    try {
        file.createNewFile();
    } catch (IOException e1) {
        e1.printStackTrace();
    }
    //and create the streams
    FileOutputStream fos = null;
    try {
        fos = new FileOutputStream(file2);
    } catch (FileNotFoundException e1) {
        e1.printStackTrace();
    }
    PrintWriter writer = new PrintWriter(fos);
    try {
        //loop through all lines and 
        while((line = bufferedReader.readLine()) != null){
            //get all the diffent terms
            words = line.split(" ");

            //see if there are 4 terms in there: wall x x x
            //and if the first term equals wall
            //and if the middle number is the number you want to delete
            //if not just copy the line over
            if(words.length == 4 && words[0].equals("wall") && words[2].equals(String.valueOf(number))){
                //now modify the line by removing the middel number
                String newLine = words[0] + " " + words[1] + " " + words[3];

                //write this to the new file
                writer.println(newLine);
            }else{
                //copy the old line
                writer.println(line);
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    //close our resources
    writer.close();
    try {
        bufferedReader.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

    //now we rename the temp file and replace the old file
    //with the new file with the new content
    file.delete();
    file2.renameTo(file);
}

} }
If you have ay questions about this code feel free to ask them. 如果您对此代码有疑问,请随时询问。
Oh and also you might need to run this with administrator right as it uses files. 哦,而且您可能需要以管理员身份运行此文件,因为它使用文件。

Hope this helps. 希望这可以帮助。

You could use this to count the number of occurances of a word in a string: 您可以使用它来计算字符串中一个单词的出现次数:
Try 1: 尝试1:

public static int countWords(String string, String word) {
    //get all individual words
    String[] terms = string.split(" ");
    //this variable counts how many times word occurs
    int count = 0;
    //a count variable for the loop
    int counter = 0;
    //loop through all the words and if we see a word that equals word we add one to the count variable
    while(counter < terms.length){
        //check if the term equals the word
        if(terms[counter].equals(word)){
            //the term matched add one to the count variable
            count++;
        }
        counter++;
    }
    //return the number of occurrences
    return count;
}



Try 2: 尝试2:

public static String countWords(String string, String word) {
    //get all individual words
    String[] terms = string.split(" ");
    //this variable counts how many times word occurs
    int count = 0;
    //a count variable for the loop
    int counter = 0;

    StringBuffer sb = new StringBuffer();
    sb.append("1");
    //loop trough all the words and if we see a word that equals word we add one to the count variable
    while(counter < terms.length){
        //check if the term equals the word
        if(terms[counter].equals(word)){
            //the term matched add one to the count variable
            count++;
            sb.append(" " + word + (count + 1));
        }
        counter++;
    }
    //return the number of occurrences
    return sb.toString();
}<br><br>

Try 3: you need to have a static variable in your code called lastVar: 尝试3:您的代码中需要有一个名为lastVar的静态变量:

static int lastVar = 0;
public static String countWords(String string, String word) {
    //get all individual words
    String[] terms = string.split(" ");
    //this variable counts how many times word occurs
    int count = 0;
    //a count variable for the loop
    int counter = 0;

    StringBuffer sb = new StringBuffer();
    sb.append("1");
    //loop trough all the words and if we see a word that equals word we add one to the count variable
    while(counter < terms.length){
        //check if the term equals the word
        if(terms[counter].equals(word)){
            //the term matched add one to the count variable
            count++;
            sb.append(" " + word + (count + 1 + lastVar));
        }
        counter++;
    }
    lastVar += count + 1;
    //return the number of occurrences
    return sb.toString();
}


That should work. 那应该工作。

Hope this helps :D. 希望这会有所帮助:D。

To reformat your cube lines you could use: 要重新格式化立方体线,可以使用:
Try 1: 尝试1:

// loop through all lines and
        while ((line = bufferedReader.readLine()) != null) {
            if(line.contains("// brush from cube")){
                line = line.replace("// brush from cube ", "").replace("(", "").replace(")", "");
                String[] arguments = line.split("\\s+");
                line = "cube" + Cube + " usemtl texture ceil " + arguments[2] + " wall " + arguments[1] + " " + arguments[3] + " usemtl texture floor " + arguments[5] + " wall " + arguments[4] + " " + arguments[6];
                Cube++;
            }
            line = line
                    .replace("//", "#")
                    .replace("(", "wall")
                    .replace(")", "\n")
                    .replace("{", "")
                    .replace("}", "")
                    .replace(" NULL 0 0 0 1 1 0 0 0", "")
                    .replace("\"classname\"", "")
                    .replace("\"worldspawn\"", "");


try 2: 尝试2:

// loop through all lines and
        while ((line = bufferedReader.readLine()) != null) {
            if(line.contains("// brush from cube")){
                line = line + bufferedReader.readLine() + " " + bufferedReader.readLine();
                line = line.replace("// brush from cube ", "").replace("(", "").replace(")", "");
                String[] arguments = line.split("\\s+");
                line = "cube" + Cube + " usemtl texture ceil " + arguments[2] + " wall " + arguments[1] + " " + arguments[3] + " usemtl texture floor " + arguments[5] + " wall " + arguments[4] + " " + arguments[6];
                Cube++;
            }
            line = line
                    .replace("//", "#")
                    .replace("(", "wall")
                    .replace(")", "\n")
                    .replace("{", "")
                    .replace("}", "")
                    .replace(" NULL 0 0 0 1 1 0 0 0", "")
                    .replace("\"classname\"", "")
                    .replace("\"worldspawn\"", "");


PS I've only posted the important part. PS我只发布了重要的部分。 You should be able to see where in the code this goes. 您应该能够看到代码在哪里。 Also you need to have a static int called cube somewhere in you code like: 另外,您还需要在代码中的某个地方有一个称为int的静态int,例如:

static int Cube = 1;


That should be it if it doesn't work let me know! 如果不起作用就应该这样告诉我! :D :D

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM