Java Socket programming-Transferring directory through socket in Java

So far we have discussed the fundamentals of Java networking .We also discussed about TCP and UDP methods of communication.In the previous chapter we have seen how to transfer a file between two machines in a network through TCP Socket. In this chapter we are discussing how transferring the contents of  directory or folder  through socket in Java  is possible.

Transferring directory through socket in Java – example

We have a client and a server applications.The directory is transferring from client to server. The client scans the source directory for individual files. It sends each file as an object . The object also contains the details of file like  file name , file size etc.The server receives each object and it is creating  and writing those files in the specified destination directory. Let us examine the FileEvent.java whose object contains the file along with the necessary metadata related with that file.The client sends the objects of FileEvent to server.

FileEvent.java

import java.io.Serializable;

public class FileEvent implements Serializable {

public FileEvent() {
}

private static final long serialVersionUID = 1L;

private String destinationDirectory;
private String sourceDirectory;
private String filename;
private long fileSize;
private byte[] fileData;
private String status;
private int remainder;

public String getDestinationDirectory() {
return destinationDirectory;
}

public void setDestinationDirectory(String destinationDirectory) {
this.destinationDirectory = destinationDirectory;
}

public String getSourceDirectory() {
return sourceDirectory;
}

public void setSourceDirectory(String sourceDirectory) {
this.sourceDirectory = sourceDirectory;
}

public String getFilename() {
return filename;
}

public void setFilename(String filename) {
this.filename = filename;
}

public long getFileSize() {
return fileSize;
}

public void setFileSize(long fileSize) {
this.fileSize = fileSize;
}

public String getStatus() {
return status;
}

public void setStatus(String status) {
this.status = status;
}

public byte[] getFileData() {
return fileData;
}

public void setFileData(byte[] fileData) {
this.fileData = fileData;
}

public int getRemainder() {
return remainder;
}

public void setRemainder(int remainder) {
this.remainder = remainder;
}
}

The FileEvent.java should implement the Serializable interface.The reason is explained in an earlier chapter.

Now lets see the Server.java.It is accepting socket connection from client. And after getting connected , it is receving FileEvent objects continuously till the last file is received.(The FileEvent object of last file has remainder attribute value as zero).After receiving all files  the server exits itself.

import java.net.ServerSocket;
import java.net.Socket;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class Server {
private ServerSocket serverSocket = null;
private Socket socket = null;
private ObjectInputStream inputStream = null;
private FileEvent fileEvent;
private File dstFile = null;
private FileOutputStream fileOutputStream = null;

public Server() {

}

/**
* Accepts socket connection
*/
public void doConnect() {
try {
serverSocket = new ServerSocket(4445);
socket = serverSocket.accept();
inputStream = new ObjectInputStream(socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* Reading the FileEvent object and copying the file to disk.
*/
public void downloadFiles() {
while (socket.isConnected()) {
try {
fileEvent = (FileEvent) inputStream.readObject();
if (fileEvent.getStatus().equalsIgnoreCase("Error")) {
System.out.println("Error occurred ..with file" + fileEvent.getFilename() + "at sending end ..");

}
String outputFile = fileEvent.getDestinationDirectory() + fileEvent.getFilename();
if (!new File(fileEvent.getDestinationDirectory()).exists()) {
new File(fileEvent.getDestinationDirectory()).mkdirs();
}
dstFile = new File(outputFile);
fileOutputStream = new FileOutputStream(dstFile);
fileOutputStream.write(fileEvent.getFileData());
fileOutputStream.flush();
fileOutputStream.close();
System.out.println("Output file : " + outputFile + " is successfully saved ");
if (fileEvent.getRemainder() == 0) {
System.out.println("Whole directory is copied...So system is going to exit");
System.exit(0);
}

} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Server server = new Server();
server.doConnect();
server.downloadFiles();
}
}

Now its the time to see the client application.It is   connecting to server.And creating FileEvent objects for each file in the source directory and sending to server application.The source path destination path , host name etc are specific to each need.

import java.io.*;
import java.net.Socket;

public class Client {
private Socket socket = null;
private boolean isConnected = false;
private ObjectOutputStream outputStream = null;
private String sourceDirectory = "E:/temp/songs";
private String destinationDirectory = "C:/tmp/downloads/";
private int fileCount = 0;
private FileEvent fileEvent = null;

public Client() {

}

public void connect() {
while (!isConnected) {
try {
socket = new Socket("localHost", 4445);
outputStream = new ObjectOutputStream(socket.getOutputStream());
isConnected = true;
} catch (IOException e) {
e.printStackTrace();
}
}
}

public void locateFiles() {
File srcDir = new File(sourceDirectory);
if (!srcDir.isDirectory()) {
System.out.println("Source directory is not valid ..Exiting the client");
System.exit(0);
}
File[] files = srcDir.listFiles();
fileCount = files.length;
if (fileCount == 0) {
System.out.println("Empty directory ..Exiting the client");
System.exit(0);
}

for (int i = 0; i < fileCount; i++) { System.out.println("Sending " + files[i].getAbsolutePath()); sendFile(files[i].getAbsolutePath(), fileCount - i - 1); System.out.println(files[i].getAbsolutePath()); } } public void sendFile(String fileName, int index) { fileEvent = new FileEvent(); fileEvent.setDestinationDirectory(destinationDirectory); fileEvent.setSourceDirectory(sourceDirectory); File file = new File(fileName); fileEvent.setFilename(file.getName()); fileEvent.setRemainder(index); DataInputStream diStream = null; try { diStream = new DataInputStream(new FileInputStream(file)); long len = (int) file.length(); byte[] fileBytes = new byte[(int) len]; int read = 0; int numRead = 0; while (read < fileBytes.length && (numRead = diStream.read(fileBytes, read, fileBytes.length - read)) >= 0) {
read = read + numRead;
}
fileEvent.setFileData(fileBytes);
fileEvent.setStatus("Success");
} catch (Exception e) {
e.printStackTrace();
fileEvent.setStatus("Error");

}

try {
outputStream.writeObject(fileEvent);
} catch (IOException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
Client client = new Client();
client.connect();
client.locateFiles();
}
}

Output

Run both client and server after giving correct source directory , destination directory and host address in client application.The status will be displayed in console for both the applications.When the transfer completes both applications exits.

See also:

Networking in Java -Overview

TCP communication in Java

UDP communication in Java

Chat application in Java using socket programming

Transferring Java object through socket

Transferring file through socket