Я пытаюсь создать простую программу в 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
Итак, как я могу это заменить?
Ответьте, пожалуйста! Я понятия не имею, как!
Теперь, после ответов @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;
}
Большое спасибо
Хорошо, я очень не уверен, правильно ли я это понял.
Это моя интерпретация того, что ваш вопрос:
У вас есть файл с строками, которые говорят: 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);
}
}
Если у вас есть вопросы по этому коду, не стесняйтесь спрашивать их.
О, а также вам может потребоваться запустить это с правами администратора, так как он использует файлы.
Надеюсь это поможет.
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:
// 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
// brush from cube ( 400 100 200 ) ( 300 -100 300 ) // brush from cube ( 400 100 200 ) ( 300 -100 300 )
. Это дает мне ArrayIndexOutOfBounds Exception: 5
в строке 79. Я посмотрел на код, но все выглядит хорошо ...
Вы можете использовать это, чтобы подсчитать количество встречных слов в строке:
Попробуйте 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.
Простым решением без использования (явно) регулярного выражения является разбиение String
с использованием токена (в вашем случае это пробел.
line = "wall 100 300 50";
String[] words = line.split("\\s+");
Затем вы можете преобразовать слова [2] в int
и т.д. Затем вы можете записать обратно в новый файл (или тот же, если вы прочитали все содержимое файла).
Regex являются более мощными, но для меня немного более устрашающе, поэтому вы можете выбрать все, что соответствует вашим потребностям.
\\s+
?
Чтобы проанализировать строку и посмотреть, соответствует ли она (номер номера номера "стена"), вы можете использовать выражение REGEX: см. Здесь документ.
Чтобы использовать выражение регулярного выражения, просто примените.matches() к вашей переменной String и вернет true или false в зависимости от того, проверен ли формат.
Если формат проверен, просто используйте функцию SubString, укажите индекс начала и конца, чтобы получить среднее число. Чтобы вытащить это, вы могли бы сделать обратное. SubString start (все до среднего числа), затем SubString end (все после среднего числа), а затем создайте новую строку, используя те 2.