package com.mindprod.example;
import com.mindprod.common18.EIO;
import com.mindprod.hunkio.HunkIO;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.text.DecimalFormat;
import java.util.Random;
import static java.lang.System.*;
/**
* Discover best way te reay an entire file all at once.
*
* @author Roedy Green, Canadian Mind Products
* @version 1.0 2014-05-16 initial version
* @since 2014-05-16
*/
public final class TestReadFileAtOnce
{
/**
* size of line in chars including \n
*/
private static final int LINESIZE = 100;
/**
* how many benchmark trials
*/
private static final int TRIALS = 5;
/**
* size of test file in chars
*/
private static final long FILESIZE = 400L * 1024 * 1024;
/**
* chars we allow in our random data
*/
private static final String ALLOWED = "abcdefghijklmnopqrstuvwxyzABCDEFGHJKMLMOPQRSTUVWXYZ 0123456789 +!@$#$%^&*()_-?/|\\\n";
/**
* character set to use
*/
private static final Charset charset = Charset.forName( "UTF-8" );
/**
* allows us to display seconds to zero decimal places.
*/
private static final DecimalFormat df0 = new DecimalFormat( "###,##0" );
/**
* allows us to display seconds to two decimal places.
*/
private static final DecimalFormat df2 = new DecimalFormat( "###,##0.00" );
/**
* sample date file we read to test
*/
private static File sampleDataFile = null;
/**
* display nanoseconds as seconds to two decimal places.
*
* @param nanoseconds how many nanoseconds ( billionths of a second )
*
* @return displayable String.
*/
private static String asSeconds( double nanoseconds )
{
return df2.format( nanoseconds / 1000000000d ) + " seconds";
}
/**
* generate 100K of sample data in a temporary file.
*/
private static void generateSampleData() throws IOException
{
HunkIO.createTempFile( "temp_", ".tmp", new File( "H:/temp" ) );
sampleDataFile = File.createTempFile( "temp_", ".tmp" );
final Random wheel = new Random();
final BufferedWriter bw = EIO.getBufferedWriter( sampleDataFile, 256 * 1024, charset );
char[] line = new char[ LINESIZE - 1 ];
for ( int i = 0; i < ( FILESIZE / LINESIZE ); i++ )
{
for ( int j = 0; j < line.length; j++ )
{
line[ j ] = ALLOWED.charAt( ( wheel.nextInt() & Integer.MAX_VALUE ) % ALLOWED.length() );
}
bw.write( line );
bw.write( "\n" );
}
bw.close();
}
/**
* Benchmark three ways of buffered writing and three ways of buffered reading.
*
* @param args not used
*
* @throws java.io.IOException if problem writing or reading the test file.
*/
public static void main( String[] args ) throws IOException
{
generateSampleData();
out.println( "Using a random sample data file of "
+ df0.format( FILESIZE )
+ " chars "
+ df0.format( sampleDataFile.length() )
+ " bytes." );
for ( int i = 0; i < TRIALS; i++ )
{
readFileAtOnceWithRandomAccess( sampleDataFile );
readFileAtOnceWithInputStream( sampleDataFile );
readFileAtOnceWithNIO( sampleDataFile );
}
sampleDataFile.delete();
}
/**
* read file of bytes in one I/O and convert to a String using an InputStream
*
* @param fromFile file to read
*
* @throws IOException when cannot access file.
* @noinspection WeakerAccess
*/
public static String readFileAtOnceWithInputStream( File fromFile ) throws IOException
{
final long prevTime = System.nanoTime();
final int size = ( int ) fromFile.length();
final FileInputStream fis = new FileInputStream( fromFile );
final byte[] rawContents = new byte[ size ];
final int bytesRead = fis.read( rawContents );
if ( bytesRead != size )
{
throw new IOException( "error: problems reading InputStream file " + fromFile );
}
fis.close();
final String result = new String( rawContents, charset );
out.println( "InputStream " + asSeconds( System.nanoTime() - prevTime ) );
return result;
}
/**
* read file of bytes in one I/O and convert to a String using NIO
*
* @param fromFile file to read
*
* @return String that was in the file
* @throws IOException when cannot access file.
* @noinspection WeakerAccess
*/
public static String readFileAtOnceWithNIO( File fromFile ) throws IOException
{
final long prevTime = System.nanoTime();
final int size = ( int ) fromFile.length();
final ByteBuffer b = ByteBuffer.allocateDirect( size );
final RandomAccessFile raf = new RandomAccessFile( fromFile, "r" );
final FileChannel fc = raf.getChannel();
fc.read( b );
if ( fc.position() != size )
{
throw new IOException( "error: problems reading NIO file " + fromFile );
}
b.flip();
fc.close();
final byte[] holder = new byte[ size ];
b.get( holder );
final String result = new String( holder, charset );
out.println( "NIO " + asSeconds( System.nanoTime() - prevTime ) );
return result;
}
/**
* read file of bytes in one I/O and convert to a String, using a RAF.
*
* @param fromFile file to read
*
* @return String that was in the file
* @throws IOException when cannot access file.
* @noinspection WeakerAccess
*/
public static String readFileAtOnceWithRandomAccess( File fromFile ) throws IOException
{
final long prevTime = System.nanoTime();
final int size = ( int ) fromFile.length();
final RandomAccessFile raf = new RandomAccessFile( fromFile, "r" );
final byte[] rawContents = new byte[ size ];
final int bytesRead = raf.read( rawContents );
if ( bytesRead != size )
{
throw new IOException( "error: problems reading RandomAccess file " + fromFile );
}
raf.close();
final String result = new String( rawContents, charset );
out.println( "RandomAccess " + asSeconds( System.nanoTime() - prevTime ) );
return result;
}
}