---
description: In this lab, we are going to talk about Binary I/O and how we can manipulate binary files, we should know that every file in your computer is a binary file, but the files that contain binary which represents a text will be considered as text files as they are very common.
---
<h1 style='border: none'><center>Programming II Lab 9</center></h1>
<h2 style='border: none'><center>Binary I/O</center></h2>
<h5><center>The Islamic University of Gaza<br>Engineering Faculty<br>Department of Computer Engineering</center></h5>
<h6>Author: Mohammed Nafiz ALMadhoun<span style="float:right">2021/04/17</span></h6>
---
<p style='text-align:justify'>
In this lab, we are going to talk about Binary I/O and how we can manipulate binary files, we should know that every file in your computer is a binary file, but the files that contain binary which represents a text will be considered as text files as they are very common.
</p>
## Viewing Files as Binary
You can view any file as a binary file using a `Hex Editor`, which is a program that will display the binary data of a file, you could also see your whole hard drive or ram as a big binary chunk.
You could use this [online hex editor](https://hexed.it/), or you could install a program such as [HxD](https://mh-nexus.de/en/hxd/).
<center>

The binary data of an Image.
</center>
**Note:** We read binary data as hex because it's easier for us, and programs usually store data as bytes (two hex digits).
## Binary I/O Classes
The main classes for reading and writing as binary is `InputStream`, and `OutputStream`, these two abstract classes define the common methods for writing or reading binary data (which could be something other than files).
Please read the documentation here:
https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html
https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html
As an example, we will take a look at the `FileOutputStraem` class which will output the binary data to a file.
#### Example 1
```java=
import java.io.*;
public class Test{
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("testfile.bin");
fos.write(0x10);
fos.write(0x20);
fos.write(0x30);
fos.close();
}
}
```
And here's the file in a hex editor:
<center>

Example 1 Output
</center>
Now we could use `FileInputStream` to read the data from that file.
## Data Streams
So it's useful to write data byte by byte, but sometimes we need something bigger than a byte, something like `int`, or `float`, we could do that by hand but there is an easier way, to use `DataInputStraem` and `DataOutputStream` classes.
Please take a look at the documentation here:
https://docs.oracle.com/javase/8/docs/api/java/io/DataOutputStream.html
https://docs.oracle.com/javase/8/docs/api/java/io/DataInputStream.html
### Example 2
```java=
import java.io.*;
public class Test{
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("testfile.bin");
DataOutputStream dos = new DataOutputStream(fos);
for (int i=1000000;i<1010000;i++){
dos.writeInt(i);
}
dos.close();
fos.close();
}
}
```
Notice that we've created a `FileOutpuStream`, then we've constructed the `DataOutputStream` using that object because we could write data to something other than a file (e.g. a network packet!).
So this file will contain the numbers from `1000000` to `1010000`, and the output size will be `40,000` bytes because each `int` will take four bytes.
Now if we created a text file with the same data, it will take about `90,000` bytes.
**Writing binary data to a binary file is faster in writing and reading, and take much lower space.**
### Example 3
In this example, we will save and read the data of students using `DataOuptutStream` and `DataInputStream`.
#### Student Class
```java=
public class Student {
private String name;
private float gpa;
public Student(String name, float gpa) {
this.name = name;
this.gpa = gpa;
}
public Student(DataInputStream dataStream) throws IOException{
name = dataStream.readUTF();
gpa = dataStream.readFloat();
}
public void saveToStream (DataOutputStream dataStream) throws IOException{
dataStream.writeUTF(name);
dataStream.writeFloat(gpa);
}
public void printDetails(){
System.out.printf("Name: %s%n", name);
System.out.printf("GPA : %.2f%n", gpa);
}
}
```
#### Saving Data
```java=
Student[] students = {
new Student("Mohammed ALMadhoun", 60),
new Student("Test 1", 70.1f),
new Student("Test 2", 95.2f),
new Student("Test 3", 50.5f),
};
try(FileOutputStream fos = new FileOutputStream("students.bin")){
try(DataOutputStream dos = new DataOutputStream(fos)){
dos.writeInt(students.length); // Write the length of the array!
for (Student s : students){
s.saveToStream(dos);
}
}
}
```
#### Reading Data
```java=
Student[] students = null;
try(FileInputStream fis = new FileInputStream("students.bin")){
try(DataInputStream dis = new DataInputStream(fis)){
students = new Student[dis.readInt()];
for (int i=0;i<students.length;i++){
Student s = new Student(dis);
s.printDetails();
students[i] = s;
}
}
}
```
## Object Streams
In this section, we will try to use `ObjectOutpuStream`, and `ObjectInputStraem`, which are classes that help us automatically serialize an object, so the previous example will be trivial and it will help you a lot if you want to save the data of a certain object.
A serializable class should implement the interface `Serializable`, which will tell the output stream that this class could be serialized.
### Example 4
In this example, we will create the previous example using Object Streams.
#### Student Class
```java=
public class Student implements Serializable {
private String name;
private float gpa;
public Student(String name, float gpa) {
this.name = name;
this.gpa = gpa;
}
public void printDetails(){
System.out.printf("Name: %s%n", name);
System.out.printf("GPA : %.2f%n", gpa);
}
}
```
#### Saving Data
```java=
Student[] students = {
new Student("Mohammed ALMadhoun", 60),
new Student("Test 1", 70.1f),
new Student("Test 2", 95.2f),
new Student("Test 3", 50.5f),
};
try(FileOutputStream fos = new FileOutputStream("students.bin")){
try(ObjectOutputStream oos = new ObjectOutputStream(fos)){
oos.writeObject(students);
}
}
```
#### Reading Data
```java=
Student[] students = null;
try(FileInputStream fis = new FileInputStream("students.bin")){
try(ObjectInputStream ois = new ObjectInputStream(fis)){
students = (Student[]) ois.readObject();
for (int i=0;i<students.length;i++){
students[i].printDetails();
}
}
}
```
## Random Access File
Notice that in the previous examples, we access the data sequentially, but sometimes we need to access the data in a random way (which means we will read whatever address we want).
Notice that Random Access File is not an output or input stream, it's not a stream.
Notice that the constructor of a RandomAccessFile contains the file path and a mode, the mode specifies if you want to read, read-write, or write to that file.
Please take a look at the documentation:
https://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html
### Example 5
```java=
public class Test{
public static void main(String[] args) throws Exception {
try (RandomAccessFile raf = new RandomAccessFile("testfile.bin", "r")){
System.out.println(raf.readInt());
System.out.println(raf.readInt());
raf.seek(4 * 100);
System.out.println(raf.readInt());
System.out.println(raf.readInt());
raf.seek(4 * 2);
System.out.println(raf.readInt());
System.out.println(raf.readInt());
}
}
}
```
Notice that we are reading the output file of Example 1.
The seek method will move the file pointer to a certain location in the file.
**Q: What should be the output of this program?**
## Lab Tasks
### Task 1: Create a Hex Dump program
In this task, you should create a program that takes a file name as an argument, and prints the hex dump of it, here is an example of my solution:
<center>

Task 1 Expected Ouptut
</center>
### Task 2: Data Recovery program
In this task, you should create a data recovery program, which will recover files from the hard disk after deleting it, these programs will search for something called **file signature** which is something that identifies files, then they extract that file from the hard disk binary.
Take a look here: https://en.wikipedia.org/wiki/List_of_file_signatures
Your program should take a file as input (to avoid destroying your hard drive you will read a file), and output what files it finds.
The program should extract PDF files, PDF files will always start with these bytes:
`25 50 44 46`
And end with these bytes:
`25 25 45 4F`
Your program should search for this pattern and extract the PDF files from this dump file:
https://drive.google.com/file/d/1BaPR6Qg6_Xwjt7C7uQ4Um93bgqO8fqY8/view?usp=sharing
This dump file contains 2 pdf files, so your program should output two files!
###### tags: `Programming` `Java` `IUG`
<center>End Of Lab 9</center>