I've the below piece of code, where there is a progress bar that has to progressed.
public void createFiles(String srcText, String destText, JTextArea outputTextArea, JProgressBar progressBar) {
String zipFilePath = srcText;
String destDirectory = destText;
UnZip unzipper = new UnZip();
File dir = new File(zipFilePath);
File[] files = dir.listFiles();
System.out.println(files.length);
double pBarInt = (double) files.length / 100;
int count = 1;
System.out.println(count);
if (null != files) {
for (int fileIntList = 0; fileIntList < files.length; fileIntList++) {
System.out.println("coun in vlocj " + count);
String ss = files[fileIntList].toString();
if (null != ss && ss.length() > 0) {
try {
if (files[fileIntList].isDirectory())
continue;
unzipper.unzip(zipFilePath + ss.substring(ss.lastIndexOf("\\") + 1, ss.length()), destDirectory,
outputTextArea);
if ((fileIntList + 1) % pBarInt == 0) {
progressBar.setValue(count);
progressBar.update(progressBar.getGraphics());
count += 1;
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
}
Here the value of files.length is 25.
My question is, since there are 25 files 1% of them would be 2.5%, can i increase my progress bar for every 4 files processed as 10% or can i show 2.5% whenever a file has been processed.
If files.length is greater than 100, i'm able to do it, but unable to understand for files less than 100.
please let me know how can i get this done.
Thanks
You might just have to set the maximum correctly. E.g.:
progressBar.setMaximum(files.length);
To get only the files and not the directories in the first place do:
File[] files = dir.listFiles(new FilenameFilter() {
#Override
public boolean accept(File file, String name) {
return !file.isDirectory();
}
});
I would write the whole bit like this:
File[] files = dir.listFiles(new FilenameFilter() {
#Override
public boolean accept(File file, String name) {
return !file.isDirectory();
}
});
progressBar.setMaximum(files.length);
for (int i = 0; i < files.length; i++) {
File f = files[i];
try {
unzipper.unzip(f.getAbsolutePath(), destDirectory, outputTextArea);
progressBar.setValue(i);
progressBar.update(progressBar.getGraphics());
} catch (Exception ex) {
ex.printStackTrace();
}
}
And you might want to dispatch it in a thread. See the comment on your question.
Not sure why you need this condition (fileIntList + 1) % pBarInt == 0
You should be setting the progress bar count as a percentage of the total files. Try using
progress.setValue(100);
....
int progressBarValue = count * 100/files.length;
progressBar.setValue(progressBarValue);
For accuracy use the correct files.length - ignoring directories.
Related
here is a java program that allows to display the files of each directory
the problem how to display the result in a textarea
private static void
findFilesRecursively(File file, Collection<File> all, final String extension) {
final File[] children = file.listFiles(new FileFilter() {
public boolean accept(File f) {
return f.getName().endsWith(extension) ;
}}
);
if (children != null) {
//Pour chaque fichier recupere, on appelle a nouveau la methode
for (File child : children) {
all.add(child);
findFilesRecursively(child, all, extension);
}
}
}
public static void main(String[] args)
{
//try {
final Collection<File> all = new ArrayList<File>();
// JFileChooser fc = new JFileChooser(".");
// int returnVal = fc.showOpenDialog(null);
findFilesRecursively(new File("c:\\repertoire"), all,"");
//File outputFile = new File("C:\\Users\\21365\\Desktop\\tt.txt");
//FileOutputStream fos = new FileOutputStream(outputFile);
for (int i = 0; i < all.size(); i++) {
for (File file : all) {
if(file.isDirectory()==true){
System.out.println("le repertoire \t"+file.getName()+"\t contien");
}else{
You should not iterate through your list twice - get rid of one of these 2 for loops :
for (int i = 0; i < all.size(); i++) {
for (File file : all) {
Also instead of using System.out.println(…) to print to console, just create a JFrame / JTextArea and use its append(String text) method, eg :
if (file.isDirectory() == true) {
yourTextArea.append("le repertoire \t" + file.getName() + "\t contien");
} else {
yourTextArea.append(file.getName());
}
This is my first post, so if something wrong, I'll try to fix it.
Test task I am dealing with is to make file searcher with ability to navigate text, etc. I finished this part except one thing: application needs to allow user work with it while it is searching files in directories.
I've read a lot about multithreading, but still can't get answer how to do this... This is a code which executes when user presses "Choose folder" in my JFrame("GUI" class):
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
DefaultTreeModel model = (DefaultTreeModel) jTree1.getModel();
DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
int j = jTree1.getRowCount() - 1;
final JFileChooser fc = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter(jComboBox1.getSelectedItem().toString() + " files", jComboBox1.getSelectedItem().toString());
fc.setFileFilter(filter);
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fc.setDialogTitle("Choose a folder to fing ." + jComboBox1.getSelectedItem().toString() + " files");
jLabel4.setText("Searching files in folder, please wait");
if (fc.showOpenDialog(jButton3) == JFileChooser.APPROVE_OPTION) {
root.setUserObject("Your root");
jTextArea1.setText("");
jTextField1.setText("");
if (jTree1.getRowCount() > 0) {
for (int i = 0; i < j; i++) {
model.removeNodeFromParent((MutableTreeNode) model.getChild(root, 0));
}
}
long startTime = System.currentTimeMillis();
File f2 = new File(fc.getSelectedFile().getAbsolutePath());
String name2 = "." + jComboBox1.getSelectedItem().toString();
//FilenameFilter filter1 = (File dir, String name1) -> name1.endsWith(name2);
ArrayList<File> files = new ArrayList<>();
new NewТhread();
listf(f2, files, name2);
root.setUserObject(f2);
model.nodeChanged(root);
for (int i = 0; i < files.size(); i++) {
DefaultMutableTreeNode child = new DefaultMutableTreeNode(files.get(i).getAbsolutePath().replace(f2.toString(), ""));
root.add(child);
model.reload();
jLabel4.setText("Done! Now type text to search and press \"Search files\"");
}
System.out.println("Time used for getting files: " + (System.currentTimeMillis() - startTime) / 1000 + "sec");
JOptionPane.showMessageDialog(null, "Directory opened:" + fc.getSelectedFile().getAbsolutePath());
System.out.println("Main thread finished");
} else if (fc.showOpenDialog(jButton3) == JFileChooser.CANCEL_OPTION) {
jLabel4.setText("Please, choose folder and extension to find files");
}
}
Listf is a method to check all subdirectories too:
public ArrayList<File> listf(File directory, ArrayList<File> files, String extension) {
File[] flist = directory.listFiles();
for (int i = 0; i < flist.length; i++) {
if (flist[i].isFile() && flist[i].getName().endsWith(extension) == true) {
files.add(flist[i]);
} else if (flist[i].isDirectory()) {
listf(flist[i], files, extension);
}
}
return files;
}
NewThread is a class that I still can't get in. For now it looks like this:
class NewТhread extends Thread {
NewТhread() {
super("Demo");
start();
}
public synchronized void run() {
try {
for (int i = 3; i > 0; i--) {
Thread.sleep(500);
System.out.println(i);
GUI gui = new GUI();
gui.setVisible(true);
}
} catch (InterruptedException е) {
System.out.println("Interrupted");
}
}
After 3-2-1 count it should open new GUI object (JFrame) that should allow to make all the actions. Now all the elements of object GUI gui are frozen while main thread executes (and become unfrozen only when search finishes).
Could you help, please?
You can simply start a thread by putting only the code, which does not require user's interaction, inside the thread's run method as shown below:
new Thread()
{
public void run()
{
// code which does not require user's interaction
}
}.start();
In your case the code to be placed in run method, will be the code written in "jButton1ActionPerformed" action listener. :-)
Thanks for everyone. I've found decision with ExecutorService, it allows to not freeze project while data is loading.
I need to identify the file numbers which are missing in a folder.
I have retrieved the files names by using the code below :
File folder = new File(FILE_PATH);
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
System.out.println("File " + listOfFiles[i].getName());
} else if (listOfFiles[i].isDirectory()) {
System.out.println("Directory " + listOfFiles[i].getName());
}
}
But now after retrieving i need to find which are the file number which are missing from a file range of 1-1976 both included.
If you need just the filenames, you may use list() method. After you get all the filenames with this method, you can just check the presence of the specified filenames, like:
File parent = ...
String prefix = "xxx_", suffix = ".txt"; // for example
Set<String> files = new HashSet<>(Arrays.asList(parent.list()));
// or, as suggested by #JulienLopez:
String pattern = Pattern.quote(prefix) + "\\d+" + Pattern.quote(suffix);
Set<String> files = new HashSet<>(Arrays.asList(parent.list((dir, file) -> file.matches(pattern))));
for (int i = 1; i <= 1976; ++i) { // actually constant should be used
if (!files.contains(prefix + i + suffix)) {
System.out.format("File #%d doesn't exist%n", i);
}
}
But if you really need to check, that the file is not, for example, the directory, there's one more way to do it, by just creating the Files for every i and checking its existence:
for (int i = 1; i <= 1976; ++i) {
File file = new File(parent, prefix + i + suffix);
if (!file.isFile()) {
System.out.format("File #%d doesn't exist or is directory%n", i);
}
}
I'm not sure your structural of your file name , and what exactly on your mind with "both included". That is my idea,I hope it's a bit help for you.
String FILE_PREFIX= "your_file_prefix"; // Your file prefix. If your file is "logfile_on_20160121_0001" then the prefix is "logfile_on_20160121_"
int RANGE_MIN = 1;
int RANGE_MAX = 1976;
int fileList[] = new int[RANGE_MAX];
int directoryList[] = new int[RANGE_MAX];
// Quote your code with a bit modify from me
File folder = new File(FILE_PATH);
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
System.out.println("File " + listOfFiles[i].getName());
// Added started
String tempSplitedName[] = listOfFiles[i].split(FILE_PREFIX);
if(tempSplitedName.length==2){
int seq = Integer.parseInt(tempSplitedName[2]);
if(seq>=RANGE_MIN && seq<=RANGE_MAX){
fileList[seq] = 1;
}
}
// Added ended
} else if (listOfFiles[i].isDirectory()) {
System.out.println("Directory " + listOfFiles[i].getName());
// Added started
String tempSplitedName[] = listOfFiles[i].split(FILE_PREFIX);
if(tempSplitedName.length==2){
int seq = Integer.parseInt(tempSplitedName[2]);
if(seq>=RANGE_MIN && seq<=RANGE_MAX){
directoryList[seq] = 1;
}
}
// Added ended
}
// Now you count missing files/directory, which is equal 0
for (int i=RANGE_MIN; i<=RANGE_MAX; i++){
if(fileList[i]==0) System.out.println("Missing file No." + i);
}
for (int i=RANGE_MIN; i<=RANGE_MAX; i++){
if(directoryList[i]==0) System.out.println("Missing directory No." + i);
}
I'm only asking this as a last resort. I'm stumped.
I have written a small app which performs very simple image processing. It is made using JDK 1.8, written in Netbeans 8.0.1 and is running on Debian Linux.
The application captures a large number of individual frames at a certain framerate, set by the user, by calling the 'streamer' webcam program via a process builder. Once it has begun capturing, it begins to translate the frames into RGB values and checks whether or not any pixels are above a user defined threshold. If no pixels exceed this threshold, it simply deletes the frame. If any pixels do exceed it, it moves the frame to a different folder for user inspection. This all works fine. It keeps up with even relatively high framerates and selects appropriate frames as expected. However, when the number of frames processed reaches around 1500 (or fewer for lower framerates), the program is freezing. I've tried issuing the commands to streamer manually at the command line, and it seems perfectly capable of producing as many as required, so I have to assume the issue is with my coding. The images are only small (320x240). Am I somehow maxxing out the available memory (I am getting no errors, just freezing).
The purpose of this program is to detect cosmic ray impacts on a CMOS sensor, part of a friend's dissertation. If I can't get this working reliably, the poor kid's going to have to go through the footage manually!
The code is attached below. Apologies for the length of the code, but as all of it is fairly crucial, I didn't want to omit anything.
package cosmicraysiii;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
public class CosmicRaysIII {
public static int dark = 0;//Dark current determined by averaging
public static int tol = 0;//Tolerance set by user
public static int frames = 0;//Total number of frames set by user
public static int runs = 0;
public static int rate = 0;//Framerate set by user
public static int time = 0;//Total time calculated
public static String zeros = "";
public static int ready = 0;
public static void main(String[] args) throws IOException, InterruptedException {
//Get directory ID from user
String id = JOptionPane.showInputDialog("Enter a folder name for detections (no ., in name):");
//Get dark current
Dark d = new Dark();
dark = d.getCurrent();
//Get tolerance from user, will be added to dark current.
String t = JOptionPane.showInputDialog("Dark Current = " + dark + "/255\n"
+ "Enter a tolerance (integer values only).\n "
+ "This will be added to the dark current:");
tol = Integer.parseInt(t) + dark;
//Get number of frames from user
String fs = JOptionPane.showInputDialog("Enter the total number of frames required (Mulitples of 500 only):");
frames = Integer.parseInt(fs);
runs = frames / 500;
//Get framerate from user
String r = JOptionPane.showInputDialog("Enter the framerate required:");
rate = Integer.parseInt(r);
//Determine duration
time = (int) Math.round(frames / rate);
//Provide summary for user and request permission to continue
int secs = time % 60;
int mins = (time - secs) / 60;
int hrs = (mins - (mins % 60)) / 60;
if (hrs >= 1) {
mins = mins % 60;
}
String theMessage = "The following parameters have been set:\n"
+ "Tolerance (including dark current): " + tol + "\n"
+ "Frames: " + frames + "\n"
+ "Frame rate: " + rate + " fps\n"
+ "Total capture time: " + time + " sec\n"
+ " " + hrs + " h " + mins + " m " + secs + " s\n"
+ "\n"
+ "Would you like to proceed?";
int result = JOptionPane.showConfirmDialog(null, theMessage, "Continue?", JOptionPane.OK_CANCEL_OPTION);
if (result == 2) {
System.exit(0);
}
//Create directory for data acquisition
ProcessBuilder pb1 = new ProcessBuilder("mkdir", "data");
pb1.start();
//Establish array of filenames
String[] filenames = new String[frames];
//Fill filenames array with filenames
//Taking into consideration that the filename
//will have a varying number of zeros appended
//before the frame number, dependent on the
//order of the frame number
for (int i = 0; i < frames; i++) {
if (i < 10) {
zeros = "00000000";
} else if (i >= 10 && i < 100) {
zeros = "0000000";
} else if (i >= 100 && i < 1000) {
zeros = "000000";
} else if (i >= 1000 && i < 10000) {
zeros = "00000";
} else if (i >= 10000 && i < 100000) {
zeros = "0000";
} else if (i >= 100000 && i < 1000000) {
zeros = "000";
} else if (i >= 1000000 && i < 10000000) {
zeros = "00";
} else if (i >= 10000000 && i < 100000000) {
zeros = "0";
} else {
zeros = "";
}
filenames[i] = "./data/frame" + zeros + i + ".ppm";
}
//Begin data acquisition
new Thread(new Runnable() {
public void run() {
try {
//Capture images
ProcessBuilder pb2 = new ProcessBuilder("streamer", "-t", Integer.toString(frames), "-r", Integer.toString(rate), "-p", "0", "-o", "./data/frame000000000.ppm");
Process p = pb2.start();
p.waitFor();
ready = 1;
} catch (IOException | InterruptedException ex) {
Logger.getLogger(CosmicRaysIII.class.getName()).log(Level.SEVERE, null, ex);
}
}
}).start();
//Sleep to allow some image capture to prevent thread disordering
Thread.sleep(3000);
//Check array size
System.out.println("Array size: " + filenames.length);
//Conduct image analysis
new Thread(new Runnable() {
public void run() {
int done = 0;
int donea = 0;
while (ready == 0) {
for (int i = 0; i < frames; i++) {
File f = new File(filenames[i]);
if (f.exists() && !filenames[i].equals("")) {//Check file still exists
try {
//Perform analysis steps
Analysis a = new Analysis();
//STEP 1: Convert file from P6 to P3
String newfile = a.convert(filenames[i], zeros, i);
//STEP 2: Read file
a.read(newfile, tol, i, id);
filenames[i] = "";
done++;
} catch (IOException ex) {
Logger.getLogger(CosmicRaysIII.class.getName()).log(Level.SEVERE, null, ex);
}
}
if (done > donea) {
System.out.println(done + " files processed");
donea = done;
}
}
}
}
}).start();
}
}
Then the Analyse.java class is as follows:
package cosmicraysiii;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class Analysis {
public String convert(String ofile, String zeros, int number) throws IOException {
//Create new file name
String nfile = "./proc/frame" + zeros + number + ".ppm";
//Ensure process directory exists
ProcessBuilder mkdir = new ProcessBuilder("mkdir", "proc");
mkdir.start();
//Convert file to P3 PPM (RGB format) and move to process folder
ProcessBuilder convert = new ProcessBuilder("convert", ofile, "-compress", "none", nfile);
convert.start();
//Delete original file
ProcessBuilder del = new ProcessBuilder("sudo", "rm", ofile);
del.start();
//Return new filename
return nfile;
}
public void read(String filename, int tol, int ix, String id) throws FileNotFoundException, IOException {
int move = 0;
//Make directory for hits
ProcessBuilder mkdir = new ProcessBuilder("mkdir", "hits" + id);
mkdir.start();
//Open reader to read file
File f = new File(filename);
if (f.exists()) {
BufferedReader br = new BufferedReader(new FileReader(filename));
String line;
//To eliminate header
int x = 0;
//Iterate through text to find abnormal pixels
while ((line = br.readLine()) != null) {
x++;
String[] pixrgb = line.split("\\ ");
//Iterate through pixels on each line
for (int i = 0; i < pixrgb.length; i++) {
if (x >= 4) {//Eliminate header
//Check each pixel value
try {
int pixval = Integer.parseInt(pixrgb[i]);
if (pixval > tol) {
move = 1;
break;
}
} catch (NumberFormatException ne) {
}
}
}
}
if (move == 1) {
//Move file to hits folder
ProcessBuilder pb3 = new ProcessBuilder("sudo", "cp", filename, "./hits" + id + "/detection" + ix + ".ppm");
pb3.start();
//Delete original file
ProcessBuilder del = new ProcessBuilder("sudo", "rm", filename);
del.start();
}
}
//Delete original file
ProcessBuilder del = new ProcessBuilder("sudo", "rm", filename);
del.start();
}
}
I appreciate this is quite a lengthly chunk of code to be posting. Really appreciate any help that can be given.
G
OK I have managed to solve this by completely overhauling the analysis process. Firstly, rather than converting the image into a P3 .ppm file, I now examine the pixels directly from the image using BufferedReader. Then, I stopped looping through the file list repeatedly. Instead, the loop which calls Analysis() just runs through the list of filenames once. If it encounters a file which does not yet exist, it does Thread.sleep(500) and then tries again. I have now successfully run a batch of 50,000 frames without incident, and there is now much less of a drain on memory thanks to the improved process. Just thought I should place this answer up here in case anyone comes across it. I may post code if anyone wants it.
In my project has 40 to 50 jar files available, It takes lot of time to find out latest version of each jar at every time. Can u any one help me to write a java program for this?
You may want to just use maven : http://maven.apache.org/
Or an other dependencies manager, like Ivy.
At the time of ant-build please call this method
public void ExpungeDuplicates(String filePath) {
Map<String,Integer> replaceJarsMap = null;
File folder = null;
File[] listOfFiles = null;
List<String> jarList = new ArrayList<String>();
String files = "";
File deleteFile = null;
Iterator<String> mapItr = null;
//String extension ="jar";
try {
folder = new File(filePath);
listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
files = listOfFiles[i].getName();
jarList.add(files);
}
}
if (jarList.size() > 0) {
replaceJarsMap = PatternClassifier.findDuplicatesOrLowerVersion(jarList);
System.err.println("Duplicate / Lower Version - Total Count : "+replaceJarsMap.size());
mapItr = replaceJarsMap.keySet().iterator();
while (mapItr.hasNext()) {
String key = mapItr.next();
int repeat = replaceJarsMap.get(key);
System.out.println( key +" : "+repeat);
for (int i = 0; i <repeat; i++) {
deleteFile = new File(filePath + System.getProperty ("file.separator")+key);
try{
if (deleteFile != null && deleteFile.exists()){
if(deleteFile.delete()){
System.err.println(key +" deleted");
}
}
}catch (Exception e) {
}
}
}
}
} catch (Exception e) {
// TODO: handle exception
}
}
You only need to give the path of your Lib to this function.This method will find all the duplicate or lower version of of file.
And the crucial function is given below...Which finds out the duplicates from the list of files you provided.
public static Map<String,Integer> findDuplicatesOrLowerVersion(List<String> fileNameList) {
List<String> oldJarList = new ArrayList<String>();
String cmprTemp[] = null;
boolean match = false;
String regex = "",regexFileType = "",verInfo1 = "",verInfo2 = "",compareName = "",tempCompareName = "",tempJarName ="";
Map<String,Integer> duplicateEntryMap = new HashMap<String, Integer>();
int count = 0;
Collections.sort(fileNameList, Collections.reverseOrder());
try{
int size = fileNameList.size();
for(int i = 0;i<size;i++){
cmprTemp = fileNameList.get(i).split("[0-9\\._]*");
for(String s : cmprTemp){
compareName += s;
}
regex = "^"+compareName+"[ajr0-9_\\-\\.]*";
regexFileType = "[0-9a-zA-Z\\-\\._]*\\.jar$";
if( fileNameList.get(i).matches(regexFileType) && !oldJarList.contains(fileNameList.get(i))){
for(int j = i+1 ;j<size;j++){
cmprTemp = fileNameList.get(j).split("[0-9\\._]*");
for(String s : cmprTemp){
tempCompareName += s;
}
match = (fileNameList.get(j).matches(regexFileType) && tempCompareName.matches(regex));
if(match){
cmprTemp = fileNameList.get(i).split("[a-zA-Z\\-\\._]*");
for(String s : cmprTemp){
verInfo1 += s;
}
verInfo1 += "000";
cmprTemp = fileNameList.get(j).split("[a-zA-Z\\-\\._]*");
for(String s : cmprTemp){
verInfo2 += s;
}
verInfo2 += "000";
int length = 0;
if(verInfo1.length()>verInfo2.length()){
length = verInfo2.length();
}else{
length = verInfo1.length();
}
if(Long.parseLong(verInfo1.substring(0,length))>=Long.parseLong(verInfo2.substring(0,length))){
count = 0;
if(!oldJarList.contains(fileNameList.get(j))){
oldJarList.add(fileNameList.get(j));
duplicateEntryMap.put(fileNameList.get(j),++count);
}else{
count = duplicateEntryMap.get(fileNameList.get(j));
duplicateEntryMap.put(fileNameList.get(j),++count);
}
}else{
tempJarName = fileNameList.get(i);
}
match = false;verInfo1 = "";verInfo2 = "";
}
tempCompareName = "";
}
if(tempJarName!=null && !tempJarName.equals("")){
count = 0;
if(!oldJarList.contains(fileNameList.get(i))){
oldJarList.add(fileNameList.get(i));
duplicateEntryMap.put(fileNameList.get(i),++count);
}else{
count = dupl icateEntryMap.get(fileNameList.get(i));
duplicateEntryMap.put(fileNameList.get(i),++count);
}
tempJarName = "";
}
}
compareName = "";
}
}catch (Exception e) {
e.printStackTrace();
}
return duplicateEntryMap;
}
What findDuplicatesOrLowerVersion(List fileNameList) function task - Simply it found the duplicates and passting a map which contains the name of the file and number of time the lower version repeats.
Try this. The remaining file exist in the folder should be latest or files with out duplicates.Am using this for finding the oldest files.on the basis of that it will find the old and delete it.
This am only checking the name..Futher improvement you can made.
Where PatternClassifier is a class which contains the second method given here.