Este exemplo pretende demonstrar a utilização de Streams processadas para a escrita de texto e uma utilização simples de streams de memória para a implementação de um sistema de undo/redo. São mostrados apenas os métodos relevantes, podem ver todo o código nos vários ficheiros no fundo da página.
//... public class BlocoNotas extends javax.swing.JFrame { //Guarda o estado do documento para undo e redo private transient ByteArrayOutputStream[] undos; private int indice; private static final int MAX_UNDO = 16; private File ficheiro; public BlocoNotas() { initComponents(); undos = new ByteArrayOutputStream[BlocoNotas.MAX_UNDO]; for (int i = 0; i < BlocoNotas.MAX_UNDO; i++) { undos[i] = new ByteArrayOutputStream(); } indice = -1; } /** * Permite abrir um ficheiro de texto, ler o seu conteúdo e preencher a * JTextArea com o texto. * * @param file Ficheiro a abrir */ private void openDocument(File file) { BufferedReader bf = null; try { bf = new BufferedReader(new FileReader(file)); String linha; StringBuffer buf = new StringBuffer(); while ((linha = bf.readLine()) != null) { buf.append(linha); buf.append("n"); } jtaText.setText(buf.toString()); ficheiro = file; } catch (FileNotFoundException ex) { JOptionPane.showMessageDialog(this, "Não foi possível encontrar o ficheiro " + file.getAbsolutePath(), "Ficheiro não encontrado.", JOptionPane.ERROR_MESSAGE); } catch (IOException ex) { JOptionPane.showMessageDialog(this, "Ocorreu um erro ao tentar ler o conteúdo do ficheiro.", "Erro de leitura.", JOptionPane.ERROR_MESSAGE); } finally { if (bf != null) { try { bf.close(); } catch (IOException ex) { //IGNORE } } } } /** * Permite gravar o conteúdo da JTextArea, num ficheiro já aberto ou num novo * ficheiro se o documento é novo. */ private void saveDocument() { if (ficheiro == null) { JFileChooser jfc = new JFileChooser(); if (jfc.showSaveDialog(this) != JFileChooser.APPROVE_OPTION) { return; } ficheiro = jfc.getSelectedFile(); } BufferedWriter bw = null; try { bw = new BufferedWriter(new FileWriter(ficheiro)); bw.write(jtaText.getText()); } catch (IOException ex) { JOptionPane.showMessageDialog(this, "Ocorreu um erro ao tentar gravar o documento.", "Erro de escrita.", JOptionPane.ERROR_MESSAGE); } finally { if (bw != null) { try { bw.close(); } catch (IOException ex) { //IGNORE } } } } private void undo() { ObjectInputStream is = null; try { is = new ObjectInputStream(new BufferedInputStream(new ByteArrayInputStream(undos[(--indice) % MAX_UNDO].toByteArray()))); String texto = (String) is.readObject(); jtaText.setText(texto); } catch (ClassNotFoundException ex) { //Nunca pode acontecer System.err.println("Não foi possível fazer undo."); System.err.println(ex.getMessage()); } catch (IOException ex) { System.err.println("Não foi possível fazer undo."); System.err.println(ex.getMessage()); } finally { if (is != null) { try { is.close(); } catch (IOException ex) { //IGNORE } } } } private void redo() { ObjectInputStream is = null; try { is = new ObjectInputStream(new BufferedInputStream(new ByteArrayInputStream(undos[(++indice) % MAX_UNDO].toByteArray()))); String texto = (String) is.readObject(); jtaText.setText(texto); } catch (ClassNotFoundException ex) { //Nunca pode acontecer System.err.println("Não foi possível fazer redo."); System.err.println(ex.getMessage()); } catch (IOException ex) { System.err.println("Não foi possível fazer redo."); System.err.println(ex.getMessage()); } finally { if (is != null) { try { is.close(); } catch (IOException ex) { //IGNORE } } } } /** * Guarda o stado no array de estados para undo/redo */ private void store() { ObjectOutputStream os = null; try { undos[(++indice) % MAX_UNDO].reset(); os = new ObjectOutputStream(new BufferedOutputStream(undos[(indice) % MAX_UNDO])); os.writeObject(jtaText.getText()); } catch (IOException ex) { System.err.println("Não foi possível guardar o stado."); System.err.println(ex.getMessage()); } finally { try { if (os != null) { os.close(); } } catch (IOException ex) { //IGNORE } } } //... }