/*==========================================================================*\
| $Id: IOHelper.java,v 1.3 2011/06/09 15:30:25 stedwar2 Exp $
|*-------------------------------------------------------------------------*|
| Copyright (C) 2007-2010 Virginia Tech
|
| This file is part of the Student-Library.
|
| The Student-Library is free software; you can redistribute it and/or
| modify it under the terms of the GNU Lesser General Public License as
| published by the Free Software Foundation; either version 3 of the
| License, or (at your option) any later version.
|
| The Student-Library is distributed in the hope that it will be useful,
| but WITHOUT ANY WARRANTY; without even the implied warranty of
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
| GNU Lesser General Public License for more details.
|
| You should have received a copy of the GNU Lesser General Public License
| along with the Student-Library; if not, see <http://www.gnu.org/licenses/>.
\*==========================================================================*/
package student;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Scanner;
// -------------------------------------------------------------------------
/**
* This class provides several static methods that streamline the use of
* basic I/O operations in Java.
*
* It is designed to work seamlessly within the BlueJ environment, but
* is equally applicable in any other IDE or for standaline applications.
* It is designed to make it simple to use {@link Scanner} and
* {@link PrintWriter} for basic input and string-based output.
* <p>
* This class is based on Petr Skoda's "Beginner's IOHelper for BlueJ"
* (@href{http://www.rdv.vslib.cz/skodak}).
* </p>
* @author Stephen Edwards (based on Petr Skoda's original)
* @author Last changed by $Author: stedwar2 $
* @version $Revision: 1.3 $, $Date: 2011/06/09 15:30:25 $
*/
public class IOHelper
{
//~ Instance/static variables .............................................
private static File cwd; // current working directory
//~ Initializers ..........................................................
static
{
Object obj = new Object() { /* empty */ };
if ( obj.getClass().getClassLoader().toString().startsWith( "bluej" ) )
{
String className = obj.getClass().getName();
String classFileName = className.substring(
className.lastIndexOf( '.' ) + 1 )
+ ".class";
File classFile = new File( obj.getClass().getResource(
classFileName ).getFile() );
File projectDir = classFile.getParentFile();
int i = className.indexOf( '.', 0 );
while ( i >= 0 )
{
projectDir = projectDir.getParentFile();
i = className.indexOf( '.', i + 1 );
}
cwd = projectDir;
}
else if (System.getProperty("catalina.home") != null)
{
cwd = new File( System.getProperty("catalina.home"),
"/webapps/"
+ System.getProperty("IOHelper.servlet.name", "zk" ) );
}
else
{
cwd = new File( System.getProperty( "user.dir" ) );
}
}
//~ Constructors ..........................................................
// ----------------------------------------------------------
/**
* Creates a new IOHelper object.
*/
private IOHelper()
{
// Nothing to do
}
//~ Methods ...............................................................
// ----------------------------------------------------------
/**
* Returns current working directory.
* In BlueJ, the currect directory is undefined and can not be set,
* so the directory of the current project is returned instead.
*
* @return current working directory
*/
public static File getCurrentWorkingDirectory()
{
return cwd;
}
// ----------------------------------------------------------
/**
* Changes the current working directory (for the purposes of future
* calls to IOHelper methods). This doesn't actually change the JVM
* process' notion of the current working directory, but does change
* the directory that other methods in this class use for locating all
* relative path names.
* @param newCwd The new current working directory
*/
public static void setCurrentWorkingDirectory(File newCwd)
{
assert newCwd != null : "current working directory cannot be null";
assert newCwd.exists() : "current working directory must exist";
cwd = newCwd;
}
// ----------------------------------------------------------
/**
* Creates a new {@link File} instance from a relative or an absolute
* pathname.
* If given a relative path, it is resolved against the current
* working directory. In BlueJ, the directory of the current project
* is used as the working directory for resolving relative paths.
* Absolute path names are left unaltered.
*
* @param pathname a relative or absolute pathname
* @return instance of {@link File} referring to the
* specified path
*/
public static File getFile( String pathname )
{
File child = new File( pathname );
if ( child.isAbsolute() )
{
return child;
}
else
{
return new File( cwd, pathname );
}
}
// ----------------------------------------------------------
/**
* Takes an existing file and, if it contains a relative path name,
* it is resolved against the current working directory. In BlueJ,
* the directory of the current project is used as the working
* directory for resolving relative paths. Absolute path names are left
* unaltered.
*
* @param pathname a relative or absolute pathname as a File object
* @return instance of {@link File} referring to the
* specified path
*/
public static File getFile( File pathname )
{
if ( pathname.isAbsolute() )
{
return pathname;
}
else
{
return new File( cwd, pathname.getPath() );
}
}
// ----------------------------------------------------------
/**
* Creates and returns an instance of {@link BufferedReader} that
* can be used to read from the keyboard.
* To enter text, you usually have to switch to some console in your
* IDE. Also, remember not to close the keyboard reader. The {@link
* BufferedReader#readLine()} method blocks until the user hits enter.
* <p>
* This method is provided to support older code, but writers of newer
* code should consider {@link #createKeyboardScanner()} instead.
* </p>
* @return instance of {@link BufferedReader} for reading from keyboard
*/
public static BufferedReader createKeyboardReader()
{
return new BufferedReader( new InputStreamReader( System.in ) );
}
// ----------------------------------------------------------
/**
* Creates and returns a {@link Scanner} that
* can be used to read from the keyboard. This is just a convenience
* method for uniformity, since the Scanner class provides a constructor
* that can take {@link System#in} as a parameter.
* To enter text, you usually have to switch to some console in your
* IDE. Also, remember not to close the keyboard scanner. The {@link
* Scanner#nextLine()} method blocks until the user hits enter.
*
* @return instance of {@link Scanner} for reading from keyboard
*/
public static Scanner createKeyboardScanner()
{
return new Scanner( System.in );
}
// ----------------------------------------------------------
/**
* Creates an instance of {@link BufferedReader} that can be used
* to read from the given file.
* <p>
* This method is provided to support older code, but writers of newer
* code should consider {@link #createScanner(File)} instead.
* </p>
*
* @param file the file to read from
* @return instance of {@link BufferedReader} for reading from
* the file
* @throws RuntimeException if there is an error opening the file
*/
public static BufferedReader createBufferedReader( File file )
{
try
{
return new BufferedReader( new java.io.FileReader( file ) );
}
catch ( IOException e )
{
throw new RuntimeException( e );
}
}
// ----------------------------------------------------------
/**
* Creates a {@link Scanner} that can be used
* to read from the given file. This is just a convenience
* method for uniformity, since the Scanner class provides a constructor
* that can take {@link System#in} as a parameter.
* Turns any {@link IOException} that is raised into a
* {@link RuntimeException} so that it does not have to be
* placed inside a try/catch block.
*
* @param file the file to read from
* @return instance of {@link Scanner} for reading from
* the file
*/
public static Scanner createScanner( File file )
{
try
{
return new Scanner( file );
}
catch ( IOException e )
{
throw new RuntimeException( e );
}
}
// ----------------------------------------------------------
/**
* Creates an instance of {@link BufferedReader} that can be used to
* read from the file referred to by the given name.
* <p>
* This method is provided to support older code, but writers of newer
* code should consider {@link #createScanner(String)} instead.
* </p>
* @param pathname a relative or absolute pathname indicating the
* file to read from
* @return instance of {@link BufferedReader} for reading from
* the named file
* @throws RuntimeException if there is an error opening the file
*/
public static BufferedReader createBufferedReader( String pathname )
{
return createBufferedReader( getFile( pathname ) );
}
// ----------------------------------------------------------
/**
* Creates a {@link Scanner} that can be used to
* read from the file referred to by the given name.
* Turns any {@link IOException} that is raised into a
* {@link RuntimeException} so that it does not have to be
* placed inside a try/catch block.
*
* @param pathname a relative or absolute pathname indicating the
* file to read from
* @return instance of {@link Scanner} for reading from
* the named file
*/
public static Scanner createScanner( String pathname )
{
return createScanner( getFile( pathname ) );
}
// ----------------------------------------------------------
/**
* Creates an instance of {@link BufferedReader} that can be used
* to read from a URL over the net.
* <p>
* This method is provided to support older code, but writers of newer
* code should consider {@link #createScanner(URL)} instead.
* </p>
* @param url the URL to read from
* @return instance of {@link BufferedReader} for reading from
* the URL
* @throws RuntimeException if there is an error opening the URL
*/
public static BufferedReader createBufferedReader( URL url )
{
try
{
return new BufferedReader(
new InputStreamReader( url.openStream() ) );
}
catch ( IOException e )
{
throw new RuntimeException( e );
}
}
// ----------------------------------------------------------
/**
* Creates a {@link Scanner} that can be used
* to read from a URL over the net.
* Turns any {@link IOException} that is raised into a
* {@link RuntimeException} so that it does not have to be
* placed inside a try/catch block.
*
* @param url the URL to read from
* @return instance of {@link Scanner} for reading from
* the URL
*/
public static Scanner createScanner( URL url )
{
try
{
java.net.URLConnection connection = url.openConnection();
// Use a browser-like user agent, so that servers that
// refuse connections from generic programs might still
// provide a useful response
connection.setRequestProperty("User-Agent", USER_AGENT);
return new Scanner( connection.getInputStream() );
}
catch ( IOException e )
{
throw new RuntimeException( e );
}
}
// ----------------------------------------------------------
/**
* Creates an instance of {@link BufferedReader} that can be used to
* read from a URL given as a text string.
* <p>
* This method is provided to support older code, but writers of newer
* code should consider {@link #createScannerForURL(String)} instead.
* </p>
* @param url a string denoting a URL to read from
* @return instance of {@link BufferedReader} for reading from
* the given URL
* @throws RuntimeException if there is an error opening the URL or the
* URL is syntactically incorrect
*/
public static BufferedReader createBufferedReaderForURL( String url )
{
try
{
return createBufferedReader( new URL( url ) );
}
catch ( IOException e )
{
throw new RuntimeException( e );
}
}
// ----------------------------------------------------------
/**
* Creates a {@link Scanner} that can be used to
* read from a URL given as a text string.
* Turns any {@link MalformedURLException} or other {@link IOException}
* that is raised into a {@link RuntimeException} so that it does not
* have to be placed inside a try/catch block.
*
* @param url a string denoting a URL to read from
* @return instance of {@link Scanner} for reading from
* the given URL
*/
public static Scanner createScannerForURL( String url )
{
try
{
return createScanner( new URL( url ) );
}
catch ( IOException e )
{
throw new RuntimeException( e );
}
}
// ----------------------------------------------------------
/**
* Creates an instance of {@link BufferedReader} that can be used to
* read directly from a given text string.
* <p>
* This method is provided to support older code, but writers of newer
* code should consider {@link #createScannerForString(String)} instead.
* </p>
* @param s the string to read from
* @return instance of {@link BufferedReader} for reading from
* the given string
*/
public static BufferedReader createBufferedReaderForString( String s )
{
return new BufferedReader( new StringReader( s ) );
}
// ----------------------------------------------------------
/**
* Creates a {@link Scanner} that can be used to
* read directly from a given text string. This is just a convenience
* method for uniformity, since the Scanner class provides a constructor
* that can take a String as a parameter.
*
* @param s the string to read from
* @return instance of {@link Scanner} for reading from
* the given string
*/
public static Scanner createScannerForString( String s )
{
return new Scanner( s );
}
// ----------------------------------------------------------
/**
* Creates and returns an instance of {@link PrintWriter} that
* can be used to write to the console.
* Normally, {@link System#out} is easy enough to use for basic
* information. However, this method makes it easier to write
* I/O-based classes that use {@link PrintWriter} in their interface,
* but are still capable of writing to the screen as well as to a
* file.
*
* @return instance of {@link PrintWriter} for writing to the console
*/
public static PrintWriter createConsoleWriter()
{
return new PrintWriter( System.out, true );
}
// ----------------------------------------------------------
/**
* Creates an instance of {@link PrintWriter} that can be used to
* write to the given file.
* If the file does not exist, it will be created if possible
* (including any necessary parent directories that do not exist).
*
* @param file the file to write to
* @param append true means preserve any existing file contents and
* start write at the end of the current file, while false
* means to delete any existing content first and start
* writing from scratch.
* @return instance of {@link PrintWriter} for writing to the
* given file
*/
public static PrintWriter createPrintWriter( File file, boolean append )
{
try
{
File parent = file.getParentFile();
if ( !parent.exists() )
{
parent.mkdirs();
}
return new PrintWriter(
new java.io.FileOutputStream( file, append ), true );
}
catch ( IOException e )
{
throw new RuntimeException( e );
}
}
// ----------------------------------------------------------
/**
* Creates an instance of {@link PrintWriter} that can be used to
* write to the file referred to by the given name.
* If the file does not exist, it will be created if possible
* (including any necessary parent directories that do not exist).
*
* @param pathname a relative or absolute pathname indicating the file
* to write to
* @param append true means preserve any existing file contents and
* start write at the end of the current file, while false
* means to delete any existing content first and start
* writing from scratch.
* @return instance of {@link PrintWriter} for writing to the
* given file
*/
public static PrintWriter createPrintWriter( String pathname,
boolean append )
{
return createPrintWriter( getFile( pathname ), append );
}
// ----------------------------------------------------------
/**
* Creates an instance of {@link PrintWriter} that can be used to
* write to the file referred to by the given name.
* If the file does not exist, it will be created if possible
* (including any necessary parent directories that do not exist).
* If the file does exist, it will be overwritten.
*
* @param pathname a relative or absolute pathname indicating the file
* to write to
* @return instance of {@link PrintWriter} for writing to the
* given file
*/
public static PrintWriter createPrintWriter( String pathname )
{
return createPrintWriter( getFile( pathname ), false );
}
//~ Instance/static variables .............................................
private static final String USER_AGENT =
"Mozilla/4.0 (compatible; MSIE 6.0; Windows 2000)";
}