Open the file using Scanner
The file is read integer by integer.
This lesson explains a Java project that works with very large numeric data. We begin from absolute basics, then move into the active program, the backup recursive design, the actual Java code, dry runs, GitHub usage, and how to run the project in Google Colab.
Suppose we have a very large collection of integers. It might contain one crore numbers, which means ten million values. If the data is very large, reading and sorting everything together may become inconvenient. So this project explores file-based processing.
Instead of asking the computer to hold everything at once, we divide the work by files or chunks, process one piece at a time, and combine results later.
The active code computes local and global min-max across files. The backup code goes further and recursively breaks a giant file into smaller range-based files.
There are really two levels of thinking here: Level 1: Many files already exist → scan each file → find each file's min and max → combine results Level 2: One giant file exists → split by numeric midpoint → create child files → recurse until each child file is small enough
The current main program is not a full sorter. It reads many files, finds the min and max in each file, and then computes the overall min and max across all files.
Data folder
↓
Get all files
↓
For each file:
open file
read integers
compute local min-max
store FileData(file, mm)
↓
Compare all file summaries
↓
Print overall max and min
This method takes a folder path, creates a Java File object for that directory,
and returns the files inside it.
BillionsAndBillions.javapublic static File[] getAllFiles(String directory)
{
try
{
File f=new File(directory);
return f.listFiles();
}
catch(Exception ex)
{
System.out.println(ex);
return null;
}
}
ScannerThe file is read integer by integer.
That is why the boolean b exists.
Update max if larger; update min if smaller.
FileData objectThis stores the file and its local result.
BillionsAndBillions.javapublic static FileData getFileData(File file)
{
try
{
MaxMin mm=new MaxMin();
boolean b=false;
Scanner s=new Scanner(file);
while(s.hasNextInt())
{
int n=s.nextInt();
if(!b)
{
mm.max=n;
mm.min=n;
}
else
{
if(n>mm.max)
mm.max=n;
if(n
Initialization part
if(!b)
{
mm.max=n;
mm.min=n;
}
The first number is used to set both min and max.
Comparison part
else
{
if(n>mm.max)
mm.max=n;
if(n
Every later number is checked against the current min and max.
Dry run idea
If 0.txt contains values from 0 to 9, then the first value
sets both min and max to 0, and after scanning all values, max becomes 9
while min stays 0.
This method first gets all files, then scans each one, and stores the result in an array of
FileData objects.
BillionsAndBillions.javapublic static FileData[] getFilesData(String directory)
{
File[] files=getAllFiles(directory);
FileData[] filedata=new FileData[files.length];
for(int i=0;i<=files.length-1;i++)
{
File f=files[i];
FileData fd=getFileData(f);
filedata[i]=fd;
}
return filedata;
}
This method compares all the file-level summaries. It is correct, but it uses nested loops, which means it does more repeated work than necessary.
BillionsAndBillions.javapublic static MaxMin getTotalMaxMin(FileData[] fd)
{
boolean b=false;
int max=0;
int min=0;
for(int i=0;i<=fd.length-1;i++)
{
max=fd[i].mm.max;
min=fd[i].mm.min;
for(int j=0;j<=fd.length-1;j++)
{
if(fd[j].mm.max>max)
max=fd[j].mm.max;
if(fd[j].mm.min
Comparison logic
if(fd[j].mm.max>max)
max=fd[j].mm.max;
if(fd[j].mm.min
Returned final object
MaxMin mm=new MaxMin();
mm.max=max;
mm.min=min;
return mm;
Result for the sample chunk files
If the files are 0.txt through 9.txt with ranges 0–9,
10–19, and so on up to 90–99, then the final result is:
Max=99 ,Min=0
main()BillionsAndBillions.javapublic static void main(String[] args)
{
FileData[] data=getFilesData("Data");
for(FileData datum : data)
System.out.println(datum);
MaxMin totalmaxmin=getTotalMaxMin(data);
System.out.println(totalmaxmin);
}
FileData.javapublic class FileData
{
public java.io.File file;
public MaxMin mm;
public FileData(java.io.File file,MaxMin mm)
{
this.file=file;
this.mm=mm;
}
public String toString()
{
return "" + file + " , " + mm;
}
}
This stores the file and its corresponding MaxMin result.
MaxMin.javapublic class MaxMin
{
public int max,min;
public String toString()
{
return "Max=" + max + " ,Min=" + min;
}
}
This stores only two values: max and min.
The backup code is trying to solve a larger problem. Instead of just finding min and max in many files, it starts with one very large file and recursively breaks it into smaller files according to numeric range.
Generate huge file ↓ Read min, max, size from filename ↓ If size is already small enough → stop ↓ Else compute midpoint ↓ Split values into two child files ↓ Update child min, max, and size ↓ Delete parent file ↓ Rename child files with metadata ↓ Recurse on both child files
OneCroreBreakUp.javapublic static int getRandom(int lowerlimit,int upperlimit)
{
if(lowerlimit==upperlimit)
return lowerlimit;
if(lowerlimit>upperlimit)
{
int t=lowerlimit;
lowerlimit=upperlimit;
upperlimit=t;
}
int range=upperlimit-lowerlimit + 1;
int n=(int)(Math.random()*range);
return lowerlimit + n;
}
public static void saveArray(String onlyfilename,int n,int min,int max)
{
try
{
String filename=getFileName(onlyfilename + "0",min,max,n);
PrintWriter pw=new PrintWriter("Data\\\\" + filename);
for(int i=1;i<=n;i++)
{
String str="" + getRandom(min,max);
pw.println(str);
}
pw.flush();
pw.close();
}
catch(Exception ex)
{
System.out.println(ex);
}
}
public static String getFileName(String filename,int min,int max,int size)
{
return filename + "," + min + "," + max + "," + size;
}
Example result: Data0,-1000,1000,10000000
public static FileData getDataFromFileName(String fullfilename)
{
String[] strings=fullfilename.split(",");
String filename=strings[0];
int min=Integer.parseInt(strings[1]);
int max=Integer.parseInt(strings[2]);
int size=Integer.parseInt(strings[3]);
return new FileData(min,max,size,filename,fullfilename);
}
FileData.javapublic class FileData
{
public int min,max,size;
public String filename,fullfilename;
public FileData(int min,int max,int size,String filename,String fullfilename)
{
this.min=min;
this.max=max;
this.size=size;
this.filename=filename;
this.fullfilename=fullfilename;
}
public String toString()
{
return "Min = " + min + ", Max = " + max + ", Size = " + size + ", FileName = " + filename + ", FullFileName = " + fullfilename;
}
}
breakTheFile()It checks if a file is already small enough. If not, it computes the midpoint of the numeric range, sends lower values into one child file and greater-or-equal values into another child file, updates metadata while writing, deletes the old file, and then recurses on the two new files.
OneCroreBreakUp.javapublic static void breakTheFile(String filename,int maxsize)
{
try
{
FileData fd=getDataFromFileName(filename);
if(fd.sizemax1)
max1=x;
if(xmax2)
max2=x;
if(x0)
{
pw1.flush();
pw1.close();
}
if(n2>0)
{
pw2.flush();
pw2.close();
}
s.close();
currentfile.delete();
String filename1=getFileName("" + fileno++,min1,max1,n1);
String filename2=getFileName("" + fileno++,min2,max2,n2);
totalfiles++;
f1.renameTo(new File("Data\\\\" + filename1));
System.out.println("File " + totalfiles);
totalfiles++;
f2.renameTo(new File("Data\\\\" + filename2));
System.out.println("File " + totalfiles);
if(n1>0)
breakTheFile(filename1,maxsize);
if(n2>0)
breakTheFile(filename2,maxsize);
}
catch(Exception ex)
{
System.out.println(ex);
System.exit(0);
}
}
FileData fd=getDataFromFileName(filename); if(fd.size
if(x
If the file range is -1000 to 1000, then avg = 0.
So values like -700 and -2 go left. Values like 0,
15, and 999 go right.
OneCroreBreakUp.javapublic static void main(String[] args)
{
saveArray("Data",10000000,-1000,1000);
breakTheFile("Data0,-1000,1000,10000000",25000);
}
Create a file containing ten million random integers between -1000 and 1000.
Keep breaking that file until every resulting file has fewer than 25,000 numbers.
This is not the active large-file engine, but it demonstrates counting sort on a normal in-memory array.
Counting.javaclass Counting
{
public static void main(String[ ] args)
{
int max=0;
int b[ ];
int[] a={21,3,54,10,54,67,89,21};
for(int i=0;i<=a.length-1;i++)
{
if(max=0;i--)
{
int value=a[i];
int pos=f[value];
f[value]--;
pos--;
b[pos]=value;
}
for(int i=0;i<=a.length-1;i++)
a[i]=b[i];
}
}
Replace this dummy link with your real repository later.
Store the Java source code, version the project, publish docs and lesson pages, and use GitHub Actions to compile and test the Java project automatically.
GitHub Pages is for static content such as HTML, CSS, and JavaScript. It is a good place for your lesson page, project explanation, screenshots, and download links, but not for hosting a live Java backend.
Put your Java project code in the GitHub repository. Put this HTML lesson in the same repository or in a docs branch/folder. Use GitHub Pages for the lesson page, and GitHub Actions for Java build/test automation.
name: Java Build
on:
push:
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '17'
- name: Compile Java files
run: javac *.java
<section class="card">
<h2>Project Repository</h2>
<p>Replace this dummy link with your real GitHub repository.</p>
<a
href="https://github.com/your-username/your-repository"
target="_blank"
rel="noopener"
class="btn btn-primary"
>
View Project on GitHub
</a>
</section>
Yes. A Colab notebook is a Linux-based environment, so you can compile and run Java using shell commands. The usual flow is: check Java → upload ZIP → unzip → compile → run.
!java -version
from google.colab import files files.upload()
!unzip "One Crore Sorting.zip"
!javac *.java
!java BillionsAndBillions
%%writefile HelloWorld.java
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello from Java in Colab!");
}
}
!javac HelloWorld.java
!java HelloWorld
If your ZIP contains multiple folders with duplicate class names, compile one target folder at a time. Otherwise Java compilation may clash.
# 1. Check Java !java -version # 2. Upload the zip from google.colab import files files.upload() # 3. Unzip project !unzip "One Crore Sorting.zip" # 4. Optional: see Java files !find . -name "*.java" # 5. Compile top-level Java files !javac *.java # 6. Run active main class !java BillionsAndBillions # 7. Optional backup runs # !java OneCroreBreakUp # !java Counting
Here N is the total number of integers and F is the number of files.
Here R is the numeric range being split recursively.
Good large-data thinking, file-wise processing, clean local summaries, and a smart recursive range-based design in the backup folder.
The active code does not fully sort the whole dataset. The global combine method is more repetitive than needed, and the backup design would still need a final production-ready sort/merge strategy if full ordering is desired.
b in getFileData()?This project shows how very large numeric data can be processed through files: the active code computes local and global min-max values, while the backup design recursively partitions a giant file into smaller range-based files.
Use GitHub for source control and GitHub Actions for Java build/test automation. Use GitHub Pages for this lesson. Use Colab for quick demos, teaching, and simple compile-run workflows.
Add a proper final sorting or merge stage so the backup design becomes a more complete external sorting system.