Search code examples
javasocketsprogressmonitor

ProgressMonitorInputStream in Socket Programming


I have a socket connected client and server. I tried to implement progressMonitorInputStream() to server, the data is transferred perfectly but the Progress Monitor is not visible. I tried implementing it for reading from a file only one side, there the progress monitor works fine. Below are both codes

Server:

    public class Server implements ActionListener, PropertyChangeListener {

    DataInputStream dis;
    ProgressMonitor pm;
    ProgressMonitorInputStream pmis;
    JFrame frm;
    Server s;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {

                new Server().createAndShowUI();
            }
        });
    }

    private void createAndShowUI() {
        frm = new JFrame();
        JPanel panel = new JPanel();

        JButton st = new JButton("Start");

        st.setPreferredSize(new Dimension(80, 25));

        panel.add(st);

        panel.setSize(500, 50);

        frm.add(panel);
        frm.setLocationRelativeTo(null);
        frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frm.pack();
        frm.show();

        st.addActionListener(this);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        frm.dispose();
        try {
            ServerSocket ss = new ServerSocket(5555);
            Socket soc = ss.accept();
            dis = new DataInputStream(soc.getInputStream());
            pmis = new ProgressMonitorInputStream(frm, "Progress", dis);
            pm = pmis.getProgressMonitor();
//            pm.setMillisToPopup(1);
            Task task = new Task();
            task.addPropertyChangeListener(s);
            task.execute();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if ("progress".equals(evt.getPropertyName())) {
            int progress = (Integer) evt.getNewValue();
            pm.setProgress(progress);

        }
    }

    class Task extends SwingWorker<Void, Void> {

        @Override
        protected Void doInBackground() throws Exception {
            int progress = 0;
            setProgress(0);
            int x;
            while ((x = pmis.read()) != -1) {
                System.out.print((char) x);
                setProgress(progress);
                progress++;                
            }
            pmis.close();
            return null;
        }

        @Override
        public void done() {
            pm.close();
        }        

    }
}

The above code is the problematic one. The working code is below:

Proper working code with File Input Stream on one side

    public class ProgressMonitorOwn implements ActionListener,
        PropertyChangeListener {

    JFrame frm;
    Task task;
    DataInputStream dis;
    ProgressMonitorInputStream pmis;
    JButton but;
    ProgressMonitor pm;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ProgressMonitorOwn().createAndShowUI();
            }
        });
    }

    private void createAndShowUI() {
        frm = new JFrame();
        JPanel panel = new JPanel();
        but = new JButton("Show");
        but.setPreferredSize(new Dimension(100, 25));

        panel.add(but);
        panel.setSize(200, 100);

        frm.add(panel);
        frm.setSize(200, 100);
        frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frm.setLocationRelativeTo(null);
        frm.show();
        but.addActionListener(this);
    }

    class Task extends SwingWorker<Void, Void> {

        @Override
        protected Void doInBackground() throws Exception {
            int x;
            int prog = 0;
            while ((x = pmis.read()) != -1) {
                System.out.print((char) x);
                setProgress(prog);
                Thread.sleep(100);
                prog++;
            }
            return null;

        }

        @Override
        public void done() {
            but.setEnabled(true);
            pm.close();
            System.exit(0);
        }

    }

    @Override
    public void actionPerformed(ActionEvent e) {

        but.setEnabled(false);
        try {
            FileInputStream fis = new FileInputStream("D:\\test\\test.txt");
            dis = new DataInputStream(fis);
            pmis = new ProgressMonitorInputStream(frm, "ProgressTest", dis);
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        }
        task = new Task();
        task.addPropertyChangeListener(this);
        task.execute();
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if ("progress" .equals(evt.getPropertyName())) {
            int progress = (Integer) evt.getNewValue();
            pm = pmis.getProgressMonitor();
            pm.setProgress(progress);
        }
    }
}

I am not able to figure out why Progress Monitor is displayed in FileInputStream Program but not on socket program. Any ideas?


Solution

  • You need to call setMaximum() on the ProgressMonitor of the ProgressMonitorInputStream to the expected size of the download. Otherwise it doesn't know what 'progress' means.

    You don't have to call setProgress() with a ProgressMonitorInputStream. It does that automatically.

    You don't need the DataInputStream.

    You should read more than a byte at a time. Read into a byte[] buffer.