Design and develop a program that accepts the name of a directory that contains
ID: 3734800 • Letter: D
Question
Design and develop a program that accepts the name of a directory that contains a set of text-only files. The program must be executable as below.
The program ensures the following:
a) there are two parameters to the main method
b) <input-folder-name> is a valid, readable directory
c) the directory <output-folder-name> does not exist.
If there is a violation of these requirements, the program prints an error message and stops.
The program must read the files in <input-folder-name> in parallel using multiple threads and create an index of every token (a sequence of characters delineated by white space) in the input files: the token, the file name in which it occurs and the line number or offset in the file must all be output to a file in <output-folder-name>. All file names and line numbers associated with a token must be output before outputting the next token and its related information.
Suppose the files data1 and data2 are files in the folder C:ClassesICS 440PA2 Mapdata. The file data1 contains the following three lines.
And data2 contains the following three lines.
An output would be as follows. (The order of the tokens is unimportant.)
1
It is fine to output just the file name relative to the folder as opposed to the absolute path name.
Use a combination of thread pools, Callables, and Futures. All files must be processed in parallel to update a concurrent map implementation from java.util.
Explanation / Answer
package TypesOfLinkedList;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
public class TokenInfo implements Callable<Map<String, String>> {
final Map<String, String> TokensInfo;
private final String[] filePath;
AtomicInteger counter=new AtomicInteger(0);
public TokenInfo(String[] StringPath)
{
this.filePath=StringPath;
this.TokensInfo=new ConcurrentHashMap<String, String>();
}
public Map<String, String> getPaths(String filePath)
{
//System.out.println(filePath);
try {
List<String> allLines = Files.readAllLines(Paths.get(filePath));
int count=1;
for (String line : allLines) {
//System.out.println(line);
String[] str=line.split(" ");
for (String string : str) {
String found=TokensInfo.putIfAbsent(string, filePath+":"+count);
if(found==null){
//do Nothing since it was already put into map
}
else{
String path=found;
path+=" "+filePath+":"+count;
TokensInfo.replace(string, path);
}
}
count++;
}
} catch (IOException e) {
e.printStackTrace();
}
return TokensInfo;
}
@Override
public Map<String, String> call() throws Exception {
int ct=counter.getAndIncrement();
//System.out.println(counter);
return getPaths(filePath[ct]);
}
public static void main(String[] args) {
int noOfThreads=args.length;
if (noOfThreads==0) {
System.out.println("No file is provided to read...Please input");
return;
}
for (int i = 0; i < args.length; i++) {
File file = new File(args[i]);
if (!file.exists()) {
System.out.println(args[i] + " does not exist.");
return;
}
if (!(file.isFile() && file.canRead())) {
System.out.println(file.getName() + " cannot be read from.");
return;
}
}
//Get ExecutorService from Executors utility class, thread pool size is fine counts
ExecutorService executor = Executors.newFixedThreadPool(noOfThreads);
//create a list to hold the Future object associated with Callable
List<Future<Map<String, String>>> list = new ArrayList<Future<Map<String, String>>>();
//Create MyCallable instance
Callable<Map<String, String>> callable = new TokenInfo(args);
for(int i=0; i< noOfThreads; i++){
//submit Callable tasks to be executed by thread pool
Future<Map<String, String>> future = executor.submit(callable);
//add Future to the list, we can get return value using Future
list.add(future);
}
Map<String, String> tokens=new ConcurrentHashMap<String, String>();
for(Future<Map<String, String>> fut : list){
try {
//print the return value of Future, notice the output delay in console
// because Future.get() waits for task to get completed
tokens=fut.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
//shut down the executor service now
executor.shutdown();
for (Map.Entry<String, String> token : tokens.entrySet()) {
System.out.println("Token Name-"+token.getKey()+" Path-"+token.getValue());
}
}
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.