Recursion Java vs Python - java

last week i made this java file wondering to search in my pc files which contains certain words i input.
After to have done it i thought "why not translating it in python?" and in python i have seen that it runs out of memory (because of the recursion), but in java didn't (in python the code works if i dont give a lot of dirs and files), i put here the 2 codes and the error (java vs python) so u can help me(sorry for my english i am not mother tongue).
JAVA:
package com.company;
import java.io.*;
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
System.out.println("Input path to start(remember the / at the end):");
Scanner input = new Scanner(System.in);
String path=input.nextLine();
ArrayList<String> words= new ArrayList<>();
String word="";
while(!word.equals("//quit")){
System.out.println("Input word to search (input://quit to stop):");
word=input.nextLine();
if(!word.equals("//quit"))
words.add(word);
}
Finder finder= new Finder(path,castToArray(words));
finder.readFile();
}
private static void readFiles(Finder finder){
String[] files = finder.printFiles();
for(int i=0; i< files.length;i++){
System.out.println(files[i]);
}
}
private static String[] castToArray(ArrayList<String> words){
String[] w0rds = new String[words.size()];
for(int i=0; i< words.size(); i++){
w0rds[i]= words.get(i);
}
return w0rds;
}
}
class Finder {
private String[] words;
private File file;
private String path;
Finder(String path,String... words){
this.words=words;
this.path=path;
file= new File(path);
}
public String[] printFiles(){
String[] files;
files=file.list();
return files;
}
public void readFile(){
String[] files= printFiles();
for(int i=0; i< files.length;i++){
File f = new File(file.getPath()+"/"+files[i]);
if(!f.isDirectory()){
searchWord(f,words);
}else {
Finder finder = new Finder(path+f.getName()+"/",words);
finder.readFile();
}
}
}
public File getFile() {
return file;
}
public void searchWord(File file,String... words){
DataInputStream dis = null;
try {
dis = new DataInputStream(new FileInputStream(file));
byte[] bytes = new byte[512];
dis.readFully(bytes);
String obj = new String(bytes);
for(int i=0; i< words.length;i++){
if(obj.contains(words[i])){
System.out.println(file.getName());
break;
}
}
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}
}
PYTHON:
import os
class Finder:
path = ""
words= []
def readFile(self,path,words):
new_file = open(path, "r")
data=new_file.read(8192)
new_file.close()
for word in words:
if(data.find(word,0,len(data))!=-1):
print "name: "+new_file.name+" path: "+path
break
def __init__(self,path, words):
self.path=path
self.words=words
def __del__(self):
files=os.listdir(path)
for file in files:
if(os.path.isdir(path+file)!=True):
self.readFile(path+file,words)
else:
dirpath = path+file+"/"
finder = Finder(path,words)
path= raw_input("input path to start(remember the / at the end):\n")
words=[]
word = ""
while word != "//quit":
word=raw_input("input word to search (write //quit to start searching):\n")
if word != "//quit":
words.append(word);
print "start searching for "+str(words)+"..."
finder = Finder(path,words)
PYTHON ERROR:
Exception RuntimeError: 'maximum recursion depth exceeded' in <bound method Finder.__del__ of <__main__.Finder instance at 0x7f5c0b4f4d40>> ignored
Exception RuntimeError: 'maximum recursion depth exceeded' in <bound method Finder.__del__ of <__main__.Finder instance at 0x7f5c0b4f4c68>> ignored
Exception RuntimeError: 'maximum recursion depth exceeded' in <bound method Finder.__del__ of <__main__.Finder instance at 0x7f5c0b4f4d40>> ignored
Exception RuntimeError: 'maximum recursion depth exceeded' in <bound method Finder.__del__ of <__main__.Finder instance at 0x7f5c0b4f4c68>> ignored

In python, you rarely should use the __del__ method. It is a special magic method that is called at an arbitrary time (when the object is garbage-collected) with very few applications and multiple caveats. Instead, for most use cases, you should use a .close() method you call explicitly or with a context manager like contextlib.closing.
That said, I don't know why you made a __del__ method at all since in your java code there is nothing like that. Closest java thing would be a finalize method, but you're not using it, so why did you chose to use __del__ in your translation?
Anyway, in python you can use os.walk() instead of os.listdir() to traverse your directory tree - os.walk() is iteratively recursive so it can handle any path depth without running out of call stack space:
for pth, dirs, files in os.walk(path):
for filename in files:
self.readFile(os.path.join(pth, filename))
This code snippet will call readFile with all files in all subfolders.

The problem in your python code is, that you use the global path variable in __del__ instead of self.path. Therefore you get an infinite recursion.
Better convert your class into functions:
import os
def readFile(path, words):
with open(path, "r") as new_file:
data = new_file.read(8192)
for word in words:
if word in data:
print "name: {} path: {}".format(new_file.name, path)
break
def search(path, words):
files = os.listdir(path)
for filename in files:
fullname = os.path.join(path, filename)
if not os.path.isdir(fullname):
readFile(fullname, words)
else:
search(fullname, words)
path = raw_input("input path to start: ")
words = []
while True:
word = raw_input("input word to search (write //quit to start searching): ")
if word == "//quit":
break
words.append(word)
print "start searching for {}...".format(', '.join(words))
search(path, words)

Related

Get a jar file from a path, and change its classes names

So I need to make a java console app that gets a jar file path and prints all the classes names to the console.
Then I want it to change all of the classes names to 3 random letters from the abc "ABC" (for example) and then I need it to create a new jar file with the same code in the classes but with the new classes names.
Now my idea for storing the classes code
ArrayList> that way each index will represent a class and each index of the ArrayList would represent a line in that class
also maybe will not need a decompiler if you can get the bytecode and just transfer it to the new file were creating
Now I don't really have much experience working with files like that in Java and in C# I have worked with files some times but not in that level, but I would be happy to learn, I also understand that it may be problematic to just create a new jar with the code of the old one
I hope there is a short efficient way to do what I need here
Also, I don't need this to be a big project right now and that's why I do everything in one class
here is what I got right now
private static ArrayList<String> usedNames;
private static final String letters = "abcdefghijklmnopqrstuvwxyz";
private static Random rnd;
public static void main(String args[]) throws Exception
{
usedNames = new ArrayList<String>();
usedNames.add("");
rnd = new Random();
// reading
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter a jar path: ");
String inputPath = reader.readLine();
System.out.println("Enter a output path: ");
String outputPath = reader.readLine();
// getting all class names from jar
List<String> classNames = new ArrayList<String>();
ZipInputStream zip = new ZipInputStream(new FileInputStream(inputPath + ".jar"));
for (ZipEntry entry = zip.getNextEntry(); entry != null; entry = zip.getNextEntry()) {
if (!entry.isDirectory() && entry.getName().endsWith(".class")) {
// This ZipEntry represents a class. Now, what class does it represent?
String className = entry.getName().replace('/', '.'); // including ".class"
classNames.add(className.substring(0, className.length() - ".class".length()));
}
}
// print all classes names
for (String s : classNames)
System.out.println(s);
// getting the code of each class to some sort of data structure
// changing classes names to random letters
// creating a new jar file with the classes in location outputPath
}
private static String getRandomClassName() {
String str = "";
while (usedNames.contains(str)) {
for (int i = 0; i < 3; i++)
str += letters.charAt(rnd.nextInt(27));
}
usedNames.add(str);
return str;
}

Read Multiple text files and Finding longest word from each text files

i have a friends assignement of last year which had an interesting question and which i found good for praticing with text files manipulation in java. the question goes like this.
XYZ Company is a digital publishing company and want your help to develop a small
Java Application. The Java Application should :
1. Count number of java files that end with .txt in a directory/folder.
2. Display the longest word in each file.
Example of the outputs are shown below (assuming that filename are f1.txt , f2.txt and f3.txt):
Number of Files = 3
Longest Word in f1.txt = strachouming
Longest Word in f2.txt = newstraaach
Longest Word in f3.txt = revolutions
i have so far managed to do this but am stuck i cannot find a solution to this problem am fairly new to java and still learning the concepts.
package longestWordTxt;
import java.util.Scanner;
import java.io.*;
public class Longestword {
public static void main(String [ ] args) throws FileNotFoundException {
File f = new File("C:/Users/Dell/Desktop/java");
int count = 0;
for (File file : f.listFiles()) {
if (file.isFile() && (file.getName().endsWith(".txt"))) {
count++;
}
}
System.out.println("Number of files: " + count);
//calling function longestWord
new Longestword().getLongestWords();
}
//funtion longestWord
public String getLongestWords() throws FileNotFoundException {
String longestWord = "";
String current;
String [] word = new String[4];
int i;
for(i=1;i<5;i++) {
Scanner scan = new Scanner(new File("C:/Users/Dell/Desktop/java/f"+i+".txt"));
while (scan.hasNext()) {
current = scan.next();
if ((current.length() > longestWord.length()) && (!current.matches(".*\\d.*"))) {
longestWord = current;
}
}
System.out.println("Longest word in f"+i+".txt = " + longestWord);
}
longestWord.replaceAll("[^a-zA-Z ]", "").split("\\s+");
return longestWord;
}
}
This is my result:
Number of files: 4
Longest word in f1.txt = disastrous
Longest word in f2.txt = disastrous
Longest word in f3.txt = heartbreaking
Longest word in f4.txt = heartbreaking
My problem is it the first two top words come from the f1.txt file and 2 bottom ones come from the f3.txt file. how can i fix that?
Thanks for your help in advance.
The program you created calculates the longest word so far from all the files it has read. Meaning that 'disastrous' is the longest word in files f1 and f2.
If you want to get the longest word of each file separately and not in comparison with other files you should add this line of code at the end of each iteration of the for loop in your getLongestWords() method.
longestWord = "";
Also the method getLongestWords() can be a void method since you do not need to use the string it returns.

Java not detecting file contents

I'm having difficulty figuring out why this isn't working. Java simply isn't executing the while loop, file apparently does not have a next line.
fileName = getFileName(keyboard);
file = new Scanner (new File (fileName));
pass = true;
String currentLine;
while (file.hasNextLine()) {
currentLine = file.nextLine();
System.out.println(reverse(currentLine));
}
Here is the file I am testing this with. I got it to work with the first few paragraphs but it seems to simply stop working...:
Jabberwocky
'Twas brillig, and the slithy toves
Did gyre and gimble in the wabe;
All mimsy were the borogoves,
And the mome raths outgrabe.
"Beware the Jabberwock, my son!
The jaws that bite, the claws that catch!
Beware the Jubjub bird, and shun
The frumious Bandersnatch!"
He took his vorpal sword in hand:
Long time the manxome foe he soughtó
So rested he by the Tumtum tree,
And stood awhile in thought.
And as in uffish thought he stood,
The Jabberwock, with eyes of flame,
Came whiffling through the tulgey wood,
And burbled as it came!
One, two! One, two! and through and through
The vorpal blade went snicker-snack!
He left it dead, and with its head
He went galumphing back.
"And hast thou slain the Jabberwock?
Come to my arms, my beamish boy!
O frabjous day! Callooh! Callay!"
He chortled in his joy.
'Twas brillig, and the slithy toves
Did gyre and gimble in the wabe;
All mimsy were the borogoves,
And the mome raths outgrabe.
——from Through the Looking-Glass, and What Alice Found There (1872).
/*
* Lab13a.java
*
* A program that prompts the user for an input file name and, if that file exists,
* displays each line of that file in reverse order.
* Used to practice simple File I/O and breaking code up into methods as well as a first
* step to implementing Lab13b.java - reversing the entire file and Lab13c.java writing
* output to a separate output file.
*
* #author Benjamin Meyer
*
*/
package osu.cse1223;
import java.io.*;
import java.util.*;
public class Lab13a {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
String fileName = "";
Scanner file;
boolean pass = false;
while (!pass) {
try {
fileName = getFileName(keyboard);
file = new Scanner (new File (fileName));
pass = true;
String currentLine;
while (file.hasNextLine()) {
currentLine = file.nextLine();
System.out.println(reverse(currentLine));
}
}
catch (FileNotFoundException e) {
System.out.println("There was a problem reading from " + fileName);
System.out.println("Goodbye.");
return;
}
}
}
// Given a Scanner as input prompts the user to enter a file name. If given an
// empty line, respond with an error message until the user enters a non-empty line.
// Return the string to the calling program. Note that this method should NOT try
// to determine whether the file name is an actual file - it should just get a
// valid string from the user.
private static String getFileName(Scanner inScanner) {
boolean pass = true;
String fileName = "";
while (pass) {
System.out.print("Enter an input name: ");
fileName = inScanner.nextLine();
if (fileName.length()!=0) {
pass = false;
}
else {
System.out.println("You cannot enter an empty string.");
}
}
return fileName;
}
// Given a String as input return the reverse of that String to the calling program.
private static String reverse(String inString) {
if (inString.length()==0) {
return "";
}
String reversed = "" + inString.charAt(inString.length()-1);
for (int x = inString.length()-2; x>=0; x--) {
reversed = reversed + inString.charAt(x);
}
return reversed;
}
}
The issue might lie in your implementation of your functions getFilename() or reverse(). Since you have stated that you got it to work with a few of the paragraphs I doubt that your program is failing due to your file handling. It might be in the logic you are using to reverse the strings in the file that is causing the issue.

Why user.home returns "\" not "/"?

Maybe some of you will tell me where the mistake is, because I'm sitting on this for a few hours and didnt see anything.
The program should check if the if can be found in a txt file and return it to the bottom.
The second question about user.home
When I use it gets "C: \ Users \ Daniel / test / Test.java" by which the program does not work when I set the path to "C :/ Users / Daniel / test / Test.java" program begins to find my .txt file, but i cant leave it like that it must be found by user.home :(
public class Main {
public static void main(String ... args) throws Exception {
String usrHome = System.getProperty("user.home");
Finder finder = new Finder(usrHome + "/Testy/Test.java");
int nif = finder.getIfCount();
System.out.println("Number found 'if'": " + nif);
}
}
And finder class:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Finder {
String file;
Finder(String file){
file = this.file;
}
int getIfCount() throws FileNotFoundException{
int count = 0; String tmp; String lf = "if";
Scanner sc = new Scanner (new File("C:/Users/Daniel/Testy/Test.java"));
while(sc.hasNext()){
tmp = sc.next();
System.out.println(tmp); //to check if it works correctly
if(tmp == lf){
count++;
}
}
sc.close();
return count;
}
}
The result should look like this:
Number found "if": 3
Because there are three such elements, although the result is always 0
the result is always 0
Because you use == with String, try to Use equals() when you compare two string
if (tmp.equals(lf)) {
count++;
}
A better way to do the filename concatenation would be this:
File home = new File(System.getProperty("user.home"));
File file = new File(home, "Testy/Test.java");
/* Or even ...
File file = new File(new File(home, "Testy"), "Test.java");
*/
Finder finder = new Finder(file);
This avoids needing to know about the platform pathname representation.
The miscounting issue is caused by a basic Java 101 mistake. You are using '==' to compare Strings. It (usually) doesn't work. Use String.equals(...).

File that exists is not being found in Java

I have a Java program that searches through your cookies files and then saves each file into an array. I then try to search through each of those files for a certain string, however when I try to search the files I KNOW exist, java tells me that they don't. Any ideas?
Here is my code so far:
import java.io.*;
import java.util.*;
public class CheckCookie
{
static String[] textFiles = new String[100];
static String userName = "";
public static void findCookies()
{
String path = "pathtocookies";
String files;
File folder = new File(path);
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++)
{
if (listOfFiles[i].isFile())
{
files = listOfFiles[i].getName();
if (files.endsWith(".txt") || files.endsWith(".TXT"))
{
textFiles[i] = files;
}
}
}
}
public static boolean searchCookies()
{
for(int j = 0; j < textFiles.length; j++) {
String path2 = "pathtocookies"+textFiles[j];
File file = new File(path2);
try {
Scanner scan = new Scanner(file);
while (scan.hasNext()) {
String line = scan.nextLine();
if(line.contains("ineligible_age")) {
System.out.println("A cookie for ineligible age was set.");
return true;
}
}
}
catch(FileNotFoundException e) {
System.out.println("File was not found.");
return false;
}
}
System.out.println("A cookie for ineligible age was not set.");
return false;
}
public static void main(String[] args)
{
findCookies();
searchCookies();
System.out.println();
System.out.println("Finished searching for cookies. Yum.");
}
}
Actual path:
C:/Users/lucas.brandt/AppData/Roaming/Microsoft/Windows/Cookies
Use a List, instead of an array to store the textFiles.
Imagine a directory with 2 files. The first is "abc.doc", the second "itsme.txt"
Your textFiles array will look like this:
textFiles[0]: null
textFiles[1]: "itsme.txt"
So you try to access "pathtocookies" + "null" which will fail, you go to the catch and return out of the function.
Further hints:
Return the list from the first function, use it as an argument for the second function
Use a debugger or "debug" print statements to debug your code to see whats happening
More hints depends on the actual use case.
--tb
In this line:
String path2 = "pathtocookies"+textFiles[j];
You are missing the File separator between the directory name and the file name. java.io.File has a constructor that takes the parent path and the file name as separate arguments. You can use that or insert File.separator:
String path2 = "pathtocookies" + File.separator + textFiles[j];
You are also picking up directories in your array. Check that it is a file before you try to scan it.
Also, consider the other answer where the files are saved in a List, eliminating the directories.
files = listOfFiles[i].getName();
Try to change to
files = listOfFiles[i].getAbsolutePath();
EDIT
You can also initiate directectly an array of File (instead of String),
and you have to use .canRead() method to verify File access.
Why don't you just store the File instances in a File[] or List<File>?
I think you would also benefot from using a StringBuilder, when doing a lot of string concatenstions...

Categories

Resources