Отслеживание чтения данных из потока Java

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

Использовать данный фильтр чрезвычайно просто. Следует лишь поместить ProgressMonitorInputStream в состав последовательности используемых потоков.

Предположим, например, что вам требуется читать текст из файла. Формирование последовательности начинается с потока FileInputStream:

FileInputStream in = new FileInputStream(f);

Обычно этот поток преобразуют в InputStreamReader:

InputStreamReader reader = new InputStreamReader(in);

Если же вы хотите отслеживать чтение данных из потока, нужно сначала преобразовать FileInputStream в ProgressMonitorInputStream:

ProgressMonitorInputStream = progressIn = new ProgressMonitorInputStream(parent, caption, in);

Конструктору ProgressMonitorInputStream передается родительский компонент, заголовок и, конечно же, поток, предназначенный для отслеживания. Метод read() данного класса анализирует количество прочитанных байтов и обновляет содержимое диалогового окна.

Создав объект ProgressMonitorInputStream, можно продолжить формирование последовательности потоков:

InputStreamReader reader = new InputStreamReader(profressIn);

На этом действия по организации мониторинга чтения данных заканчивается. При чтении из файла автоматически отобразится окно, показанное на рис.2.

Отслеживание чтения данных из потока JavaРис.2. Окно, позволяющее отслеживать процесс чтения данных из потока ввода.

Для определения общего количества байтов в потоке объект ProgressMonitorInputStream использует метод available() класса InputStream. Однако этот метод возвращает лишь число байтов, которые могут быть прочитаны без блокировки ввода. Таким образом, рассматриваемый здесь фильтр хорошо работает с файлами и данными, получаемыми посредством протокола HTTP, поскольку их размер известен заранее, однако следует помнить, что результаты его применения к другим потокам могут быть гораздо хуже.

Программа, код который увидите в конце урока, подсчитывает строки в файле. Если размеры файла велики, отображается диалоговое окно, отображающее ход выполнения задачи.

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

Обратите внимание, что в данном примере использован не самый эффективный способ заполнения текстовой области. Программа работала бы гораздо быстрее, если бы мы сначала прочитали файл в StringBuilder, а затем связали текстовую область с контекстом.

Однако в данном случае медленное выполнение программы является преимуществом, так как главная задача примера - продемонстрировать индикацию хода выполнения задачи.

Чтобы избежать мерцания, мы не отображаем текстовую область до ее заполнения.

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;

/**
 * ,   
 *    .
 * @author pro-java.ru
 */
public class ProgressMonitorInputStreamTest {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                TextFrame frame = new TextFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
            }
        });
    }

}
/**
 * ,  ,   
 *    ,   ,
 *     .
 *       
 *       
 *   .   
 *     .
 */
class TextFrame extends JFrame
{
    public TextFrame()
    {
        setTitle("ProgressMonitorInputStreamTest");
        setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
        
        textArea = new JTextArea();
        add(new JScrollPane(textArea));
        
        chooser = new JFileChooser();
        chooser.setCurrentDirectory(new File("."));
        
        JMenuBar menuBar = new JMenuBar();
        setJMenuBar(menuBar);
        JMenu fileMenu = new JMenu("File");
        menuBar.add(fileMenu);
        openItem = new JMenuItem("Open");
        openItem.addActionListener(new ActionListener() {
            
            public void actionPerformed(ActionEvent event) {
                try
                {
                    openFile();
                }
                catch(IOException exception)
                {
                    exception.printStackTrace();
                }
            }
        });
        fileMenu.add(openItem);
        exitItem = new JMenuItem("Exit");
        exitItem.addActionListener(new ActionListener() {
            
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
        fileMenu.add(exitItem);
    }
    
    /**
     *    ,    
     *       
     *   .
     */
    
    public void openFile() throws IOException
    {
        int r = chooser.showOpenDialog(this);
        if(r != JFileChooser.APPROVE_OPTION) return;
        final File f = chooser.getSelectedFile();
        
        //   
        //     .
        
        FileInputStream fileIn = new FileInputStream(f);
        ProgressMonitorInputStream progressIn = new ProgressMonitorInputStream(this, "Reading " + f.getName(), fileIn);
        final Scanner in = new Scanner(progressIn);
        
        textArea.setText("");
        
        SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>()
                {
            protected Void doInBackground() throws Exception
            {
                while(in.hasNextLine())
                {
                    String line = in.nextLine();
                    textArea.append(line);
                    textArea.append("\n");
                }
                in.close();
                return null;
            }
                };
                worker.execute();
    }
    private JMenuItem openItem;
    private JMenuItem exitItem;
    private JTextArea textArea;
    private JFileChooser chooser;
    
    public static final int DEFAULT_WIDTH = 300;
    public static final int DEFAULT_HEIGHT = 200;
}

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *