Замена текста из файла в Java

1

Я пытаюсь создать простую программу в java, которая заменяет некоторые слова в файл. Чтобы изменить текст в созданном мной файле, я создаю String и устанавливаю его в текстовый файл:

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

EDIT: чтобы сохранить файл в s, я использовал Files.write(path, s.getBytes(charset)); ,

Затем я изменяю String с помощью команд типа s.replaceAll("A", "B"). Но теперь я застрял. Я хочу сделать более сложным, чем просто заменить "A" на "B". Я попытаюсь объяснить, что я могу:

Мне нужно найти в файле, если в wall someNumber someNumer someNumber, и если есть три аргумента (someNumber someNumber someNumber), тогда получите значение " someNumber " в центре. Например:

Если команды:

wall 200 500 100
wall 200 500 100

Затем я хочу получить аргумент из центра (в первом случае 500 и во втором 500) и сохранить его в переменной, а затем удалить из строки. После этого в верхней части этих команд (в примере wall 200 500 100 wall 200 500 100), я хочу написать:

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

Обратите внимание, что если wall wall аргументов не имеют какого-либо разделения (например, #other wall), то someNumber в центре будет равен (500 и 500 равны). Итак, приведенная ниже команда будет отображаться только для каждой группы (если wall wall wall... не #other wall, например, на #other wall).

Другим примером может быть файл до/после:

До:

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

После:

usemtl texture
ceil 300

wall 100 50
wall 100 100
wall 100 400

Итак, как я могу это заменить?

Ответьте, пожалуйста! Я понятия не имею, как!

EDIT: вопрос @Roan, владелец большей части этого кода:

Теперь, после ответов @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;
    }
}

Проблема в том, что эта часть не заменяет:

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);
}

Как я могу это исправить? Другое дело, эта часть должна создать число, которое растет после проверки того, сколько раз куб написан, но он тоже не работает :(

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

Метод 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;
}

Большое спасибо

  • 1
    Пожалуйста, уточните свой вопрос. Вы хотите написать: PS ....
  • 0
    Да, я знаю, что это может выглядеть сложно. Я исправил PS, теперь попробуйте прочитать его снова. Если что-то не понимаешь, то прокомментируй, что я отвечу.
Теги:
string
file
replace

5 ответов

1
Лучший ответ

Хорошо, я очень не уверен, правильно ли я это понял.
Это моя интерпретация того, что ваш вопрос:
У вас есть файл с строками, которые говорят: wall [number] [number] [number]
Теперь вы хотите проверить, есть ли там 3 номера, а затем удалить среднее число, если это номер, который вы ищете.

Поэтому я бы сделал следующее:
Если вы запустите программу, вам понадобится папка на вашем диске C: с именем "текст", и внутри этой папки вам понадобится файл text.txt с вашим форматом: например:
стена 123 300 320
Если вы измените значение номера, вы можете указать номер, номер которого должен быть указан другим, чтобы он был удален.

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);
}

}
Если у вас есть вопросы по этому коду, не стесняйтесь спрашивать их.
О, а также вам может потребоваться запустить это с правами администратора, так как он использует файлы.

Надеюсь это поможет.

  • 0
    Спасибо за ответы. Я тоже попробую. +1 Ну, ты вроде как понял. Номера команды «Стена» могут быть в любом количестве. Таким образом, файл может быть: wall 100 400 100 wall 300 400 400 wall 500 400 200 wall 200 400 600 (обратите внимание, что среднее число равно). Затем я удаляю среднее число (равное и сохраняю в переменной). После этого я создаю другой код в верхней части команд (другой пример, основанный на первом): usemtl texture ceil (middle number, that repeats HERE) wall 100 400 100 wall 300 400 400 wall 500 400 200 wall 200 400 600
  • 1
    Хорошо, рад, что смог помочь. Нужно ли мне модифицировать мой код или вы сами справитесь?
Показать ещё 33 комментария
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\"", "");


попробуйте 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 Я только опубликовал важную часть. Вы должны уметь видеть, где в коде это. Также вам нужно иметь статический int cub где-то в вашем коде, например:

static int Cube = 1;


Это должно быть, если это не помогает, дайте мне знать! : D

  • 0
    В этом файле: // brush from cube ( 400 100 200 ) ( 300 -100 300 ) // brush from cube ( 400 100 200 ) ( 300 -100 300 ) . Это дает мне ArrayIndexOutOfBounds Exception: 5 в строке 79. Я посмотрел на код, но все выглядит хорошо ...
  • 1
    Хм странно, я думаю, я посмотрю, смогу ли я найти проблему.
Показать ещё 12 комментариев
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;
}



Попробуйте 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>

Попробуйте 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();
}


Это должно сработать.

Надеюсь, это поможет: D.

  • 1
    Спасибо!!!!!! +1
  • 1
    Нет проблем, приятно видеть, что ты доволен этим: D.
Показать ещё 14 комментариев
1

Простым решением без использования (явно) регулярного выражения является разбиение String с использованием токена (в вашем случае это пробел.

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

Затем вы можете преобразовать слова [2] в int и т.д. Затем вы можете записать обратно в новый файл (или тот же, если вы прочитали все содержимое файла).

Regex являются более мощными, но для меня немного более устрашающе, поэтому вы можете выбрать все, что соответствует вашим потребностям.

  • 0
    Спасибо за ответы. Я тоже попробую. 1+
  • 0
    Почему команда \\s+ ?
Показать ещё 2 комментария
1

Чтобы проанализировать строку и посмотреть, соответствует ли она (номер номера номера "стена"), вы можете использовать выражение REGEX: см. Здесь документ.

Чтобы использовать выражение регулярного выражения, просто примените.matches() к вашей переменной String и вернет true или false в зависимости от того, проверен ли формат.

Если формат проверен, просто используйте функцию SubString, укажите индекс начала и конца, чтобы получить среднее число. Чтобы вытащить это, вы могли бы сделать обратное. SubString start (все до среднего числа), затем SubString end (все после среднего числа), а затем создайте новую строку, используя те 2.

  • 0
    Спасибо за ответы. Я попытаюсь. +1
  • 0
    Спасибо с вашим ответом и с другими, я решил свою проблему.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню