Java Swing JTextArea и BufferedReader

Может ли кто-нибудь объяснить мне, почему мое приложение начинает зависать, если я пытаюсь добавить текст в JTextArea после чтения файла с помощью BufferedReader?

В порядке. Я использую GUI Designer, и у меня есть этот класс

public class ReaderTest {
private JPanel rootPanel;
private JTextArea textArea;
private JButton readButton;
private File file;

public static void main(String[] args) {
    SwingUtilities.invokeLater(() -> {
        JFrame frame = new JFrame("Reader");
        frame.setContentPane(new ReaderTest().rootPanel);

        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setSize(800, 600);

        frame.setVisible(true);
    });
}

private ReaderTest() {
    readButton.addActionListener(e -> {
        file = new File("/path/to/6.3MBfile");
        new Thread(new FileReader()).start();
    });
}

class FileReader implements Runnable {

    @Override
    public void run() {
        reader1();
//        reader2();
    }

    private void reader1() {
        try (InputStream inputStream = new BufferedInputStream(new FileInputStream(file))) {
            int count;

            StringBuilder str = new StringBuilder();
            while ((count = inputStream.read()) != -1) {
                str.append((char) count);
            }

            textArea.setText(str.toString());

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void reader2() {
        try (InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
             BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {

            String line;
            StringBuilder str = new StringBuilder();

            while ((line = bufferedReader.readLine()) != null) {
                str.append(line);
            }

            textArea.setText(str.toString());

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
}

Если я прочитал файл с помощью BufferedInputStream (reader1), у меня не было зависаний. Но если я прочитаю это с помощью BufferedReader (reader2), я получаю некоторые зависания. Кроме того, мой компьютер начинает зависать через минуту, и я не могу просто остановить свое приложение.

Есть ли конкретная причина, по которой вы используете Custom Runnable, а не просто Runnable?

SamHoque 10.12.2018 00:03

Ну, вы сначала нарушаете однопоточную природу Swing.

MadProgrammer 10.12.2018 00:04

Точно так же, как заявляет @MadProgrammer - вы делаете вызовы Swing из фонового потока, что нехорошо или безопасно. Вместо этого используйте SwingWorker<String, Void>

Hovercraft Full Of Eels 10.12.2018 00:04

Я не думаю, что пользовательский интерфейс так сильно "зависает", поскольку существует задержка между чтением файла и тем, что текст становится доступным, но я предполагаю

MadProgrammer 10.12.2018 00:06

Извините, я просто не знаю других методов, как прочитать файл и установить текст в JTextArea в другом потоке :) Я попробую использовать SwingWorker.

global_silence 10.12.2018 00:23

Пробовал использовать SwingWorker - тоже самое. Да, приложение не зависает, но текст не доступен долгое время, и мой компьютер начинает зависать. Я добавил класс FileReaderWorker, расширяющий SwingWorker <Void, Void>. Добавил в метод doInBackground мой читатель и установил текст в JTextArea с помощью метода "done". Я также добавил в readButton AL новый FileReaderWorker (). Execute () ;. И снова после использования reader1 текст доступен сразу, но после использования reader2 текст недоступен, и он не может быть добавлен в мою область textArea.

global_silence 10.12.2018 01:04
"/path/to/6.3MBfile" Что хорошего (для пользователя) в 6,3 мегабайтах текста?
Andrew Thompson 10.12.2018 03:53

Это был файл .osm - что-то вроде xml-файла.

global_silence 10.12.2018 12:18
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
8
54
1

Ответы 1

Первое, что нужно проверить, - это производительность кода на полпути между примерами - используйте BufferedReader.read() вместо BufferedReader.readLine(). Я предполагаю, что производительность будет примерно такой же, хотя есть накладные расходы на декодирование UTF-8.

Далее вы каждый раз выделяете String. Это не хорошо. Было бы намного лучше просто прочитать кусок с Reader.read(char[]). Кроме того, BufferedReader.readLine() не очень эффективен, помимо распределения String он может также выделить StringBuffer с внутренними компонентами каждый раз, когда это звонок. java.nio.file.Files.readAllLines - это простой и эффективный способ загрузить файл, если вам нужны все строки, хотя это будут все String.

Огромный оборот памяти будет причиной проблем всех потоков.

Я использовал BufferedReader br = new BufferedReader (новый FileReader (файл)) и получаю то же самое без доступного текста. BufferedReader успешно прочитал файл даже в кодировке UTF-8. Я попытался отладить его и понял, что моя программа останавливается на «textArea.setText (text)».

global_silence 10.12.2018 10:44

Я сделал случайный файл строк 90k с 5x UUID в 1 строке. И все работает хорошо. Я не понял этого, потому что это зависит от файла ... Ранее я пытался прочитать файл .osm (открытая карта улиц) со строками 83k. Это своего рода xml-файл.

global_silence 10.12.2018 12:17
Files.readAllLines - это простой способ читать все строки, но поскольку он просто вызывает readLine() на BufferedReader, он вообще не дает улучшения производительности, поскольку он по-прежнему создает те же объекты, что и reader2(), но дополнительно заполняет ArrayList, который должен быть преобразован в финальный String тогда. @global_silence: имейте в виду, что readLine() возвращает строку без разрывов строки. Итак, reader2() отличается от reader1() тем, что устраняет все разрывы строк, создавая одну огромную строку. Многие программы имеют проблемы с длинными строками, особенно редакторы с переносом строк.
Holger 13.12.2018 09:08

Другие вопросы по теме