Заменить слово другим без использования функции замены

Мне нужно заменить слово на другое без использования функций replace и replaceAll в тексте.

Если слово, которое я хочу заменить, имеет ту же длину, что и исходное, проблем не возникает. Проблема в том, что слово, которое я хочу заменить, длиннее или короче исходного.

Например: я хочу заменить «один» на «тринадцать» в строке «У меня есть одна собака». Вот что я пытался сделать (я использую класс RandomAccessFile):

RandomAccessFile r  = new RandomAccessFile("toto.txt","rw")
r.seek(position); // imagine that position is the right cursor which take place under the o from the word "one"
r.writeBytes("thirteen");

Когда я пытаюсь это сделать, я стираю слова после собаки, потому что «тринадцать» длиннее, чем «один»..

Та же проблема, если слово, которое я хочу заменить, короче исходного. Я заменил оставшиеся буквы пустыми буквами, но у меня есть уродливые пробелы...

Как я могу продолжить?


person ChrisBlp    schedule 11.11.2016    source источник
comment
По какой конкретной причине вы не можете использовать замену? Это задание? У вас есть ограничения по памяти?   -  person Alexey Soshin    schedule 11.11.2016
comment
Да, это задание.   -  person ChrisBlp    schedule 11.11.2016
comment
Что вам действительно нужно изменить? Вам нужно изменить строку в памяти или файл?   -  person Kenster    schedule 12.11.2016
comment
Мне просто нужно изменить слово (строку, если хотите) на другое в заданном тексте (файле).   -  person ChrisBlp    schedule 13.11.2016


Ответы (4)


Вот как я бы это сделал:

  • Для каждой строки в файле
  • Замените то, что вы хотите в строке
  • Записать строку во временный файл
  • Запишите все обратно из временного файла в исходный файл

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

Вместо того, чтобы записывать все обратно, вы можете удалить исходный файл и переименовать временный в исходное имя файла.

person Mats391    schedule 11.11.2016

Вы можете прочитать весь файл, а затем использовать String replace. Возможны два альтернативных исхода:

  1. новая строка короче - в этом случае мы дополняем строку в конце
  2. новая строка длиннее или такой же длины - это не должно быть проблемой, так как RandomAccessFile расширит файл.

Мы записываем newString с позиции 0 - RandomAccessFile работает как массив, поэтому содержимое перезаписывается.

RandomAccessFile r  = new RandomAccessFile("toto.txt","rw");

//read the content 
byte[] buffer = new byte[(int)r.length()];
r.read(buffer);
String str = new String(buffer, "UTF-8");

//replace and pad right to get at least the same length
String newString = str.replaceAll("one","three");
str = String.format("%1$"+str.length()+ "s", newString);

//write back to the file
r.seek(0);
r.writeBytes(newString);
r.close();
person Aimee Borda    schedule 11.11.2016
comment
Я понимаю ваш метод, большое спасибо, но я не могу использовать функцию replaceAll. На самом деле, цель моего задания — найти каждое слово, совпадающее с другим (я реализовал данный алгоритм), и заменить его. Короче говоря, я должен выполнить замену всей работы по-своему. - person ChrisBlp; 13.11.2016

Попробуйте работать со строкой, как с массивом: используйте https://en.wikipedia.org/wiki/Boyer–Moore_string_search_algorithm и замена символов. Конечно, вам нужно изменить длину массива.

person Eugene Ustimenko    schedule 11.11.2016

RandomAccessFile работает как массив. Вы можете перезаписывать значения, но не вставлять что-либо посередине. Что вы можете сделать, так это setLength компенсировать и сдвинуть существующий текст вперед настолько, насколько вам нужно.

Я не уверен, что это «лучшее» решение, чем то, что предложил Mats391. Это может быть самый короткий (но не самый простой) путь.

person JollyJoker    schedule 11.11.2016
comment
Могу ли я вставить что-нибудь посередине с другим классом? Например, как BufferedWriter? - person ChrisBlp; 13.11.2016