Class FileInputStream in Java

Class FileInputStream in Java

Class FileInputStream in Java

FileInputStream is a child class of InputStream class and is used to manage a  FileInput stream as an input stream for reading data from a File or from a FileDescriptor or from a String that represents the fully qualified pathname. The file depends on the host system.

FileInputStream class uses actual data files as the basis for an input stream. An object of this class represents a text file that can be accessed in sequential order byte by byte. So basically FileInputStream gets the input in the form of raw bytes.

Ads code goes here

FileInputStream provides a low-level interface for reading data from a file. We should wrap a FileInputStream with a DataInputStream if we need a higher-level interface that can handle reading strings and binary data. We should also think about wrapping a FileInputStream with a BufferedInputStream to increase reading efficiency.

Data must be read sequentially from a Class FileInputStream in Java. we can skip forward, but we cannot move back. If we need random access to file data, we need to use the RandomAccessFile class instead.

read() reads a byte or array of bytes from the file. It returns -1 when the end of file has been reached. To read binary data, we typically use this class in conjunction with a BufferedInputStream and DataInputStream.

To read the text, we typically use it with an InputStreamReader and BufferedReader and Call close() to close the file when input is no longer needed.

Usage of Class FileInputStream in Java

Typically FileInputStream is used to read

  • image data.
  • Docs
  • pdf data
  • Audio
  • Video

Class FileInputStream in Java hierarchy

java.lang.Object
—-java.io.InputStream
———–java.io.FileInputStream
FileInputStream has implemented the below interfaces:

  1. Closeable
  2. AutoCloseable

Direct SubClass of FileInputStream

  • SocketInputStream

The class structure of Class FileInputStream in Java is given as:

public class java.io.FileInputStream extends java.io.InputStream{
//constructors
public FileInputStream(File file) throws FileNotFoundException;
public FileInputStream(FileDescriptor fdObj);
public FileInputStream(String name)throws FileNotFoundException;
//Methods
public native int available()throws IOException;//returns the number of bytes of input currently available for reading.
public native int read()throws IOException;//returns an integer representation of the next available byte of input.
public int read(byte b[])throws IOException;//attempts to read up to b.length bytes into b and returns the actual number of the bytes that were successfully read.
public int read(byte b[],int offSet,int length)throws IOException;//attempts to read up to length bytes into b starting at b[offSet] returning the number of bytes successfully read. 
public native void close()throws IOException; //closes the input source;further, read attempt on a closed input will generate an IOException.
protected void finalize()throws IOException;
public final FileDescriptor getFD()throws IOException;
public native long skip(long l)throws IOException;//skips over l bytes of input and returning the number of bytes skipped.
} 

In addition, all methods may throw an IOException if an IO error occurs apart from their regular Exceptions. All of the constructors can throw a SecurityException if the application does not have permission to read from the specified file.

Note  In general java searches for the file in the current directory. But allows us to pick files from different folders.

In FileInputStream, the path is always represented in String. It is having a double backslash(\\). This is important in java in order to obtain single backslash(/). In String java, the single backslash(\) is considered as an escape character.

In Unix, we can use forward-slash(/). Like

String filePath="/home/usr/desktop/test.txt"

Constructors of Class FileInputStream in Java

The details of the class structure are given as follows:

public FileInputStream(String name)throws FileNotFoundException;

public FileInputStream(String name) constructor creates a FileInputStream that gets its input from the file (specified String). It creates a FileInputStream object to read from the specified File object. It opens a connection with the File. A new FileDecsriptor to connect this file will also be created.

It may throw FileNotFoundException if the file is not available. It may throw SecurityException if a security manager exists, and its checkRead() method is called with the file descriptor to see if the application is allowed read access to the file. This may result in a SecurityException.
Parameter
name -A String that contains the pathname of the file (to be accessed). The path must conform to the requirements of the native operating system.

Example to read a character from a file

FileInputStream fis=new FileInputStream("D:\\Test\\test.txt");
int j=fis.read();
System.out.println(j);
fis.close();

The test.txt file must be created with some initial value in it and must be placed in the D:\Test folder.

In case, the file is not available or it can not be opened, it throws a FileNotFoundException.

public FileInputStream(File file)throws FileNotFoundException;

public FileInputStream(File file) constructor creates a FileInputStream that gets its input from the file represented by the specified File. It creates a FileInputStream object to read from the specified File object. It may throw FileNotFoundException if the file is not available.

READ  SequentialInputStream in Java

If there is a security manager available, the checkRead() method is called. This method takes the argument as the path of the file.
Parameter
file -The File to use as input.

public FileInputStream(FileDescriptor fd);

public FileInputStream(FileDescriptor fd) constructor creates a FileInputStream that gets its input from the file identified by the given FileDescriptor.

Here fd is the FileDescriptor(java.io.FileDescriptor) object that opens the file for reading.

It creates a FileInputStream object to read from the specified FileDescriptor object. It may throw SecurityException if a security manager exists, and its checkRead() method is called with the file descriptor to see if the application is allowed to read from the specified FileDescriptor. This may result in a SecurityException.

So basically the SecurityManager checks if the application has access to the specified file or file descriptor. This results in the above told SecurityException.

Incase fd(FileDescriptor objcet) is null, this constructor throws a NullPointerException.
Parameter
fd-The FileDescriptor of the file to use as input.

public native int available()throws IOException;

public native int available() method returns the approximate number of remaining bytes of data to read or skip or discarded in the input stream. This calculation is approximate without blocking the next call of this method. Initially, this is the length of the file.

The invocation of the method may use separate thread or the same thread. Interestingly, a read/skip operation of the output of the available() method in terms of bytes will not block but may skip/read fewer bytes.

A read or skip operation for a non-blocking case may be blocked due to huge file size or due to a very slow network connection or if the server containing the file crashed and the file is not available to read.

If we try to read a file using available() method that has already reached the end of the file will return -1.

This method returns the number of bytes that can be read/skip from the file without blocking.

fis.available();//returns the available bytes from the stream

using buffer array:

try{
FileInputStream fis=new FileInputStream("D:\\Test\\test.txt");
byte[] myArray=new byte[20];
int k=fis.read(myArray,0,10);
System.out.println("More bytes available"+fis.available());
System.out.println("no of bytes read"+k);
for(bytes myBytes:myArray){
char myChar=(char)myBytes;
System.out.println(myChar);
}
}
catch(Exception e){}
public native void close();

public native void close() method closes this file input stream and unlocks any resources used by this stream. If the underlying stream is attached to a Channel, in that case, this method will close the channel as well.

public final FileDescriptor getFD();

public final FileDescriptor getFD() method returns the file descriptor associated with the data source of this FileInputStream.
This method returns the file descriptor for the file that supplies data for this stream.

fis.getFD();//returns the file descriptor information
//or
 FileDescriptor fd=fis.getFD();
boolean isValis=fd.valid();
System.out.println(isValid)
public native int read() throws IOException;

public native int read() method reads the next byte of data from the file. The method blocks if no input is available. If we try to read a file that has already reached the end of the file will return -1.

read() method reads unassigned bytes from the underlying InputStream and returns an integer in the range of 0 to 255.

We can create any number of input streams to read from the same file at the same time. They can work perfectly in a concurrent manner. Each stream will have its own pointer to track the corresponding position.

read() method blocks id no input is available, end of file/stream is reached/detected or an exception is thrown.

This method returns the next byte of data or -1 if the end of the stream is encountered.

public static int readSingleByte(java.io.InputStream in) throws IOException

readSingleByte() function reads a single byte from the InputStream specified.

public int read(byte[] b)throws IOException;

public int read(byte[] b) method reads b.length data into the given array(buffer). The method fills the array if enough bytes are available. The method blocks until some input are available.

This method returns the actual number of bytes read or -1 if the end of the stream is encountered immediately.
Parameter
b – An array of bytes to be filled from the stream.

public int read(byte[] b, int off, int len)throws IOException;

public int read(byte[] b, int off, int len) method reads len bytes of data into the given array, starting at element off. The method blocks until some input are available.

If the length(len) is zero then no data is read, o is returned. It fills the buffer with the data it read so far.

This method blocks id no input is available, end of file/stream is reached/detected or an exception is thrown.

if b is null a NullPointerException is thrown.

if offSet is negative or len is negative and len+offSet is greater than the length of the array b, then IndexOutOfBound is thrown.

Once the first byte is read, it is stored in b[offSet], the next byte is stored as b[offSet+1] position. So in this way, the number of bytes read is at most equal to len.

In case, n is the number of bytes actually read, they will be stored in b[offSet+n-1].And it leaves the b[offSet+n] to b[offSet+len-1] unaffected.

This method returns the actual number of bytes read or 0. If the end of the stream is encountered it returns -1.

READ  Class CollectionElementIterator in Java

Parameter
b -An array of bytes to be filled from the stream.
off – An offset into the byte array.
len – The number of bytes to read.

public native long skip(long n)throws IOException;

public native long skip(long n) method skips(discards) n bytes of data from input in the stream. This method may also skip or discard 0 byte or equivalent smaller bytes of data.

Using the skip() method we can go to the forward direction in most of the cases but not backward direction.

In case n is negative, skip() method tries to come backward direction. In that case, if the underlying file does not support the backward skip operation, this method throws IOException.

If it skips in the positive direction, the number of skipped bytes is returned and in case it skips backwards, it returns a negative value.

If skip() method skips more bytes that are remaining in the file, no exception is thrown and it returns actual bytes and some bytes beyond the end of the file.

This method returns the actual number of bytes skipped. In a case where the skip() method reached beyond the end of the file may return -1.

Parameter
n -The number of bytes to skip.

fis.skip(4);//skips 4 bytes from the stream.
public FileChannel getChannel();

public FileChannel getChannel() method returns the unique FileChannel that is connected with the FileInputStream. This channel’s initial position is the number of bytes read till now from the file. The position of the file can be altered by reading bytes or explicitly setting the value.

This channel is the object of java.nio.channels.FileChannel.

fis.getChannel();//returns the channel information

Users can not directly create a file channel directly while using NIO. They must create an instance input/output RandomAccessFile and then can apply the getChannel() method on it.

Another flavour is

public IOCipherFileChannel getChannel()

This function returns a read-only IOCipher File channel that depicts the position with the FileInputStream.

protected void finalize();

protected void finalize() method is called when the FileInputStream is garbage collected to ensure that close() is called. If the stream has a valid file descriptor, the close() method is called to free the system resources used by this stream. It checks if there are no valid references exist.

In short, the finalize() method ensures that close() method is actually successfully called and it helps in the garbage collection process. Finalize() method is called on an object when it is unreachable but not destroyed.

This call is done by JVM(Java virtual machine). Java does not call this method for every object. if at all a program is terminated abnormally and Garbage collection does not happen, only then JVM calls this method internally.

Finalize() is called by a Thread that has actually no lock on any objects or it can be called concurrently. If an exception is thrown during the finalize() call at the time of garbage collection, the exception is ignored and the object is destroyed.

Users can call finalize() method but that does not stop or accelerate the JVM’s automatic finalize() invocation.

If we try to access the FileInputStream after calling the finalize() method, an exception is thrown.

fis.getChannel();
fis.finalize();
fis.available();//an exception is thrown

We do not need to call the finalize() method explicitly in general cases. But if we create a subclass of the FileInputStream, we need to call super.finalize() from the subclasses finalize() method.

finalize() method is deprecated currently and will be removed slowly. We should not rely on this method.

Apart from these FileInputStream class also has inherited methods from class- Object. They are as follows:

  • clone()
  • finalize()
  • hashCode()
  • notifyAll()
  • wait()
  • wait(long, int)
  • equals(Object)
  • getClass()
  • notify()
  • toString()
  • wait(long)

FileInputStream class also has inherited methods from class- Object. They are as follows:

  • markSupported()- It returns boolean value. If it returns true, it is using a marker. returns false, if otherwise. This function accepts an integer parameter to set a maximum number of bytes we need to read before reaching to the point set by mark() method.
  • reset()-This method returns the control to the point where the mark was set initially in the underlying input stream.
  • mark(int)- This method marks the position of the input stream until where the data is read.

An Example of FileInputStream


class InputStreamTest{
public static void main(String args[])
{
int size;
FileInputStream fin=new FileInputStream("C:\\Tes\\tmyFile.txt");
size=fin.available();
System.out.println("Total bytes"+size);
for(int i=0;i<size/4;i++)
System.out.println((char)fin.read());
System.out.println("remaining bytes"+fin.available());
System.out.println("remaining 1/4 is displayed :using read(b[]");
byte b[]=new byte[size/4];
if(fin.read(b)!=b.length)
{
System.out.println("File reading error");
}
else
{
String temp=new String(b,0,0,,b.length);//converts bytes to ASCII code
System.out.println(temp);
System.out.println("Still available :"+fin.available());
System.out.println("skipping 1/4: using skip()");
fin.skip(size/4);
System.out.println("file remaining for reading"+fin.available());
}
fin.close();
}
}
 

FileInputStream object can be opened in the following way:

  1. FileInputStream fin;
    fin=new FileInputStream(String name);//name indicates the source file
  2. File myFile;
    FileInputStream fin;
    myFile=new File(String name);
    fin=new FileInputStream(myFile);

How to read data or the whole file using Class FileInputStream in Java?

  • Create a FileInputStream object to connect to the file.
  • Read data from FileInputStram by one byte
  • Read the whole file data one by one sequentially using a while loop.
  • finally, close the FileInputStream.
FileInputStream fis=new FileInputStream("C:\\Tes\\tmyFile.txt"); 
char ch=fis.read();//read one byte by one byte
while(j=fis.read())!=-1){
System.out.println(char)j);

Class FileInputStream in Java in Serialization

Let us create a class that we want to Serialize using Serializable interface.

import java.io.*;
public class MySerialization implements Serializable {
	
	public int x=5;
	transient int y=10;
	private float z= 2.0f;
	
	int getX() {
	return x;
	}
	int getY()
	{
		return y;
	}
	float getZ() {
		return z;
	}
}

Check here we have a transient data y.
Now lets us create a class that helps in Serialization


import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

public class MyDemoSerialization {

	public static void main(String[] args) {
		MySerialization ms= new MySerialization();
		System.out.println("value of x "+ms.getX());
		System.out.println("value of y "+ms.getY());
		System.out.println("value of z "+ms.getZ());
		try {
			FileOutputStream fos=new FileOutputStream("D:\\MyCode\\abc.ser");
			ObjectOutputStream oos=new ObjectOutputStream(fos);
			oos.writeObject(ms);
			oos.close();
			System.out.println("Serialization is done");
			
		}
		catch(Exception e) {e.printStackTrace();}
	}

}

The output of the code:
value of x 5
value of y 10
value of z 2.0
Serialization is done
the y value is printed before Serialization

READ  How To Write A Function That Will Read Data From Excel Using POI Jar
Serialization data created
Serialization data created

Now let us DeSerializa the same

import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class MyDeSerialization {

	public static void main(String[] args) {
		System.out.println("Deserialization starts");
		MySerialization ms = null;
		try {
			FileInputStream fis=new FileInputStream("D:\\MyCode\\abc.ser");
			ObjectInputStream ois=new ObjectInputStream(fis);
			 ms = (MySerialization)ois.readObject();
			ois.close();
		}
		catch(Exception e) {e.printStackTrace();}
		System.out.println("value of x "+ms.getX());
		System.out.println("value of y "+ms.getY());
		System.out.println("value of z "+ms.getZ());
	}

}

The output of the code:
Deserialization starts
value of x 5
value of y 0
value of z 2.0

Check the y value is not saved as it is transient.

Performance Improvement of Class FileInputStream in Java

FileInputStream gives us low-level interface in order to read data from a file.  Read via an array of bytes is more efficient than reading a single byte via FileInputStream. The performance factor is increased by 10X. However, the performance/speed depends on the  following factors

  • The size of the byte array on which we are trying to read.
  • The underlying operating system.
  • The hardware configuration.
  • The harddisk buffersize.
  • The target system

Note- if Buffersize is greater than or equals to 8KB, the data transfer speed will be good. But we can not infinitely increase the byte array size. In case, it is greater than the actual capacity of the underlying operating system or hardware configuration, the speed will decrease significantly.

For more efficient reading, we can wrap the FileInputStream with more efficient streams like-

  • DataInputStream
  • BufferedInputStream
  • RandomAccessFile(If we need data randomly from the InputStream)
  • etc

These are applicable only when we need to have efficient higher-level interfaces to handle String and binary data.

Use a BufferedInputStream in conjunction with Class FileInputStream in Java

BufferedInputStream is one level up of the FileInputStream. In order to read automatically and transparently, it is better than buffering of an array of bytes using FileInputStream. Even if the bytes are read sequentially one by one, BufferedInputStream is significantly faster than FileInputStream’s buffer approach.


InputStream is=new BufferedInputStream(new FileInputStream("D:\\Test\\test.txt"),1024*1024);

Convert Class FileInputStream in Java to Reader

For further speeding up the process, we can convert FileInputStream to Reader.


InputStream is= new FileInputStream("D:\\Test\\test.txt");
Reader reader=new InputStreamReader(is);

Applets and FileInputStream

The untrusted Applets are not allowed to read or write to files. So while using Applet, if we create FileInputStream(very rare though), We get a security Exception from SecurityManager.

However, Applets can connect network disconnect to the originating server, hence, Streams are useful in Applet only to transmit data between source server to itself only.

What is the difference between FileReader and FileInputStream?

FileReader and FileInputStream classes can read data from the file in java. The differences are as follows:

FileReaderFileInputStream
FileReader reads data from the character stream.FileInputStream reads data from a byte stream.
read() method can read 2 bytes(16 bits) at a time. Character is 16-bit data typeread() method can read 1 byte(8 bits) at a time.
FileReader converts raw bytes to the character. For this conversion, it uses the platform’s default character encoding.FileInputStream acts as a bridge between byte stream and character stream.
FileReader can read a file if the file is created using the platform’s default encoding scheme.If a different encoding scheme is used, FileInputStream helps to read when the character encoding scheme is specified.
FileReader is a subclass of Reader.FileInputStream is a subclass of InputStream.
FileReader does not support Serialization and Deserialization.FileInputStream supports Serialization and Deserialization.
FileReader is best suited when reading text data like text file, pdf, word file etc.FileInputStream is best suited when reading binary data like audio, video, image data.

What is the difference between FileInputStream and ObjectInputStream?

FileInputStream and ObjectInputStream are used to read data but the differences are as follows:

FileInputStreamObjectInputStream
FileInputStream is for reading from Files.ObjectInputStream is for reading Objects
FileInputStream can not directly store the state of the object.ObjectInputStream can directly store the state of the object.

Compressing a file to zip using InputStream

public void zipFile(File srcFile, File zipFile) throws IOException {
 try (FileInputStream fis = new FileInputStream(srcFile);
   ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile))) {
  zos.putNextEntry(new ZipEntry(srcFile.getName()));
  int len;
  byte[] buffer = new byte[1024];
  while ((len = fis.read(buffer)) > 0) {
   zos.write(buffer, 0, len);
  }
  zos.closeEntry();
 }
}

copy file using the channel of FileInputStream

public static void copyFile( File from, File to ) throws IOException {
   if ( !to.exists() ) { to.createNewFile(); }
   try (
	FileChannel in = new FileInputStream( from ).getChannel();
	FileChannel out = new FileOutputStream( to ).getChannel() ) {
 	out.transferFrom( in, 0, in.size() );
  }
}

Conclusion

In FileInputStream, we can read data sequentially, one by one byte. Being byte-based, it can read from Unicode code points. But the APIs of FileInputStream is not designed for reading character-based text data. They only support 8 bits of binary values(byte).

However, Java does support the above problem but the IDE console follows a specific character encoding. In that case. if we handle other than that character encoding, we may get different characters as the output.

The last point to remember is that while reading the byte sequence, we often transfer them to the character to print the value. This is done via char casting. This char casting is a wrong approach. Actually we need to decode using the appropriate character set.

Share and Enjoy !

Leave a Comment

Your email address will not be published. Required fields are marked *