/*
* [FileIO.java]
*
* Summary: File I/O Amanuensis. Generates sample I/O code for Java novices.
*
* Copyright: (c) 1997-2017 Roedy Green, Canadian Mind Products, http://mindprod.com
*
* Licence: This software may be copied and used freely for any purpose but military.
* http://mindprod.com/contact/nonmil.html
*
* Requires: JDK 1.8+
*
* Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/
*
* Version History:
* 1.0 1997-12-17
* 1.1 1997-12-22 uses layouts
* generates BufferedReader.ReadLine()
* 1.2 1998-01-02 handles URLConnection
* handle append
* handle autoflush
* handle buffered on all types
* 1.3 1998-01-03 internal reorganisation
* O P E N comments
* consistent short variable naming conventions.
* StringBuilder renamed to String
* Buffered now applies to all file types
* RandomAccessFile
* 1.4 1998-01-04 make into both application and applet
* change reference to LEDataInputStream
* 1.5 1998-01-08 warnings about applets and writing URLs.
* 1.6 1998-01-09 reference to availability of LERandomAccessFile
* change way LERandomAccess constructor works
* 1.7 1998-01-12 add Sockets
* remove connect out URL output. -
* simplify interface to HowToProcess by making all methods static.
* 1.8 1998-01-13 add Pipes
* 1.9 1998-01-13 minor changes on how buffered handled
* fix erroneous deprecated comment.
* add readLine to more places.
* 2.0 1998-01-17 GZIPOutputStream support
* 2.1 1998-01-20 code to analyse a URL
* code to flush
* 2.2 1998-03-22 add ByteArrayInputStream ByteArrayOutputStream.
* redo code to check for supported cases.
* expectExceptions
* expectExceptionOnFlush expectExceptionOnClose computed as you go rather than
* trying to figure it out all in once place.
* 2.3 1998-04-13 single character read for BufferedReader.
* 2.4 1998-05-08 no url connect() on output.
* Activator HTML
* Compile on Symantec VC 2.5
* SlickEdit code tidy
* 2.5 1998-06-24 add Javadoc.
* 2.6 1998-11-10 new address and phone.
* 2.7 1998-12-14 switch to jar file.
* use new colour scheme.
* check JVM version
* 2.8 1998-12-28 add sample HTML and BAT file.
* 2.9 1999-09-02 URLConnection.getContentLength
* 3.0 1999-09-03 warning about URL uploads.
* put connect back
* harmless if already connected.
* 3.1 1999-09-07 read/write get/post HTTP CGI
* 3.2 1999-10-08 support for encoding
* 3.3 1999-10-12 references to where to get ledatastream and
* FileTransfer
* 3.4 1999-10-21 warning about Netscape
* 3.5 1999-10-22 stronger warning about Netscape
* 3.6 2001-02-05 warning about readLine demanding a final \n
* 3.7 2001-03-07 better fileio.use file.
* 3.8 2002-02-15 use of .finish in compression.
* rename variables to better fit Sun conventions.
* variable Source/Target label
* that tracks read/write. label "Data Type"
* 3.9 2002-02-20 warning on pipes they are for inter-thread
* communication only.
* 4.0 2002-04-04 package name now lower case
* fitting Sun conventions
* 4.1 2002-04-19 replace term ASCII with accurate wordings
* throughout.
* autoflush for pipes and sockets. - rename all datatypes
* for greater clarity.
* 4.2 2003-05-19 better spacing.
* Notes about Serialisation.
* notes about -1 bytesRead means EOF.
* 4.3 2003-05-26 note about missing readLine method in unbuffered
* Readers.
* 4.4 2003-05-27 Dropped all Exception catching for simplicity.
* Redid code using StringBuilders instead of concatenation.
* use of readEverything for HttpURLConnections.
* 4.5 2004-05-04 add HEAD and turn off keep-alive
* 4.6 2004-06-09 warnings about read not giving all bytes/chars you ask
* for in one go.
* add version check safety add about box tidier add code.
* 4.7 2004-07-21 use UTF-8 instead of Cp437 as example encoding.
* 4.8 2005-06-24 notes on safety of bad line separators in Reader files.
* parameterised RELEASE_DATE.
* 4.9 2005-11-30 add User-Agent and setRequestMethod to URL GET
* 5.0 2006-01-04 add warnings about readUTF and writeUTF.
* 5.1 2006-03-05
* 5.2 2007-07-12 add reference to com.mindprod.http package.
* convert to JDK 1.5 and Swing
* use of enum
* pass IntelliJ inspector.
* 5.3 2007-07-19 notes in GET/POST about HTTPClient, changed ordering.
* 5.4 2007-07-27 correct code generated for URL read, and PIPE write.
* 5.5 2007-08-05 major rewrite. refactor, simplify, make code more orthogonal,
* generate code for more cases, timeouts.
* 5.6 2007-08-24 notes on where to get source for readBytesBlocking.
* 5.7 2008-04-02 add build number to title
* 5.8 2009-12-21 use keyword final as much as possible in generated code.
* 5.9 2010-02-21 use of FastCat instead of StringBuilder. Generate code to use Aux buffering for Readers and Writers.
* 6.0 2010-12-06 support getResourceAsStream, FileReader, FileWriter.
* 6.1 2011-12-03 configurable Look and Feel
* 6.2 2014-05-10 optimal buffering ratios
*/
package com.mindprod.fileio;
import com.mindprod.common18.Build;
import com.mindprod.common18.CMPAboutJBox;
import com.mindprod.common18.FontFactory;
import com.mindprod.common18.HybridJ;
import com.mindprod.common18.Laf;
import com.mindprod.common18.VersionCheck;
import javax.swing.ButtonGroup;
import javax.swing.JApplet;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Label;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
/**
* File I/O Amanuensis. Generates sample I/O code for Java novices.
*
*
* @author Roedy Green, Canadian Mind Products
* @version 6.2 2014-05-10 optimal buffering ratios
* @noinspection FieldCanBeLocal
* @since 1997-12-17
*/
public final class FileIO extends JApplet
{
/**
* if true, will generate file E:\com\mindprod\fileio\Test.java so can test compile all possible outputs.
*/
static final boolean DEBUGGING = false;
/**
* height of Applet box in pixels. Does not include surrounding frame.
*/
private static final int APPLET_HEIGHT = 696;
/**
* Width of Applet box in pixels.
*/
private static final int APPLET_WIDTH = 646;
private static final int FIRST_COPYRIGHT_YEAR = 1997;
/**
* undisplayed copyright notice
*
* @noinspection UnusedDeclaration
*/
private static final String EMBEDDED_COPYRIGHT =
"Copyright: (c) 1997-2017 Roedy Green, Canadian Mind Products, http://mindprod.com";
/* date this version released */
private static final String RELEASE_DATE = "2014-05-10";
private static final String TITLE_STRING = "File I/O Amanuensis";
private static final String VERSION_STRING = "6.2";
/**
* pale apricot background
*/
private static final Color BACKGROUND_FOR_APPLET = new Color( 0xfae5b7 );
/**
* instructions
*/
private static final Color FOREGROUND_FOR_INSTRUCTIONS = new Color( 0x008000 );
/**
* text for labels
*/
private static final Color FOREGROUND_FOR_LABEL = new Color( 0x0000b0 );
/**
* usual text
*/
private static final Color FOREGROUND_FOR_RESULTS = Color.BLACK;
/**
* for titles
*/
private static final Color FOREGROUND_FOR_TITLE = new Color( 0xdc143c );
/**
* font for labels
*/
private static final Font FONT_FOR_LABEL = FontFactory.build( "Dialog", Font.BOLD, 15 );
/**
* font to display generated code
*/
private static final Font FONT_FOR_RESULTS = FontFactory.build( "Dialog", Font.PLAIN, 13 );
/**
* for for titles and About buttons
*/
private static final Font FONT_FOR_TITLE = FontFactory.build( "Dialog", Font.BOLD, 16 );
/**
* for for title second line
*/
private static final Font FONT_FOR_TITLE2 = FontFactory.build( "Dialog", Font.PLAIN, 14 );
/**
* the buffer/compressed CheckBoxes
*/
private ButtonGroup bufferCheckBoxes;
/**
* the read/write buttons.
*/
private ButtonGroup readWriteCheckBoxes;
/**
* radio button to select buffered file io
*/
private JCheckBox bufferedButton;
/**
* radio button to select compressed file io.
*/
private JCheckBox compressedButton;
/**
* radiobutton to select that you want file input code generated.
*/
private JCheckBox readButton;
/**
* radio button to select unbuffered file io.
*/
private JCheckBox unbufferedButton;
/**
* radio button to select that you want output code generated.
*/
private JCheckBox writeButton;
/**
* Multiple choice: which type of data is in your file.
*/
private JComboBox data;
/**
* Multiple choice: which type of "file" are you doing I/O to.
*/
private JComboBox sourceTarget;
/**
* label "data"
*/
private JLabel dataLabel;
/**
* Label "file"
*/
private JLabel fileSourceTargetLabel;
/**
* label suggestions to use cut/paste.
*/
private JLabel instructions;
/**
* Title and version for the applet.
*/
private JLabel title;
/**
* title, second line
*/
private JLabel title2;
/**
* allow generated sample code to scroll
*/
private JScrollPane howToScroller;
/**
* scrollable text area to contain the generated sample Java source code.
*/
private JTextArea howTo;
private void buildComponents()
{
title = new JLabel( TITLE_STRING + " " + VERSION_STRING );
title.setFont( FONT_FOR_TITLE );
title.setForeground( FOREGROUND_FOR_TITLE );
title2 = new JLabel(
"released:" +
RELEASE_DATE +
" build:" +
Build.BUILD_NUMBER
);
title2.setFont( FONT_FOR_TITLE2 );
title2.setForeground( FOREGROUND_FOR_TITLE );
/* variable Source/Target depending on read/write button. */
fileSourceTargetLabel = new JLabel( "Source" );
fileSourceTargetLabel.setFont( FONT_FOR_LABEL );
fileSourceTargetLabel.setForeground( FOREGROUND_FOR_LABEL );
sourceTarget = new JComboBox<>( FileType.values() );
sourceTarget.setSelectedItem( FileType.SEQUENTIAL );
dataLabel = new JLabel( "Data FormatPadSites", Label.RIGHT );
dataLabel.setFont( FONT_FOR_LABEL );
dataLabel.setForeground( FOREGROUND_FOR_LABEL );
data = new JComboBox<>( DataType.values() );
data.setSelectedItem( DataType.BIGEND );
readButton = new JCheckBox( "read", true );
readButton.setForeground( FOREGROUND_FOR_LABEL );
readButton.setBackground( BACKGROUND_FOR_APPLET );
writeButton = new JCheckBox( "write", false );
writeButton.setForeground( FOREGROUND_FOR_LABEL );
writeButton.setBackground( BACKGROUND_FOR_APPLET );
readWriteCheckBoxes = new ButtonGroup();
readWriteCheckBoxes.add( readButton );
readWriteCheckBoxes.add( writeButton );
unbufferedButton = new JCheckBox( "unbuffered", true );
unbufferedButton.setForeground( FOREGROUND_FOR_LABEL );
unbufferedButton.setBackground( BACKGROUND_FOR_APPLET );
bufferedButton = new JCheckBox( "buffered", false );
bufferedButton.setForeground( FOREGROUND_FOR_LABEL );
bufferedButton.setBackground( BACKGROUND_FOR_APPLET );
compressedButton = new JCheckBox( "compressed", false );
compressedButton.setForeground( FOREGROUND_FOR_LABEL );
compressedButton.setBackground( BACKGROUND_FOR_APPLET );
bufferCheckBoxes = new ButtonGroup();
bufferCheckBoxes.add( unbufferedButton );
bufferCheckBoxes.add( bufferedButton );
bufferCheckBoxes.add( compressedButton );
howTo = new JTextArea( How.how( FileType.SEQUENTIAL,
DataType.BIGEND,
true
/* input */,
false
/* buffered */,
false
/* compressed */ ), 40, 0 );
howTo.setEditable( false );
howTo.setFont( FONT_FOR_RESULTS );
howTo.setForeground( FOREGROUND_FOR_RESULTS );
howTo.setMargin( new Insets( 5, 5, 5, 5 ) );
howToScroller =
new JScrollPane( howTo,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED );
instructions =
new JLabel( "Cut and Paste results into your own code.",
JLabel.CENTER );
instructions.setForeground( FOREGROUND_FOR_INSTRUCTIONS );
}
/**
* build a menu with Look & Feel and About across the top
*/
private void buildMenu()
{
// turn on anti-alias
System.setProperty( "swing.aatext", "true" );
final JMenuBar menubar = new JMenuBar();
setJMenuBar( menubar );
final JMenu lafMenu = Laf.buildLookAndFeelMenu();
if ( lafMenu != null )
{
menubar.add( lafMenu );
}
final JMenu menuHelp = new JMenu( "Help" );
menubar.add( menuHelp );
final JMenuItem aboutItem = new JMenuItem( "About" );
menuHelp.add( aboutItem );
aboutItem.addActionListener( new ActionListener()
{
public void actionPerformed( ActionEvent e )
{
// open about frame
new CMPAboutJBox( TITLE_STRING,
VERSION_STRING,
"Generates Java source to do I/Os,",
"e.g. code for files, socket, CGI, pipes and in-RAM I/O.",
"freeware",
RELEASE_DATE,
FIRST_COPYRIGHT_YEAR,
"Roedy Green",
"FILEIO",
"1.8" );
}
} );
}
/**
* register listeners
*/
private void hookListeners()
{
// REGISTER_LISTENERS
TheListener theListener = new TheListener();
sourceTarget.addItemListener( theListener );
data.addItemListener( theListener );
readButton.addItemListener( theListener );
writeButton.addItemListener( theListener );
unbufferedButton.addItemListener( theListener );
bufferedButton.addItemListener( theListener );
compressedButton.addItemListener( theListener );
}
/**
* layout components in a GridBag
*
* @param contentPane contentPane of JApplet
*/
private void layoutComponents( Container contentPane )
{
/**
* layout
* --- 0 -----1------- 2 -------------3------
* 0--title ----------------------- -title2- 0
* 2 "source" * read unbuffered "dataformat" 2
* 3 source write buffered dataformat------- 3
* 4 * compressed ----------------- 4
* 5 ------------- how---------------------- 5
* 6 ------------- instructions ----------- 6
* --- 0 -----1------- 2 ----------------3----
*/
// x y w h wtx wty anchor fill T L B R padx pady
contentPane.add( title,
new GridBagConstraints( 0,
0,
3,
1,
0.0,
0.0,
GridBagConstraints.WEST,
GridBagConstraints.NONE,
new Insets( 10, 10, 10, 5 ),
0,
0 )
);
contentPane.add( title2,
new GridBagConstraints( 3,
0,
1,
1,
0.0,
0.0,
GridBagConstraints.EAST,
GridBagConstraints.NONE,
new Insets( 10, 5, 10, 10 ),
0,
0 )
);
// x y w h wtx wty anchor fill T L B R padx pady
contentPane.add( fileSourceTargetLabel,
new GridBagConstraints( 0,
2,
1,
1,
0.0,
0.0,
GridBagConstraints.WEST,
GridBagConstraints.NONE,
new Insets( 5, 10, 0, 5 ),
0,
0 )
);
// x y w h wtx wty anchor fill T L B R padx pady
contentPane.add( readButton,
new GridBagConstraints( 1,
2,
1,
1,
0.0,
0.0,
GridBagConstraints.WEST,
GridBagConstraints.NONE,
new Insets( 5, 5, 0, 5 ),
0,
0 )
);
// x y w h wtx wty anchor fill T L B R padx pady
contentPane.add( unbufferedButton,
new GridBagConstraints( 2,
2,
1,
1,
0.0,
0.0,
GridBagConstraints.WEST,
GridBagConstraints.NONE,
new Insets( 5, 5, 0, 5 ),
0,
0 )
);
// x y w h wtx wty anchor fill T L B R padx pady
contentPane.add( dataLabel,
new GridBagConstraints( 3,
2,
1,
1,
0.0,
0.0,
GridBagConstraints.EAST,
GridBagConstraints.NONE,
new Insets( 5, 5, 0, 10 ),
0,
0 )
);
// x y w h wtx wty anchor fill T L B R padx pady
contentPane.add( sourceTarget,
new GridBagConstraints( 0,
3,
1,
1,
0.0,
0.0,
GridBagConstraints.WEST,
GridBagConstraints.NONE,
new Insets( 5, 10, 0, 5 ),
0,
0 )
);
// x y w h wtx wty anchor fill T L B R padx pady
contentPane.add( writeButton,
new GridBagConstraints( 1,
3,
1,
1,
0.0,
0.0,
GridBagConstraints.WEST,
GridBagConstraints.NONE,
new Insets( 5, 5, 0, 5 ),
0,
0 )
);
// x y w h wtx wty anchor fill T L B R padx pady
contentPane.add( bufferedButton,
new GridBagConstraints( 2,
3,
1,
1,
0.0,
0.0,
GridBagConstraints.WEST,
GridBagConstraints.NONE,
new Insets( 5, 5, 0, 5 ),
0,
0 )
);
// x y w h wtx wty anchor fill T L B R padx pady
contentPane.add( data,
new GridBagConstraints( 3,
3,
1,
1,
0.0,
0.0,
GridBagConstraints.EAST,
GridBagConstraints.NONE,
new Insets( 5, 5, 0, 10 ),
0,
0 )
);
// x y w h wtx wty anchor fill T L B R padx pady
contentPane.add( compressedButton,
new GridBagConstraints( 2,
4,
1,
1,
0.0,
0.0,
GridBagConstraints.WEST,
GridBagConstraints.NONE,
new Insets( 5, 5, 0, 5 ),
0,
0 )
);
// x y w h wtx wty anchor fill T L B R padx pady
contentPane.add( howToScroller,
new GridBagConstraints( 0,
5,
4,
1,
1.0,
1.0,
GridBagConstraints.CENTER,
GridBagConstraints.BOTH,
new Insets( 5, 10, 0, 10 ),
0,
0 )
);
// x y w h wtx wty anchor fill T L B R padx pady
contentPane.add( instructions,
new GridBagConstraints( 0,
6,
4,
1,
0.0,
0.0,
GridBagConstraints.CENTER,
GridBagConstraints.NONE,
new Insets( 5, 10, 10, 10 ),
0,
0 )
);
}
/**
* Allow this Applet to run as as application as well.
*
* @param args command line arguments are ignored.
*/
public static void main( String args[] )
{
HybridJ.fireup( new FileIO(),
TITLE_STRING + " " + VERSION_STRING,
APPLET_WIDTH,
APPLET_HEIGHT );
} // end main
/**
* Called by the browser or Applet viewer to inform
* this Applet that it is being reclaimed and that it should destroy
* any resources that it has allocated
*/
@Override
public void destroy()
{
bufferCheckBoxes = null;
bufferedButton = null;
compressedButton = null;
data = null;
dataLabel = null;
fileSourceTargetLabel = null;
howTo = null;
howToScroller = null;
instructions = null;
readButton = null;
readWriteCheckBoxes = null;
sourceTarget = null;
title = null;
title2 = null;
unbufferedButton = null;
writeButton = null;
}
// }}
/**
* Called by the browser or Applet viewer to inform
* this Applet that it has been loaded into the system.
*/
@Override
public void init()
{
if ( !VersionCheck.isJavaVersionOK( 1, 8, 0, this ) )
{
return;
}
buildMenu();
Container contentPane = this.getContentPane();
contentPane.setBackground( BACKGROUND_FOR_APPLET );
contentPane.setLayout( new GridBagLayout() );
buildComponents();
// add components:
layoutComponents( contentPane );
hookListeners();
this.validate();
this.setVisible( true );
} // end init
/**
* Inner class to act as listener for end user actions.
*/
private final class TheListener implements ItemListener
{
/**
* Listen for any actions from the end-user.
*
* @param e details of what end user just clicked.
*/
public void itemStateChanged( ItemEvent e )
{
// It does not matter which control triggered the event, the
// response is the same,
// to recalculate the text of the howTo.
// Make Source/Target appear depending on whether read/write.
fileSourceTargetLabel.setText( readButton.isSelected()
? "Source"
: "Target" );
// get states of controls and generate display:
// HowToProcess will return code to display.
howTo.setText( How.how( ( FileType ) sourceTarget.getSelectedItem(),
/* sourceTarget */
( DataType ) data.getSelectedItem(),
/* dataType */
readButton.isSelected(),
/* input? */
bufferedButton.isSelected(),
/* buffered */
compressedButton.isSelected() ) );/* compressed */
// invoke later to give time for text to render.
SwingUtilities.invokeLater( new Runnable()
{
public void run()
{
final JScrollBar v = howToScroller.getVerticalScrollBar();
v.setValue( v.getMinimum() );
}
} );
} // end itemStateChanged
} // end TheListener
}