how to read different files in differents runnable threads Java - java

I need to read all .txt files in a folder with 4 Threads running at the same time. What can I do so each thread reads a different file. Ex: Thread 1 reads file 1, Thread 2 reads file 2... and so on until there's no more files to read.
Thread h;
public Hilo(){
h= new Thread(this,"Hilo 1");
h.start();
}
public void run(){
int contador;
File folder = new File("C:/Users/Jose/Desktop/java");
File[] listOfFiles = folder.listFiles();
for (File file : listOfFiles) {
if (file.isFile()) {
contador=0;
int i=0;
//System.out.println(file.getName());
Scanner scan = null;
try {
scan = new Scanner (file);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (scan.hasNext()){
String linea=scan.next();
String[] lineas = linea.split("(?=[,.])|\\s+");
if (Palindrome.is(lineas[i])){
contador++;
}
}
scan.close();
}
}
}

Try it:
1. Create a class ReadFiles:
public class ReadFiles {
public interface IEvents {
void onFile(File file);
}
int maxConcurrentThread = 5;
ThreadPoolExecutor pool = null;
volatile int countFiles = 0;
String folder = "";
IEvents event = null;
public ReadFiles(String folder, int maxConcurrentThread) {
this.folder = folder;
this.maxConcurrentThread = maxConcurrentThread;
}
public void setEvent(IEvents event) {
this.event = event;
}
public void read() {
ThreadPoolExecutor pool = (ThreadPoolExecutor) Executors.newFixedThreadPool(this.maxConcurrentThread);
File ffolder = new File(folder);
File[] listOfFiles = ffolder.listFiles();
for (final File file : listOfFiles) {
if (file.isFile()) {
pool.execute(new Runnable() {
#Override
public void run() {
countFiles++;
event.onFile(file);
}
});
}
}
pool.shutdown();
}
}
How to use:
int maxConcurrentThread = 5;
ReadFiles read = new ReadFiles("C:/Users/Jose/Desktop/java", maxConcurrentThread);
read.setEvent(new ReadFiles.IEvents() {
#Override
public void onFile(File file) {
Scanner scan = null;
try {
scan = new Scanner(file);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (scan.hasNext()) {
String linea = scan.next();
String[] lineas = linea.split("(?=[,.])|\\s+");
if (Palindrome.is(lineas[i])) {
contador++;
}
}
scan.close();
}
});
read.read();

package z;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
public static void main(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(4);
File folder = new File("C:/Users/Jose/Desktop/java");
File[] files = folder.listFiles();
for(File file : files){
exec.execute(new Worker(file));
}
}
}
class Worker implements Runnable {
private File file;
public Worker(File file) {
this.file = file;
}
#Override
public void run() {
int contador;
if (file.isFile()) {
contador = 0;
int i = 0;
Scanner scan = null;
try {
scan = new Scanner(file);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (scan.hasNext()) {
String linea = scan.next();
String[] lineas = linea.split("(?=[,.])|\\s+");
if (Palindrome.is(lineas[i])) {
contador++;
}
}
scan.close();
}
}
}

This is the code, without the palindromo method, its not necesary.
public class main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Hilo numero1 = new Hilo();
Hilo numero2 = new Hilo();
Hilo numero3 = new Hilo();
Hilo numero4 = new Hilo();
}
}
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Hilo implements Runnable {
Thread h;
public Hilo() {
h = new Thread(this, "Hilo 1");
h.start();
}
public void run() {
int c = 0;
int contador;
File folder = new File("C:/Users/Jose/Desktop/java");
File[] listOfFiles = folder.listFiles();
for (File file : listOfFiles) {
if (file.isFile()) {
contador = 0;
int i = 0;
//System.out.println(file.getName());
Scanner scan = null;
try {
scan = new Scanner(file);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (scan.hasNext()) {
String linea = scan.next();
String[] lineas = linea.split("(?=[,.])|\\s+");
if (Palindromo.es(lineas[i])) {
contador++;
}
c++;
}
scan.close();
System.out.println("La cantidad de Palindromos en el archivo " + file + " es de: " + contador);
}
}
}
}

Related

How to write multithread into a single text file?

I want to write both threads on a single text file, but it came out only the PrintNum part and PrintChar is not in the text file?
How to write both threads into a single file?
Is there any way to combine both threads into a class so that it would come out to a single file?
This is my code:
import java.io.FileNotFoundException;
import java.io.PrintWriter;
public class Multithread {
public static void main(String[] args) {
Runnable printA = new PrintChar('a', 500);
Runnable print100 = new PrintNum(500);
Thread thread1 = new Thread(printA);
Thread thread2 = new Thread(print100);
thread1.start();
thread2.start();
}
}
class PrintChar implements Runnable {
private char charToPrint;
private int times;
public PrintChar(char c, int t) {
charToPrint = c;
times = t;
}
#Override
public void run() {
String fileName = "out.txt";
try {
PrintWriter outputStream = new PrintWriter(fileName);
for (int i = 0; i < times; i++) {
outputStream.print(charToPrint);
}
outputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
class PrintNum implements Runnable {
private int lastNum;
public PrintNum(int n) {
lastNum = n;
}
#Override
public void run() {
String fileName = "out.txt";
try {
PrintWriter outputStream = new PrintWriter(fileName);
for (int i = 1; i <= lastNum; i++) {
outputStream.print(" " + i);
}
outputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
Try this. Here I use append to file in print writer. I didn't do many changes to your code.
import java.io.*;
public class Multithread {
public static void main(String[] args) throws FileNotFoundException {
String fileName = "out.txt";
new PrintWriter(fileName).close();//to clear the text of the file
Runnable printA = new PrintChar('a', 500);
Runnable print100 = new PrintNum(500);
Thread thread1 = new Thread(printA);
Thread thread2 = new Thread(print100);
thread1.start();
thread2.start();
}
}
class PrintChar implements Runnable {
private char charToPrint;
private int times;
public PrintChar(char c, int t) {
charToPrint = c;
times = t;
}
#Override
public void run() {
String fileName = "out.txt";
try {
synchronized (Multithread.class) {//to writ by one thread
FileWriter fw = new FileWriter(fileName, true);
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter outputStream = new PrintWriter(bw);
for (int i = 0; i < times; i++) {
outputStream.print(charToPrint);
}
outputStream.close();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
class PrintNum implements Runnable {
private int lastNum;
public PrintNum(int n) {
lastNum = n;
}
#Override
public void run() {
String fileName = "out.txt";
try {
synchronized (Multithread.class) {//to write by one thread
FileWriter fw = new FileWriter(fileName, true);
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter outputStream = new PrintWriter(bw);
for (int i = 1; i <= lastNum; i++) {
outputStream.print(" " + i);
}
outputStream.close();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}

Variable declaration from one class to another

the below codes are working fine(individually) i just want to pass letter[i] value from FindDrive class to Ziputils input file location such that i can zip pendrive data automatically.
FindDrive Class
package com.prosper;
import java.io.File;
public class FindDrive
{
/**
* Application Entry Point
*/
public static void main(String[] args)
{
String[] letters = new String[]{ "A", "B", "C", "D", "E", "F", "G", "H", "I"};
File[] drives = new File[letters.length];
boolean[] isDrive = new boolean[letters.length];
// init the file objects and the initial drive state
for ( int i = 0; i < letters.length; ++i )
{
drives[i] = new File(letters[i]+":/");
isDrive[i] = drives[i].canRead();
}
System.out.println("FindDrive: waiting for devices...");
// loop indefinitely
while(true)
{
// check each drive
for ( int i = 0; i < letters.length; ++i )
{
boolean pluggedIn = drives[i].canRead();
// if the state has changed output a message
if ( pluggedIn != isDrive[i] )
{
if ( pluggedIn ){
System.out.println("Drive "+letters[i]+" has been plugged in");
}
else
System.out.println("Drive "+letters[i]+" has been unplugged");
isDrive[i] = pluggedIn;
}
}
// wait before looping
try { Thread.sleep(100); }
catch (InterruptedException e) { /* do nothing */ }
}
}
}
The ZipUtils Class
package com.prosper;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class ZipUtils {
private List <String> fileList;
private static final String OUTPUT_ZIP_FILE = "E:\\appu\\Folder.zip";
private static final String SOURCE_FOLDER = "E:\\appu\\"; //SourceFolder
public ZipUtils() {
fileList = new ArrayList < String > ();
}
public static void main(String[] args) {
ZipUtils appZip = new ZipUtils();
appZip.generateFileList(new File(SOURCE_FOLDER));
appZip.zipIt(OUTPUT_ZIP_FILE);
}
public void zipIt(String zipFile) {
byte[] buffer = new byte[1024];
String source = new File(SOURCE_FOLDER).getName();
FileOutputStream fos = null;
ZipOutputStream zos = null;
try {
fos = new FileOutputStream(zipFile);
zos = new ZipOutputStream(fos);
System.out.println("Output to Zip : " + zipFile);
FileInputStream in = null;
for (String file: this.fileList) {
System.out.println("File Added : " + file);
ZipEntry ze = new ZipEntry(source + File.separator + file);
zos.putNextEntry(ze);
try {
in = new FileInputStream(SOURCE_FOLDER + File.separator + file);
int len;
while ((len = in .read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
} finally {
in.close();
}
}
zos.closeEntry();
System.out.println("Folder successfully compressed");
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
zos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void generateFileList(File node) {
// add file only
if (node.isFile()) {
fileList.add(generateZipEntry(node.toString()));
}
if (node.isDirectory()) {
String[] subNote = node.list();
for (String filename: subNote) {
generateFileList(new File(node, filename));
}
}
}
private String generateZipEntry(String file) {
return file.substring(SOURCE_FOLDER.length() + 1, file.length());
}
}
To pass data from one class to another, you can do the following:
1) Create an object of the class in your FindDrive class:
ZipUtils utils = new ZipUtils();
2) Pass the value to the method of that class:
utils.zipIt(letter[i])
I have inserted a few statements, which create a new object of ZipUtils class and call the method, however I do suggest you looking into Dependency Injection as well, if you want to improve your code quality here
package com.prosper;
import java.io.File;
public class FindDrive {
/**
* Application Entry Point
*/
public static void main(String[] args) {
String[] letters = new String[] {"A", "B", "C", "D", "E", "F", "G",
"H", "I"};
ZipUtils utils;
File[] drives = new File[letters.length];
boolean[] isDrive = new boolean[letters.length];
// init the file objects and the initial drive state
for (int i = 0; i < letters.length; ++i) {
drives[i] = new File(letters[i] + ":/");
isDrive[i] = drives[i].canRead();
}
System.out.println("FindDrive: waiting for devices...");
// loop indefinitely
while (true) {
// check each drive
for (int i = 0; i < letters.length; ++i) {
boolean pluggedIn = drives[i].canRead();
utils = new ZipUtils();
utils.changeDirectory(letters[i]);
// if the state has changed output a message
if (pluggedIn != isDrive[i]) {
if (pluggedIn) {
System.out.println("Drive " + letters[i] + " has been plugged in");
} else {
System.out.println("Drive " + letters[i] + " has been unplugged");
}
isDrive[i] = pluggedIn;
}
}
// wait before looping
try {
Thread.sleep(100);
} catch (InterruptedException e) { /* do nothing */ }
}
}
}
To make changes to SOURCE_FOLDER after declaration, you need to make sure its not a constant i.e it is not final.
Add a method in ZipUtils:
private static String source_folder = "E:\\appu\\"; //SourceFolder
public void changeDirectory(String zip) {
source_folder = zip + ":\\";
}

JavaFX Update TextField in Loop

I have a problem with my application JavaFX.
Image: https://picload.org/image/rlwpwdgi/javafx.png
With the button (1) showing the second window.
With the key (2) start the search in a path.
I need that the TextField (3) update as searching finds files.
In the Controller class of the second window, the button (2) perform this method.
public void startSuchen() {
String text = textFieldPfad.getText();
if (text.length() > 0) {
dateiGef = 0;
dateiGes = 0;
listf(pfad);
textFieldDateiGef.setText(String.valueOf(dateiGef));
textFieldDateiGes.setText(String.valueOf(dateiGes));
}
}
And this is the procedure listf:
private void listf(File directory) {
try {
File[] fileList = directory.listFiles();
for (File file : fileList) {
// Platform.runLater(new Runnable() {
// #Override
// public void run() {
// textFieldDateiGef.setText(String.valueOf(getDateiGef()));
// textFieldDateiGes.setText(String.valueOf(getDateiGes()));
// }
// });
// Thread thrd = new Thread() {
// public void run() {
// Platform.runLater(new Runnable() {
// #Override
// public void run() {
// textFieldDateiGef.setText(String.valueOf(getDateiGef()));
// textFieldDateiGes.setText(String.valueOf(getDateiGes()));
// }
// });
// }
// };
// thrd.start();
if (file.isFile()) {
dateiGes += 1;
String fileName = file.getName().toLowerCase();
String nome = textFieldName.getText().toLowerCase();
Pattern r = Pattern.compile(nome);
Matcher m = r.matcher(fileName);
if (m.find()) {
dateiGef += 1;
}
} else if (file.isDirectory()) {
listf(file);
}
}
} catch (NullPointerException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
The commented lines are my tests to update the GUI, I also tried with the Task, but unfortunately it does not work. Someone please help me understand why?
Here is the solution:
public void startSuchen() {
String text = textFieldPfad.getText();
if (text.length() > 0) {
dateiGef = 0;
dateiGes = 0;
// Solution
new Thread(() -> listf(pfad)).start();
// End Solution
textFieldDateiGef.setText(String.valueOf(dateiGef));
textFieldDateiGes.setText(String.valueOf(dateiGes));
}
}
And this is the procedure listf:
private void listf(File directory) {
try {
File[] fileList = directory.listFiles();
for (File file : fileList) {
// Solution
Platform.runLater(new Runnable() {
#Override
public void run() {
textFieldDateiGef.setText(String.valueOf(getDateiGef()));
textFieldDateiGes.setText(String.valueOf(getDateiGes()));
}
});
// End Solution
if (file.isFile()) {
dateiGes += 1;
String fileName = file.getName().toLowerCase();
String nome = textFieldName.getText().toLowerCase();
Pattern r = Pattern.compile(nome);
Matcher m = r.matcher(fileName);
if (m.find()) {
dateiGef += 1;
}
} else if (file.isDirectory()) {
listf(file);
}
}
} catch (NullPointerException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
Many thanks to James_D

Parallel Read and write application in java

I am developing an application in java where i am using a shared LinkedBlocking Queue and i am creating multiple threads for reading and writing it. I have created the code as below but i am unable to get the desired result.
For result i am using a shared file which is being written by both the threads (read and write one).
Please tell me whats wrong in my code:
Message Reader.java
package com.aohandling.messagereader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.aohandling.messagequeue.MessageQueue;
public class MessageReader implements Runnable
{
public static BufferedWriter out;
public static void init()
{
file = new File("AOHandle.txt");
try
{
out = new BufferedWriter(new FileWriter(file, true));
System.out.println("Init ");
}
catch (IOException e)
{
e.printStackTrace();
}
}
static File file = null;
public void run()
{
while (true)
{
try
{
SimpleDateFormat ft = new SimpleDateFormat("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
String s = MessageQueue.getMessageQueue().poll();
if (s != null)
{
out.write("queue - " + MessageQueue.getMessageQueue().poll() + "---" + ft.format(new Date()) + "\n");
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
MessageWriter.java
package com.aohandling.writer;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.aohandling.messagequeue.MessageQueue;
import com.aohandling.messagereader.MessageReader;
public class MessageWriter implements Runnable
{
int n;
private int messageSequence;
public MessageWriter(int messageSequence)
{
this.messageSequence = messageSequence;
}
public void run()
{
try
{
SimpleDateFormat ft = new SimpleDateFormat("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
MessageReader.out.append("Writing----AO - " + this.messageSequence + "-----" + ft.format(new Date()) + "\n");
MessageQueue.getMessageQueue().put("AO " + this.messageSequence);
}
catch (IOException | InterruptedException e)
{
e.printStackTrace();
}
}
}
MessageQueue.java
package com.aohandling.messagequeue;
import java.util.concurrent.LinkedBlockingQueue;
public class MessageQueue {
private static LinkedBlockingQueue<String> messageQueue = new LinkedBlockingQueue<String>();
public static LinkedBlockingQueue<String> getMessageQueue() {
return MessageQueue.messageQueue;
}
public static void setMessageQueue(LinkedBlockingQueue<String> messageQueue) {
MessageQueue.messageQueue = messageQueue;
}
}
TestAOHandlingRead.java
package com.aohandling.main;
import com.aohandling.messagereader.MessageReader;
import com.aohandling.writer.MessageWriter;
public class TestAOHandlingRead
{
/**
* #param args
*/
public static void main(String[] args)
{
MessageReader.init();
for (int i = 0; i <= 200; i++)
{
Thread readThread = new Thread(new MessageReader());
readThread.start();
}
write();
}
public static void write()
{
for (int i = 0; i <= 20; i++)
{
if (i % 2 == 0)
{
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
Thread writeThread = new Thread(new MessageWriter(i));
writeThread.start();
}
}
}
TestAOHandlingWrite.java
package com.aohandling.main;
import java.util.concurrent.atomic.AtomicInteger;
import com.aohandling.writer.MessageWriter;
public class TestAOHandlingWrite {
int count = 0;
public int getCount()
{
return count;
}
/**
* #param args
*/
public static void main(String[] args) {
// MessageWriter.init();
for (int i=0; i<= 20; i++) {
if (i%2 ==0) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Thread writeThread = new Thread(new MessageWriter(i));
writeThread.start();
}
}
}
I suggest that you will use a FileChannel, since File channels are safe for use by multiple concurrent threads. In addition I refactored your code, the channel to your file will be created once, during the the first load of MessageReader class by the class loader.
public class MessageReader implements Runnable {
private static FileChannel channel;
static {
try {
System.out.println("Init ");
FileOutputStream fileOutputStream = new FileOutputStream(
"AOHandle.txt", true);
FileChannel channel = fileOutputStream.getChannel();
System.out.println("Init ");
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
while (true) {
FileLock fileLock = null;
try {
SimpleDateFormat ft = new SimpleDateFormat(
"E yyyy.MM.dd 'at' hh:mm:ss a zzz");
String s = MessageQueue.getMessageQueue().poll();
if (s != null) {
String message = "queue - "
+ MessageQueue.getMessageQueue().poll() + "---"
+ ft.format(new Date()) + "\n";
fileLock = channel.lock();
channel.write(ByteBuffer.wrap(message.getBytes()));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileLock != null) {
fileLock.release();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
The best practice is to open a channel to a file in one place and share him between your threads, since in your code no one closes the file.

program to show a progress bar while transferring all files from one server to another in java

i have written a java code to transfer files from one server to another using the concept of socket programming. now in the same code i also want to check for the network connection availability before each file is transferred. i also want that the files transferred should be transferred according to their numerical sequence. And while the files are being transferred the transfer progress of each file i.e the progress percentage bar should also be visible on the screen.
i will really appreciate if someone can help me with the code. i am posting the code i have written for file transfer.
ClientMain.java
import java.io.*;
import java.net.Socket;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class ClientMain {
private DirectoryTxr transmitter = null;
Socket clientSocket = null;
private boolean connectedStatus = false;
private String ipAddress;
String srcPath = null;
String dstPath = "";
public ClientMain() {
}
public void setIpAddress(String ip) {
this.ipAddress = ip;
}
public void setSrcPath(String path) {
this.srcPath = path;
}
public void setDstPath(String path) {
this.dstPath = path;
}
private void createConnection() {
Runnable connectRunnable = new Runnable() {
public void run() {
while (!connectedStatus) {
try {
clientSocket = new Socket(ipAddress, 3339);
connectedStatus = true;
transmitter = new DirectoryTxr(clientSocket, srcPath, dstPath);
} catch (IOException io) {
io.printStackTrace();
}
}
}
};
Thread connectionThread = new Thread(connectRunnable);
connectionThread.start();
}
public static void main(String[] args) {
ClientMain main = new ClientMain();
main.setIpAddress("10.6.3.92");
main.setSrcPath("E:/temp/movies/");
main.setDstPath("D:/tcp/movies");
main.createConnection();
}
}
(DirectoryTxr.java)
import java.io.*;
import java.net.Socket;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class DirectoryTxr {
Socket clientSocket = null;
String srcDir = null;
String dstDir = null;
byte[] readBuffer = new byte[1024];
private InputStream inStream = null;
private OutputStream outStream = null;
int state = 0;
final int permissionReqState = 1;
final int initialState = 0;
final int dirHeaderSendState = 2;
final int fileHeaderSendState = 3;
final int fileSendState = 4;
final int fileFinishedState = 5;
private boolean isLive = false;
private int numFiles = 0;
private int filePointer = 0;
String request = "May I send?";
String respServer = "Yes,You can";
String dirResponse = "Directory created...Please send files";
String fileHeaderRecvd = "File header received ...Send File";
String fileReceived = "File Received";
String dirFailedResponse = "Failed";
File[] opFileList = null;
public DirectoryTxr(Socket clientSocket, String srcDir, String dstDir) {
try {
this.clientSocket = clientSocket;
inStream = clientSocket.getInputStream();
outStream = clientSocket.getOutputStream();
isLive = true;
this.srcDir = srcDir;
this.dstDir = dstDir;
state = initialState;
readResponse(); //starting read thread
sendMessage(request);
state = permissionReqState;
} catch (IOException io) {
io.printStackTrace();
}
}
private void sendMessage(String message) {
try {
sendBytes(request.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
/**
* Thread to read response from server
*/
private void readResponse() {
Runnable readRunnable = new Runnable() {
public void run() {
while (isLive) {
try {
int num = inStream.read(readBuffer);
if (num > 0) {
byte[] tempArray = new byte[num];
System.arraycopy(readBuffer, 0, tempArray, 0, num);
processBytes(tempArray);
}
} catch (SocketException se) {
System.exit(0);
} catch (IOException io) {
io.printStackTrace();
isLive = false;
}
}
}
};
Thread readThread = new Thread(readRunnable);
readThread.start();
}
private void sendDirectoryHeader() {
File file = new File(srcDir);
if (file.isDirectory()) {
try {
String[] childFiles = file.list();
numFiles = childFiles.length;
String dirHeader = "$" + dstDir + "#" + numFiles + "&";
sendBytes(dirHeader.getBytes("UTF-8"));
} catch (UnsupportedEncodingException en) {
en.printStackTrace();
}
} else {
System.out.println(srcDir + " is not a valid directory");
}
}
private void sendFile(String dirName) {
File file = new File(dirName);
if (!file.isDirectory()) {
try {
int len = (int) file.length();
int buffSize = len / 8;
//to avoid the heap limitation
RandomAccessFile raf = new RandomAccessFile(file, "rw");
FileChannel channel = raf.getChannel();
int numRead = 0;
while (numRead >= 0) {
ByteBuffer buf = ByteBuffer.allocate(1024 * 100000);
numRead = channel.read(buf);
if (numRead > 0) {
byte[] array = new byte[numRead];
System.arraycopy(buf.array(), 0, array, 0, numRead);
sendBytes(array);
}
}
System.out.println("Finished");
} catch (IOException io) {
io.printStackTrace();
}
}
}
private void sendHeader(String fileName) {
try {
File file = new File(fileName);
if (file.isDirectory())
return;//avoiding child directories to avoid confusion
//if want we can sent them recursively
//with proper state transitions
String header = "&" + fileName + "#" + file.length() + "*";
sendHeader(header);
sendBytes(header.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
private void sendBytes(byte[] dataBytes) {
synchronized (clientSocket) {
if (outStream != null) {
try {
outStream.write(dataBytes);
outStream.flush();
} catch (IOException io) {
io.printStackTrace();
}
}
}
}
private void processBytes(byte[] data) {
try {
String parsedMessage = new String(data, "UTF-8");
System.out.println(parsedMessage);
setResponse(parsedMessage);
} catch (UnsupportedEncodingException u) {
u.printStackTrace();
}
}
private void setResponse(String message) {
if (message.trim().equalsIgnoreCase(respServer) && state == permissionReqState) {
state = dirHeaderSendState;
sendDirectoryHeader();
} else if (message.trim().equalsIgnoreCase(dirResponse) && state == dirHeaderSendState) {
state = fileHeaderSendState;
if (LocateDirectory()) {
createAndSendHeader();
} else {
System.out.println("Vacant or invalid directory");
}
} else if (message.trim().equalsIgnoreCase(fileHeaderRecvd) && state == fileHeaderSendState) {
state = fileSendState;
sendFile(opFileList[filePointer].toString());
state = fileFinishedState;
filePointer++;
} else if (message.trim().equalsIgnoreCase(fileReceived) && state == fileFinishedState) {
if (filePointer < numFiles) {
createAndSendHeader();
}
System.out.println("Successfully sent");
} else if (message.trim().equalsIgnoreCase(dirFailedResponse)) {
System.out.println("Going to exit....Error ");
// System.exit(0);
} else if (message.trim().equalsIgnoreCase("Thanks")) {
System.out.println("All files were copied");
}
}
private void closeSocket() {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private boolean LocateDirectory() {
boolean status = false;
File file = new File(srcDir);
if (file.isDirectory()) {
opFileList = file.listFiles();
numFiles = opFileList.length;
if (numFiles <= 0) {
System.out.println("No files found");
} else {
status = true;
}
}
return status;
}
private void createAndSendHeader() {
File opFile = opFileList[filePointer];
String header = "&" + opFile.getName() + "#" + opFile.length() + "*";
try {
state = fileHeaderSendState;
sendBytes(header.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
}
}
private void sendListFiles() {
createAndSendHeader();
}
}
(ServerMain.java)
public class ServerMain {
public ServerMain() {
}
public static void main(String[] args) {
DirectoryRcr dirRcr = new DirectoryRcr();
}
}
(DirectoryRcr.java)
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
public class DirectoryRcr {
String request = "May I send?";
String respServer = "Yes,You can";
String dirResponse = "Directory created...Please send files";
String dirFailedResponse = "Failed";
String fileHeaderRecvd = "File header received ...Send File";
String fileReceived = "File Received";
Socket socket = null;
OutputStream ioStream = null;
InputStream inStream = null;
boolean isLive = false;
int state = 0;
final int initialState = 0;
final int dirHeaderWait = 1;
final int dirWaitState = 2;
final int fileHeaderWaitState = 3;
final int fileContentWaitState = 4;
final int fileReceiveState = 5;
final int fileReceivedState = 6;
final int finalState = 7;
byte[] readBuffer = new byte[1024 * 100000];
long fileSize = 0;
String dir = "";
FileOutputStream foStream = null;
int fileCount = 0;
File dstFile = null;
public DirectoryRcr() {
acceptConnection();
}
private void acceptConnection() {
try {
ServerSocket server = new ServerSocket(3339);
socket = server.accept();
isLive = true;
ioStream = socket.getOutputStream();
inStream = socket.getInputStream();
state = initialState;
startReadThread();
} catch (IOException io) {
io.printStackTrace();
}
}
private void startReadThread() {
Thread readRunnable = new Thread() {
public void run() {
while (isLive) {
try {
int num = inStream.read(readBuffer);
if (num > 0) {
byte[] tempArray = new byte[num];
System.arraycopy(readBuffer, 0, tempArray, 0, num);
processBytes(tempArray);
}
sleep(100);
} catch (SocketException s) {
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException i) {
i.printStackTrace();
}
}
}
};
Thread readThread = new Thread(readRunnable);
readThread.start();
}
private void processBytes(byte[] buff) throws InterruptedException {
if (state == fileReceiveState || state == fileContentWaitState) {
//write to file
if (state == fileContentWaitState)
state = fileReceiveState;
fileSize = fileSize - buff.length;
writeToFile(buff);
if (fileSize == 0) {
state = fileReceivedState;
try {
foStream.close();
} catch (IOException io) {
io.printStackTrace();
}
System.out.println("Received " + dstFile.getName());
sendResponse(fileReceived);
fileCount--;
if (fileCount != 0) {
state = fileHeaderWaitState;
} else {
System.out.println("Finished");
state = finalState;
sendResponse("Thanks");
Thread.sleep(2000);
System.exit(0);
}
System.out.println("Received");
}
} else {
parseToUTF(buff);
}
}
private void parseToUTF(byte[] data) {
try {
String parsedMessage = new String(data, "UTF-8");
System.out.println(parsedMessage);
setResponse(parsedMessage);
} catch (UnsupportedEncodingException u) {
u.printStackTrace();
}
}
private void setResponse(String message) {
if (message.trim().equalsIgnoreCase(request) && state == initialState) {
sendResponse(respServer);
state = dirHeaderWait;
} else if (state == dirHeaderWait) {
if (createDirectory(message)) {
sendResponse(dirResponse);
state = fileHeaderWaitState;
} else {
sendResponse(dirFailedResponse);
System.out.println("Error occurred...Going to exit");
System.exit(0);
}
} else if (state == fileHeaderWaitState) {
createFile(message);
state = fileContentWaitState;
sendResponse(fileHeaderRecvd);
} else if (message.trim().equalsIgnoreCase(dirFailedResponse)) {
System.out.println("Error occurred ....");
System.exit(0);
}
}
private void sendResponse(String resp) {
try {
sendBytes(resp.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
private boolean createDirectory(String dirName) {
boolean status = false;
dir = dirName.substring(dirName.indexOf("$") + 1, dirName.indexOf("#"));
fileCount = Integer.parseInt(dirName.substring(dirName.indexOf("#") + 1, dirName.indexOf("&")));
if (new File(dir).mkdir()) {
status = true;
System.out.println("Successfully created directory " + dirName);
} else if (new File(dir).mkdirs()) {
status = true;
System.out.println("Directories were created " + dirName);
} else if (new File(dir).exists()) {
status = true;
System.out.println("Directory exists" + dirName);
} else {
System.out.println("Could not create directory " + dirName);
status = false;
}
return status;
}
private void createFile(String fileName) {
String file = fileName.substring(fileName.indexOf("&") + 1, fileName.indexOf("#"));
String lengthFile = fileName.substring(fileName.indexOf("#") + 1, fileName.indexOf("*"));
fileSize = Integer.parseInt(lengthFile);
dstFile = new File(dir + "/" + file);
try {
foStream = new FileOutputStream(dstFile);
System.out.println("Starting to receive " + dstFile.getName());
} catch (FileNotFoundException fn) {
fn.printStackTrace();
}
}
private void writeToFile(byte[] buff) {
try {
foStream.write(buff);
} catch (IOException io) {
io.printStackTrace();
}
}
private void sendBytes(byte[] dataBytes) {
synchronized (socket) {
if (ioStream != null) {
try {
ioStream.write(dataBytes);
} catch (IOException io) {
io.printStackTrace();
}
}
}
}
}
ClientMain.java and DirectoryTxr.java are the two classes under client application. ServerMain.java and DirectoryRcr.java are the two classes under Server application.
run the ClientMain.java and ServerMain.java
You can sort an array using Arrays.sort(...)
ie
String[] childFiles = file.list();
Arrays.sort(childFiles);
As I understand it, this will sort the files in natural order, based on the file name.
You can modify this by passing a custom Comparator...
Arrays.sort(childFiles, new Comparator<File>() {...}); // Fill out with your requirements...
Progress monitoring will come down to your requirements. Do you want to see only the overall progress of the number of files, the individual files, a combination of both?
What I've done in the past is pre-iterated the file list, calculated the total number of bytes to be copied and used a ProgressMonitor to display the overall bytes been copied...
Otherwise you will need to supply your own dialog. In either case, you will need use SwingUtilities.invokeLater to update them correctly.
Check out Concurrency in Swing for more details.
Network connectivity is subjective. You could simply send a special "message" to there server and wait for a response, but this only suggests that the message was sent and a recipt was received. It could just as easily fail when you start transfering the file again...

Categories