Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> RandomAccessFile и FileChannel оптимизация кода, проверьте код плз! 
:(
    Опции темы
Pawl
Дата 21.10.2011, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 649
Регистрация: 22.4.2008
Где: Витебск

Репутация: 7
Всего: 28



Уважаемые форумчане,
я уже открывал похожую тему, но с горяча ее закрылsmile Написал программку, позволяющую заменять в текстовом файле одно сочетание символов другим. Она работает, но мне не нравятся 2 вещи:
1) иногда (редко) не везде заменяет
2) плодится очень много строковых объектов.
Прошу помочь улучшить и оптимизировать код. код привожу тут и прилагаю.
Спасибо!
Код

import java.io.RandomAccessFile;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class Replacer {
    public static void replace(String fileName, String replable, String replacer) throws IOException, IllegalArgumentException {
        RandomAccessFile r = new RandomAccessFile(fileName, "rw");
        FileChannel file = r.getChannel();
        Mover er = new Mover(fileName, "rw");
     int i = 1, read = 0, oldRead = -1;
        long currentPosition = 0;
        String str = "";
        while (currentPosition < file.size()) {
            /**
             * записываем в буфер байты и преобразовываем их в строки до тех пор, пока в строке
             * не встретится искомое выражение
             */
            if (!str.contains(replable)) {
                file.position(currentPosition);
                ByteBuffer buffer = ByteBuffer.allocate(i++);
                read = file.read(buffer);
                str = new String(buffer.array());
                /**
                 * если текст (больше) не содержит искомого выражения, цикл прерывается
                 */
                if (read == oldRead || read >= file.size()) {
                    break;
                }
            } else {
                String oldStr = str;
                str = str.replaceAll(replable, replacer);
                if (str.length() != oldStr.length()) {
                    /**
                     * если размер заменяемого выражения не совпадает с заменяющим
                     * текстом, сдвигаем байты в файле и изменяем его размер
                     */                    
                    er.move(str.getBytes().length - oldStr.getBytes().length, file.position());
                }
                /**
                 * записываем в файл изменённую строку и переводим курсор в следующую
                 * позицию для чтения
                 */
                file.position(currentPosition);
                file.write(getByts(str));
                currentPosition += str.length();
                i = 1;
            }
            oldRead = read;
        }
        file.close();
        r.close();
    }

    private static ByteBuffer getByts(String s) {
        ByteBuffer b = ByteBuffer.wrap(s.getBytes());
        return b;
    }

    public static void main(String[] args) {
        try {
            replace("!!!.txt", "r", "AA");
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }
    }
}

Код

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

public class Mover extends RandomAccessFile {
   /**
    * Буффер для для чтения и записи в файл
    */
   private byte[] buffer = new byte[8192];

   public Mover(String name, String mode) throws FileNotFoundException {
      super(name, mode);
   }

   public Mover(File file, String mode) throws FileNotFoundException {
      super(file, mode);
   }

   public void move(int pos, long off) throws IOException {
      long oldLength = length();
      if (off < oldLength) {
         /**
          * Если смещение меньше длины файла, т.е. вставляем как
          * бы в середину файла...
         
         /**
          * Точка начиная с которой будем двигать куски файла в конец
          * buffer.length -размер передвигаемого куска
          */
         long startChunk = oldLength - buffer.length;
         while (true) {
            /**
             * Сначала передвигаем куски равные buffer.length
             */
            if (startChunk >= off) {
               seek(startChunk);
               readFully(buffer);
               seek(startChunk + pos);
               write(buffer);
            } else {
                /**
                 * В конце обычно остается кусок меньше buffer.length
                 * соответственно читаем не весь буфер, а только часть
                 */
               seek(off);
               int chunkLength = (int)(buffer.length + startChunk - off);
               readFully(buffer, 0, chunkLength);
               /**
                * Изменяем длину файла на длину вставляемого массива
                */
               setLength(oldLength + pos);              
               seek(off + pos);
               write(buffer, 0, chunkLength);
               break;
            }
            startChunk -= buffer.length;
         }
      } else {
         /**
          * Если смещение больше длины файла,
          * ничего сохранять и перемещать ненадо, просто увеличиваем файл:
          */
         setLength(off + pos);
      }
   }
}


Присоединённый файл ( Кол-во скачиваний: 3 )
Присоединённый файл  replace.rar 2,08 Kb


--------------------
В действительности всё совсем не так, как на самом деле
PM MAIL   Вверх
Pawl
Дата 21.10.2011, 20:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 649
Регистрация: 22.4.2008
Где: Витебск

Репутация: 7
Всего: 28



исправил класс Replacer, теперь заменяет всё и везде
Код

import java.io.RandomAccessFile;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class Replacer {
    public static void replace(String fileName, String replable, String replacer) throws IOException, IllegalArgumentException {
        RandomAccessFile r = new RandomAccessFile(fileName, "rw");
        FileChannel file = r.getChannel();
        Mover er = new Mover(fileName, "rw");
        int i = 1, read = 0;
        long currentPosition = 0, position = 0;
        String str = "";
        while (currentPosition < file.size()) {
            /**
             * записываем в буфер байты и преобразовываем их в строки до тех пор, пока в строке
             * не встретится искомое выражение
             */
            if (!str.contains(replable)) {
                file.position(position);
                ByteBuffer buffer = ByteBuffer.allocate(i++);
                read = file.read(buffer);
                str = new String(buffer.array());
                currentPosition++;
                /**
                 * если текст (больше) не содержит искомого выражения, цикл прерывается
                 */
                if (read >= file.size()) {
                    break;
                }
            } else {
                currentPosition = position;
                String oldStr = str;
                str = str.replaceAll(replable, replacer);
                if (str.length() != oldStr.length()) {
                    /**
                     * если размер заменяемого выражения не совпадает с заменяющим
                     * текстом, сдвигаем байты в файле и изменяем его размер
                     */                    
                    er.move(str.getBytes().length - oldStr.getBytes().length, file.position());
                }
                /**
                 * записываем в файл изменённую строку и переводим курсор в следующую
                 * позицию для чтения
                 */
                file.position(position);
                file.write(getByts(str));
                position += str.length();
                i = 1;
            }         
        }
        file.close();
        r.close();
    }

    private static ByteBuffer getByts(String s) {
        ByteBuffer b = ByteBuffer.wrap(s.getBytes());
        return b;
    }

    public static void main(String[] args) {
        try {
            replace("!!!.txt", "3", "r");
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }
    }
}

Однако остаётся вопрос, как минимизировать количество создаваемых объектов?
Кроме того, метод replaceAll класса String, по идее, должен заменять регулярное выражение. Т. е., если я, например, напишу  replace("!!!.txt", "[0-9]", "r"); или replace("!!!.txt", "\\d", "r"); то в файле !!!.txt будут заменены все цифры на r. Но так, почему-то не происходит. Для замены надо указывать конкретную цифру (или букву). Может, кто подскажет, почему!
Спасибо ещё раз!smile


--------------------
В действительности всё совсем не так, как на самом деле
PM MAIL   Вверх
ИванИванович
Дата 25.10.2011, 06:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 25.10.2011

Репутация: нет
Всего: нет



Цитата

метод replaceAll класса String, по идее, должен заменять регулярное выражение. Т. е., если я, например, напишу  replace("!!!.txt", "[0-9]", "r"); или replace("!!!.txt", "\\d", "r"); то в файле !!!.txt будут заменены все цифры на r. Но так, почему-то не происходит



потому что логика такая в методе smile
Цитата

записываем в буфер байты и преобразовываем их в строки до тех пор, пока в строке не встретится искомое выражение

Цитата

если текст (больше) не содержит искомого выражения, цикл прерывается

а str.contains regular expressions не понимает
PM MAIL   Вверх
Pawl
Дата 25.10.2011, 17:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 649
Регистрация: 22.4.2008
Где: Витебск

Репутация: 7
Всего: 28



Цитата(ИванИванович @  25.10.2011,  06:27 Найти цитируемый пост)
а str.contains regular expressions не понимает

точно не понимает! Пардон, затупил! Попробую matches.
Ну а что по поводу количества создаваемых объектов String и ByteBuffer?


--------------------
В действительности всё совсем не так, как на самом деле
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0463 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.