File Handling In Java

File handling in Java is one of the most important functions of java. We read from a file and write to a file.

When writing to a file, the source from where it is read can be anything. It can be database, a string or another file.

How to create a file?

File class which is part of the java.io package is used for the creation of a file

File obj = new File("testFile.txt");

How to read a file?

try {
    //First we create an Object to read from the input file.
    File fileObj = new File("C\\:FileTest.txt");  
    Scanner fileReader = new Scanner(fileObj);
    while (fileReader.hasNextLine()) {
    String data = fileReader.nextLine();
    System.out.println(data);
}
    fileReader.close();
} 
catch (FileNotFoundException e) {
    System.out.println("An error occurred.");
    e.printStackTrace();
}

Above we have used a scanner to read from a file. But there are other utilities available as well.

There are 2 ways in which data is read from a file.

1)Stream of Bytes: Here data is read from a file as a stream of bytes. You an say read as binary format. FileInputStream is the class which does that.

2)Stream of Characters: Here data is read from a file as sequence of text/characters. You can say read as unicode format. FileReader is the class to read text data.

Difference between an InputStream and a Reader in Java? Both InputStream and Reader are ways to read data from the source , which can be either file or socket, but main difference between them is that InputStream is used to read binary data while Reader is used to read text data, precisely Unicode characters.


Let’s see the below implementation for FileInputStream and FileReader.

//Reading File using InputStream
try (FileInputStream fis = new FileInputStream("testFile.txt")) 
{ 
  int data = fis.read(); 
  while (data != -1) 
  { 
     System.out.print(Integer.toHexString(data)); 
     data = fis.read(); 
  } 
} 
catch (IOException e) 
{ 
    System.out.println("Failed to read binary data from File"); 
    e.printStackTrace(); 
}
 
// Reading File data using FileReader in Java 
try 
(
   FileReader reader = new FileReader("testFile.txt")) 
   { 
      int char = reader.read(); 
      while (character != -1) 
      { 
         System.out.print((char) character); 
         character = reader.read(); 
      } 
 } 
 catch (IOException io) 
 { 
     System.out.println("Character data reading from File failed"); 
     io.printStackTrace(); 
 }

read():

The read() method of the FileInputStream/FileReader class returns an int which contains the byte value or char value of the byte/char read. If the read() method returns -1, there is no more data to read in the FileInputStream/FileReader, and it can be closed. That is, -1 as int value, not -1 as byte value

BufferedReader & BufferedOutputStream

Another way to read from a file is using the BufferedReader/BufferedInputStream Class. If no of reads are more, then BufferedReader/BufferedInputStream is preferable as it buffers the read characters/bytes in internal memory rather than reading and writing directly. The buffer size may be specified, or the default size may be used.

Writing to a file:

To write into a file also there are many tools available.

Let’s see a basic example using FileWriter class.

try {
    FileWriter testWriter = new FileWriter("TestFile.txt");
    testWriter.write("Writing into test file to test file writer"); 
 
    // Closing the resources allocated
    testWriter.close(); 
    System.out.println("Successfully written in the file.");

} catch (IOException e) {
    System.out.println("An exception occurred.");
    e.printStackTrace();
}

Apart from FileWriter Class, Similarly for file writing we have BufferedWriter and FileOutputStream class as well.

FileWriter writes directly into Files and should be used only when the number of writes is less. BufferedWriterBufferedWriter is almost similar to FileWriter but it uses internal buffer to write data into File. So if the number of write operations is more, the actual IO operations are less and performance is better. FileOutputStream writes stream of bytes.

ArrayList in Java

ArrayList is part of the Java Collections API.

ArrayList is a part of collection framework and is present in java.util package. If you see above hierarchy, It implements the Collection interface.

An important point here is that Map is not part of the Collections interface and only list, queue and Set are part of it. But Map is part of the collections API.

So what is ArrayList?

It is part of the java.util package and implements the List interface as seen in above hierarchy. It is an data structure or you can say a dynamic array structure.

It is an dynamic array because lots of manipulations are needed in some cases and it is ideal data structure to be used in such cases. It is slower than simple arrays.

// Java program to demonstrate the 
// working of ArrayList in Java 

import java.io.*; 
import java.util.*; 

class ArrayListExample { 
	public static void main(String[] args) 
	{ 
		// Size of the 
		// ArrayList 
		int n = 5; 

		// Declaring the ArrayList with 
		// initial size n 
		ArrayList<Integer> arrli 
			= new ArrayList<Integer>(n); 

		// Appending new elements at 
		// the end of the list 
		for (int i = 1; i <= n; i++) 
			arrli.add(i); 

		// Printing elements 
		System.out.println(arrli); 

		// Remove element at index 3 
		arrli.remove(3); 

		// Displaying the ArrayList 
		// after deletion 
		System.out.println(arrli); 

		// Printing elements one by one 
		for (int i = 0; i < arrli.size(); i++) 
			System.out.print(arrli.get(i) + " "); 
	} 
} 

If you see above code, 2 operations are being done.

a)add

b)remove

Add Elements: add() method is used to add elements in arrayList. It is an overloaded method to do operations based on parameters.

  • add(Obj): This method is used to add an element at the end of the ArrayList.
  • add(int index, Obj): This method is used to add an element at a specific index in the ArrayList.

Remove Elements: We use the remove() method to remove elements from arraylist. This method is overloaded to perform multiple operations based on different parameters. They are:

  • remove(Object): This method removes the object which is passed as a parameter to it. If there are multiple elements in the list for the same object, then the first occurrence would be removed.
  • remove(int index): This method removes the object against the index which is passed as a parameter to it.

List Iterator:

  1. import java.util.ArrayList;  
  2. public class ListIteratorExample
  3. {  
  4. ArrayList<String> list1= new ArrayList<String>();  
  5. list1.add(“a1”);  
  6. list1.add(“a2”);  
  7. list1.add(“a3”);  
  8. System.out.println(list1);
  9. ListIterator<String> iterator = list1.listIterator(1);  
  10. while (iterator.hasNext())  
  11. {  
  12. String i = iterator.next();  
  13. System.out.println(i);  
  14. }  
  15. }  

O/P would be:

[a1,a2,a3]

a1

a2

a3

Another common way is to use for loop to iterate a list. But since list iterator is more specific to list data structures, it is preferable.

Internal Working Of ArrayList?

Since ArrayList is a dynamic array and we do not have to specify the size while creating it, the size of the array automatically increases when we dynamically add and remove items.

  • Creates a double sized ArrayList in heap when array becomes full or when an element is added.
  • Copies the current memory elements to the new memory.
  • New item is added now as there is bigger memory available now.
  • Delete the old memory.

Hence Arraylist performs poorly when elements are added or removed. It is good performance of O(1) when getting elements since it implements the random access interface.

Exception in Java

It is any event which disrupts normal flow of a program execution.

Exception is different from an error. The program can recover from an exception but not from an error.

So how it recovers from an exception?

That is called Exception handling which we will see later in this post.

Let’s see the Java Exception Hierarchy.

Src: Wiki Commons

In Exception, there are 2 types.

If you see base class for both exceptions and error is java.lang.Throwable.

a)Checked Exception – IOException, SQLException etc as seen above in pink.

b)Unchecked Exception – Runtime exceptions like nullpointerexception, arithmetic etc

Checked Exception is something which we should handle at compile time. If we don’t handle it, then compilation would fail.

Runtime Exception may or may not be handled. But it’s always good to handle those too.

How to handle exceptions?

Exception handling is a compulsion so that the flow of the programs ends or moves gracefully and doesn’t end abruptly. Here the flow of programs doesn’t break.

By handling the exceptions we can provide a meaningful message to the user about the issue rather than a system generated message, which may not be understandable to a user.

Why exception occurs?

There are several reasons for that. It can be due to invalid input or data instead of expected data, database connectivity or web service connectivity problems, file missing etc.

There are 2 ways in which we can handle java exceptions.

1)using try, catch block.

2)Using throws or throw keyword.

Let’s see what is a try, catch & finally block.

try – Our code segment is inside try block because the code segment will possibly fail with an exception.

catch – This is the block which catches the exception once it encounters the same in try block.

finally- This is the block which executes in the last irrespective of the exception happening or not.

.      try {
         no1 = 0; //1
         no2 = 100/no1; //2
         System.out.println(no2); //3
         System.out.println("Try block ends"); //4
      }
      catch (ArithmeticException e) { 
         /* This block will only execute if any Arithmetic exception occurs in try block          */
         System.out.println("We should not divide a number by zero");
      }
      catch (Exception e) {
         /* This is a generic Exception handler which means it can handle
          * all the exceptions. This will execute if the exception is not
          * handled by previous catch blocks.
          */
         System.out.println("Exception occurred in catch block");
      }
     

     finally
     {
        System.out.println("Finally block in Java.");
     }

If you see the above example, the program will fail in the try block with divide by zero arithmetic exception.

Then it goes to catch block which catches arithmetic exception and then into finally block.

O/P of above try catch would be :

We should not divide a number by zero
Finally block in Java.

So the exception occurs in line 2. So lines 3 and 4 are skipped and it directly goes into catch block.

So if you see, there are multiple catch blocks. Since it is an arithmetic exception, it goes into catch block to handle arithmetic exception. If catch block to handle arithmetic exception handling was not there, then it would had gone into catch block for Exception handling.

One thing to notice here is that order of the catch blocks should be child to parent. Arithmetic exception Class is child of Exception class. If exception class catch block was before arithmetic exception, then catch would had never reach arithmetic exception catch block since exception class is the parent of all.

Throw and throws:

Throw is a keyword which is used to throw an exception explicitly in the program inside a function or inside a block of code. Throws is a keyword used in the method signature used to declare an exception which might get thrown by the function while executing the code.

public class ExceptionTestMain{
   public int division(int a, int b) throws ArithmeticException{
      int t = a/b;
      return t;
   }
   public static void main(String args[]){
      ExceptionTestMain obj = new ExceptionTestMain();
      try{
         System.out.println(obj.division(15,0));
      }
      catch(ArithmeticException e){
         System.out.println("You shouldn't divide number by zero");
      }
   }
}

Exception is thrown by the division method called in main method. Exception was thrown due to the throws keyword used with the division method declaration. If there were no throws keyword declaration with method or exception was not explicitly thrown using throw keyword like throw new RuntimeException inside the division method, then exception would not had been handled and program would had ended abruptly inside division method.

Thanks for reading. Checkout my other articles related to java and tech.

String in Java

In Java String is an object containing a sequence of characters. Probably the most important and the most used class in java.

How we instantiate it?

String s = “Java”; //#1

String s1 = new String(“Java”); //#2

So what is the difference between the two?

#1 will create a string with value java in the string pool if a string with the same value as Java is not present in the pool.

String Pool in java is a pool of Strings stored in Java Heap Memory. It is used for memory optmization. So for example if another string as String a = “Java”; is created, it will check in string pool if a string with same value exists or not. If it exists, the new string a would point to the same string reference.

#2 would create an separate instance of string object not inside the string pool. It would create in the heap space.

String Intern:

Intern is a method in the string class. It’s objective is to return the string created in the java heap space into string pool.

String s1 = new String(“Java”);

So in the above case, string object s1 created in the heap if called with intern method would return the reference from the string pool.

Now, when we are calling s1.intern()JVM checks if there is any string in the pool with value “java” present? Since there is a string object in the pool with value “java”, its reference is returned.

s1 = s1.intern();

So here s1 is pointing to the value Java present in string pool.

Is String immutable?

Yes, string in java is immutable.

For example if String s = ‘Test’; It would be added into string pool and will have a particular memory reference there.

then we update the value as s = ‘Test2’;

Here the value ‘Test’ and the memory and also the reference which was allocated to it will stay as it is. Another memory allocation would be done for value Test2 and s will point to that.

Hence it is said string is immutable because we couldn’t change the value Test.

If it was immutable, the value would have been updated in the same memory allocation itself and Test would have been replaced with Test2.

Now lt’s look at an example to clear the things finally.

 public class StringTest {
    public static void main(String[] args) {
        String s1 = "Java";
        String s2 = new String("Java");
        String s3 = "Java";
        if (s1 == s2) {
            System.out.println("s1 and s2 equal");
        } else {
            System.out.println("s1 and s2 not equal");
        }
        if (s1 == s3) {
            System.out.println("s1 and s3 equal");
        } else {
            System.out.println("s1 and s3 not equal");
        }
    }
}

O/p:
s1 and s2 not equal 
s1 and s3 equal

These are the basics of String class. Read the java documentation.

Hashmap in Java – How it works?

Hashmap is an data structure in which entry is stored as an key-value pair.

Internally, it is an array of nodes and node represents a class having following objects.

Key is always unique. Maximum one null key allowed in a hashmap.

a)int hash

b)K key

c)V value

d)Node next

Hashing : It is a process to get an integer representation of the key. It is used to calculate bucket location of the entry(key-value). Integer representation is calculated by calling hashcode() method on the key object.

Now let’s discuss equals method.

Hashmap equals:

It is used to compare 2 objects which are keys in the case of hashmap. Equals method is part of java.lang.object class. Equality is checked on the basis of the reference(hashcode) of the 2 objects.

If it is the same object, then equals method would return true. If those are different objects, it would be false always.

But sometimes, 2 different objects can be equal too but their member variables match.

For example, consider the below 2 objects from class A having just 2 member variables x & y.

A a = new A();

A b =new B();

a.x =5; b.x = 5;a.y =7; b.y = 7;

So objects a and b are ideally equal. But if we call the equals method on the object, it would return false since the reference is different for 2 objects.

a==b returns false.

In such case, we need to override the equals method in the class A and derive equality on the basis of the member variables.

boolean equals(Object key)

{

if (this.x == key.x && this.y == key.y)

{ return true }

else return false

}

Bucket:

A bucket is one element of hashmap array. It is used to store nodes. Two or more nodes can have the same bucket.

In that case, linked list is used to connect the nodes inside that bucket location.

Now let’s see how an bucket index is calculated. The hash function internally used for index location calculation is:

index = hashcode(k) & (n-1)

so if hashCode of key = 117 and size of array =16 then index loc = 5.

Ideal candidates for keys:

String is the best candidate for key since it is immutable and there is no need to override equals method.

Load factor:

The Load factor is a measure that decides when to increase the HashMap capacity to maintain the get() and put() operation complexity of O(1). The default load factor of HashMap is 0.75f (75% of the map size).

Insertion,deletion and fetch in hashmap:

HashMap<Integer, String> hash_map = newHashMap<Integer, String>(); hash_map.put(10, "Java"); hash_map.put(15, "Guru");

Here 10 and 15 are keys.

String retVal= (String)hash_map.remove(10);

It removes the entry 10, ‘Java’.

String retVal= (String)hash_map.get(15);

It fetches Guru as the value.

What is an API?

API stands for application programming interface.

It is an interface through which users or client programs interacts with other systems.

For an example, suppose you want to get the list of all admins in a whatsapp group.

There is a function named as getWhatsAppAdmins(String groupId). It returns a list of all admins. We need to pass the groupId as parameter for which we want the list of admins.

The process of calling the unction from client side is called an API call and through hat API we interact with whatsapp system.

Image Source: Guru99.com

So if you see, the client/user at the rightmost layer calls the API. The client doesn’t know anything about the business logic and the database details. A simple API call should get the job done for the client.

So the question now is where the function/method call should fit in?

So it can be a micro service or a web service.

microservice is a small, independent, application that performs a highly focused service as well as possible. A web service is an internet-based interface that makes the “services” of one application available to applications running on different platforms.

So next question is how to call it?

It can be a GET or a POST call.

In GET, the parameters are concatenated in the Web Service URL itself.

In POST, it is not part of the URL so the limit of POST is huge.

For example,

www.abc.com/whatsappmodule/getWhatsAppAdmins

is a POST call.

www.abc.com/whatsappmodule/getWhatsAppAdmins/1251

becomes a GET call because we pass the whatsapp group id 1251 as well while calling.

here www.abc.com = server address on which application is hosted.

whatsappmodule = name of the application

getWhatsAppAdmins = name of the service

In Spring MVC or REST WS API Call, it is the spring controller or an internal dispatcher which forwards it to the actual service on the basis of the name getWhatsAppAdmins in our case.

Now speaking about the response from the web service, it is either a JSON or an XML response.

Sometimes the o/p is huge which might impact the network usage, so Pagination if done at client side would be good. Like, give me the top 10 admins or something like that etc.

Thanks for reading. Checkout out our other articles as well.

What are containers? What is docker?

Ok to start, computers are comprised of below 4 resources.

Memory, I/O, Processor & Disk.

So containers are something which share the same server machine’s OS system kernel and therefore do not require an OS per application.

So an server is shared between multiple users and allocation is done to each one of them.

So as seen above, user (UI) via an API interacts with the OS & Server. That API can be Docker Container.

A container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another. A Docker container image is a lightweight, standalone, executable package of software that includes everything needed to run an application: code, runtime, system tools, system libraries and settings.

So a docker container is lightweight, secure and extremely easy to ship from here to there.

Our program specifies the memory and OS details which we need via the Docker Container and Docker will take it forward from there.

Docker can be considered as the API through which our program interacts with OS of the Main Application Server.

Docker creates an interface and handles the communication with OS and deployment of code in server. It forms an important part of Devops. Developer doesn’t need to worry about code deployment. Docker takes care of everything.

So for many users/programs, multiple light weight docker containers would be created and deployed to server.

Docker Engine is an open source containerization technology for building and containerizing your applications. Docker Engine acts as a client-server application with:

  • A server with a long-running daemon process dockerd.
  • APIs which specify interfaces that programs can use to talk to and instruct the Docker daemon.
  • A command line interface (CLI) client docker.

This is somewhat like a cloud computing.

1)App Isolation.

2)Platform independence

3)Low cost.

Horizontal vs Vertical Scaling

One of the core concepts of System Design is System Design and scalabilty is somthing which should be thought upon when designing an system.

So what is scalability?

It is the ability to handle more requests by buying more machines.

To buy a bigger machine, it is called vertical scaling. To buy more machines, it is called horizontal scaling.

Now let’s see the characteristics of each.

Horizontal

1) Load balancing is required for this architecture.

2) It is very resilient.

3)Increase in Networks calls due to multiple machines.

4)It will scale well if users increase with the addition of new machines.

5)Also a chance a data inconsistency if multiple machines are involved with their own JVM’s or you can say environments.

Vertical

1)No concept of load balancing since it is a single system or server.

2)It is a single point of failure. So if that server fails, everything stops.

3)Inter process communication is possible so no network calls.

4)There is a hardware limit unlike horizontal scaling where multiple machines can be added whenever required.

5)Data consistency is quite guaranteed as it is an single environment.

So as per your requirement, you can choose horizontal or vertical scaling.

In horizontal, you get a better scalability in case of a failure. If one server fails, the requests can go to a different server. Also it performs well with the increase in the usage and no of users.

In vertical, there is better perf with inter process communication and data consistency guaranteed.

Choose the one best for your application.

Thank for reading.

Monolithic vs Microservices Architecture

Monolithic means all in one piece or you can say a single tier application. It has a single code base as part of a one single huge application having multiple modules.

Microservices means having multiple smaller units which process as a separate service. Each microservice has it’s own business logic and a dedicated database. So in an micro services architecture, client connects to an gateway and that gateway connects to that micro service having an dedicated DB.

Now let’s take about the pros and con of each:

Monolithic:

Pros

1) It is good for smaller systems where multiple modules are not interacting with each other.

2) Low cost and maintainance.

Cons

1)Deployments are complicated in an monolithic architecture since it is one huge application. So one change might have a regression and break other modules. 🙁

2)It is very tightly coupled as it is an single tier.

3)If a server crashes then all modules would crash.

4)New Joiner will find it tougher to understand an huge monolithic app.

Microservices:

Pros:

1)Easier to design as it is loosely coupled and an independent architecture.

2)Good for new joiners to understand new functionality of a particular module rather than learning a whole huge monolith app.

3)Parallel processing possible with this architecture.

Cons:

1) Not exactly an Con but yes smart architects are needed when designing an micro services architecture. Data consistency should be guaranteed.

2) Cost is more.

So to conclude, for larger systems micro services is an better option to go ahead. But there should be an use case of multiple modules interacting with each other. If only 1-2 modules interact, then no point of going with an MS architecture.

Stack over flow uses monolithic architecture and other tech giants like google and amazon are going ahead with micro services.

Depends on the use case or you can say functionality.

Maven 4

Let me highlight the improvement done in Maven 4.

1) The entire build is done via a component known as reactor.

The first improvement in the Reactor is a bug fix. Suppose, if your project build failed on the a particular module say module1, you would get a hint to resume the build with —

resume-from :module1.

But this time you would see another failure because Maven couldn’t find the common module. You might think that adding –also-make would address this, but it wouldn’t. This long-standing bug is no longer there. If you combine –resume-from :module1 with –also-make, the Reactor will find all modules in your project and continue the build as you requested.

2) Introduction of a new implementation for parallelization and smart scheduling.

3) Our java projects can have multiple modules. Also it can be an multi-module project is more than one or two levels deep. For example, take the Quarkus project structure as below.

Each extension has least two subprojects, deployment and runtime.

Earlier, if you wanted to build only the gRPC module and its five children, you would have needed something like mvn -pl

extensions/grpc/codegen,extensions/grpc/deployment – and the list would go on and on… With Maven 4, you can use -pl extensions/grpc and build the grpc module plus all its child-modules in one go.

3) In Maven 4, all modules in the build will have the same timestamp.

4) From a contributor’s point of view for Maven, if you submit a pull request on GitHub, you don’t need to wait very long for the code to be merged. GitHub actions can run your code on other test env’s and provide the result to you. How convenient!

5) If a downloaded file fails the checksum check, the build will break. This was previously a warning. Also some other warning’s now are converted into build failures.