Может ли кто-нибудь объяснить мне, почему мое приложение начинает зависать, если я пытаюсь добавить текст в 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), я получаю некоторые зависания. Кроме того, мой компьютер начинает зависать через минуту, и я не могу просто остановить свое приложение.
Ну, вы сначала нарушаете однопоточную природу Swing.
Точно так же, как заявляет @MadProgrammer - вы делаете вызовы Swing из фонового потока, что нехорошо или безопасно. Вместо этого используйте SwingWorker<String, Void>
Я не думаю, что пользовательский интерфейс так сильно "зависает", поскольку существует задержка между чтением файла и тем, что текст становится доступным, но я предполагаю
Извините, я просто не знаю других методов, как прочитать файл и установить текст в JTextArea в другом потоке :) Я попробую использовать SwingWorker.
Пробовал использовать SwingWorker - тоже самое. Да, приложение не зависает, но текст не доступен долгое время, и мой компьютер начинает зависать. Я добавил класс FileReaderWorker, расширяющий SwingWorker <Void, Void>. Добавил в метод doInBackground мой читатель и установил текст в JTextArea с помощью метода "done". Я также добавил в readButton AL новый FileReaderWorker (). Execute () ;. И снова после использования reader1 текст доступен сразу, но после использования reader2 текст недоступен, и он не может быть добавлен в мою область textArea.
"/path/to/6.3MBfile" Что хорошего (для пользователя) в 6,3 мегабайтах текста?
Это был файл .osm - что-то вроде xml-файла.




Первое, что нужно проверить, - это производительность кода на полпути между примерами - используйте 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)».
Я сделал случайный файл строк 90k с 5x UUID в 1 строке. И все работает хорошо. Я не понял этого, потому что это зависит от файла ... Ранее я пытался прочитать файл .osm (открытая карта улиц) со строками 83k. Это своего рода xml-файл.
Files.readAllLines - это простой способ читать все строки, но поскольку он просто вызывает readLine() на BufferedReader, он вообще не дает улучшения производительности, поскольку он по-прежнему создает те же объекты, что и reader2(), но дополнительно заполняет ArrayList, который должен быть преобразован в финальный String тогда. @global_silence: имейте в виду, что readLine() возвращает строку без разрывов строки. Итак, reader2() отличается от reader1() тем, что устраняет все разрывы строк, создавая одну огромную строку. Многие программы имеют проблемы с длинными строками, особенно редакторы с переносом строк.
Есть ли конкретная причина, по которой вы используете Custom Runnable, а не просто Runnable?