How to recursively check for a file's existence and rename if it exist, using groovy? - groovy

How do recursively check and rename the file if it already exist by appending some incrementing number?
I wrote the below function but it gives me an exception
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'E:\Projects\repo1\in_conv1.xml' with class 'java.lang.String' to class 'java.io.File'
Code
//newFilePath = E:\Projects\repo1\old\testcustprops.xml
String newFilePath = checkForExistenceAndRename(newFilePath,false)
private String checkForExistenceAndRename(String newFilePath, boolean flag){
File f = new File(newFilePath)
if(!flag){
if(f.exists()){
//renaming file
newFilePath=newFilePath[0..-5]+"_conv${rename_count++}.xml"
f = checkForExistenceAndRename(newFilePath,false)
}
else
f = checkForExistenceAndRename(newFilePath,true)
}
else
return newFilePath
}

You are trying to do:
f = checkForExistenceAndRename(newFilePath,false)
Where f is a File. But your function returns a String
Not sure if it works or not (I haven't tested your function), but you could try:
private String checkForExistenceAndRename(String newFilePath, boolean flag){
File f = new File(newFilePath)
if(!flag){
if(f.exists()){
//renaming file
newFilePath = newFilePath[0..-5]+"_conv${rename_count++}.xml"
newFilePath = checkForExistenceAndRename(newFilePath,false)
}
else
newFilePath = checkForExistenceAndRename(newFilePath,true)
}
return newFilePath
}
Also, there's no need to use recursion...
Why not just do:
private String getUniqueName( String filename ) {
new File( filename ).with { f ->
int count = 1
while( f.exists() ) {
f = new File( "${filename[ 0..-5 ]}_conv${count++}.xml" )
}
f.absolutePath
}
}

Related

How can I make this more elegant and applicable to any String?

public class JavaIntern{
public static void main(String []args){
String str = "JavaIntern"; //hardcoded, but not the problem
char[] s = str.toCharArray();
String result = new String (s,0,1); //this is where the dilemma begins
System.out.println(result);
String result1 = new String (s,0,2);
System.out.println(result1);
String result2 = new String (s,0,3);
System.out.println(result2);
String result3 = new String (s,0,4);
System.out.println(result3);
String result4 = new String (s,0,5);
System.out.println(result4);
String result5 = new String (s,0,6);
System.out.println(result5);
String result6 = new String (s,0,7);
System.out.println(result6);
String result7 = new String (s,0,8);
System.out.println(result7);
String result8 = new String (s,0,9);
System.out.println(result8);
String result9 = new String (s,0,10);
System.out.println(result9); //and this is where it ends... how can I get rid of this?
}
}
//but still get this:
J
Ja
Jav
Java
JavaI
JavaIn
JavaInt
JavaInte
JavaInter
JavaIntern
I guess you want to improve the code and also don't depend on the length of the string.
What about something like this?
public class JavaIntern{
public static void main(String []args){
String str = "JavaIntern"; //hardcoded, but not the problem
String substring = "";
for (char ch: str.toCharArray()) {
substring += ch;
System.out.println(substring);
}
}
}
This will also print:
J
Ja
Jav
Java
JavaI
JavaIn
JavaInt
JavaInte
JavaInter
JavaIntern
The loop gets one character of the string at a time and concatenates it to the substring before printing it.
Im assuming you want to be able to print out one letter more each time.
To do this we use a for loop, and this way it is fairly simple.
public class MainClass {
public static void main(String[] args) {
String str = "JavaIntern";
for (int i = 1; i <= str.length(); i++) {
System.out.println(str.substring(0, i));
}
}
}
We set i to 0 in the loop, keep iterating while i less than or equal to the length of the string, and each time we iterate, add one to i.
We use the substring method to split the string from the first letter, to i.

Filename as a String getParent and getName isn't it

How can I get Desktop/1.txt as a String
File f = new File("/home/jigar/Desktop/1.txt");
System.out.println(f.getParent());// /home/jigar/Desktop
System.out.println(f.getName()); //1.txt

Find the matching string and replace the next line

I am new to the Groovy.
If the line contains the string then replace the next line in the file.
Found something in google, but I don't want to write a new file.
newPomFile.withWriter { output ->
jars.eachLine{ line ->
if (!skipFlag)output.write(line)
skipFlag = false;
output.write("\n")
if (line.contains(calArtiName.toString().trim())){
output.write(" <version>"+calArtiVer+"</version>")
skipFlag = true;
}
}
}
You may looking for this :
File a = new File ("fileName.txt");
boolean flag = false;
a.text = a.readLines().collect{ l ->
if(flag){
flag=false;
l += " hw r u" //<=== Your code
}
flag = (l.contains('hi')) // <== Your condtion
l
}.join("\n")

Swift OS X String to Int Conversion Error

I'm having trouble converting a String to Int in my Swift OS X Xcode project. I have some data saved in a text file in a comma delimited format. The contents of the text file is below:
1,Cessna 172,3,54.4,124,38.6112
(and a line break at the end)
I read the text file and seperate it, first by \n to get each line by itself, and then by , to get each element by itself. The code to do this is below:
if let dir : NSString = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true).first {
let path = dir.stringByAppendingPathComponent("FSPassengers/aircraft.txt")
do {
let content = try NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding)
if content != "" {
let astrContent:[String] = content.componentsSeparatedByString("\n")
for aeroplane in astrContent {
let aSeperated:[String] = aeroplane.componentsSeparatedByString(",")
print(aSeperated[0])
print(Int(aSeperated[0]))
//self.aAircraft.append(Aircraft(id: aSeperated[0], type: aSeperated[1], passengerCapacity: Int(aSeperated[2])!, cargoCapacityKg: Double(aSeperated[3])!, cruiseSpeed: Int(aSeperated[4])!, fuelLitresPerHour: Double(aSeperated[5])!))
}
}
}
catch {
print("Error")
}
}
The end result here will be to assign each record (each line of the text file) into the array aAircraft. This array is made up of a custom object called Aircraft. The custom class is below:
class Aircraft: NSObject {
var id:Int = Int()
var type:String = String()
var passengerCapacity:Int = Int()
var cargoCapacityKg:Double = Double()
var cruiseSpeed:Int = Int()
var fuelLitresPerHour:Double = Double()
override init() {}
init(id:Int, type:String, passengerCapacity:Int, cargoCapacityKg:Double, cruiseSpeed:Int, fuelLitresPerHour:Double) {
self.id = id
self.type = type
self.passengerCapacity = passengerCapacity
self.cargoCapacityKg = cargoCapacityKg
self.cruiseSpeed = cruiseSpeed
self.fuelLitresPerHour = fuelLitresPerHour
}
}
In the first code extract above, where I split the text file contents and attempt to assign them into the array, you will see that I have commented out the append line. I have done this to get the application to compile, at the moment it is throwing me errors.
The error revolves around the conversion of the String values to Int and Double values as required. For example, Aircraft.id, or aSeperated[0] needs to be an Int. You can see that I use the line Int(aSeperated[0]) to convert the String to Int in order to assign it into the custom object. However, this line of code is failing.
The two print statements in the first code extract output the following values:
1
Optional(1)
If I add a ! to the end of the second print statement to make them:
print(aSeperated[0])
print(Int(aSeperated[0])!)
I get the following output:
I understand what the error means, that it tried to unwrap an optional value because I force unwrapped it, and it couldn't find an Int value within the string I passed to it, but I don't understand why I am getting the error. The string value is 1, which is very clearly an integer. What am I doing wrong?
Because Casena 172 is not convertible to an Int. You also have other decimal numbers which you will lose precision when casting them to Int. Use NSScanner to create an initializer from a CSV string:
init(csvString: String) {
let scanner = NSScanner(string: csvString)
var type: NSString?
scanner.scanInteger(&self.id)
scanner.scanLocation += 1
scanner.scanUpToString(",", intoString: &type)
self.type = type as! String
scanner.scanLocation += 1
scanner.scanInteger(&self.passengerCapacity)
scanner.scanLocation += 1
scanner.scanDouble(&self.cargoCapacityKg)
scanner.scanLocation += 1
scanner.scanInteger(&self.cruiseSpeed)
scanner.scanLocation += 1
scanner.scanDouble(&self.fuelLitresPerHour)
}
Usage:
let aircraft = Aircraft(csvString: "1,Cessna 172,3,54.4,124,38.6112")
As #mrkxbt mentioned, the issue was related to the blank line after the data in the text file. The string was being split at the \n which was assigning two values into the array. The first value was a string containing the data and the second was an empty string, so obviously the second set of splitting (by ,) was failing. Amended and working code is below:
if let dir : NSString = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true).first {
let path = dir.stringByAppendingPathComponent("FSPassengers/aircraft.txt")
do {
let content = try NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding)
if content != "" {
let astrContent:[String] = content.componentsSeparatedByString("\n")
for aeroplane in astrContent {
if aeroplane != "" {
let aSeperated:[String] = aeroplane.componentsSeparatedByString(",")
print(aSeperated[0])
print(Int(aSeperated[0])!)
self.aAircraft.append(Aircraft(id: Int(aSeperated[0])!, type: aSeperated[1], passengerCapacity: Int(aSeperated[2])!, cargoCapacityKg: Double(aSeperated[3])!, cruiseSpeed: Int(aSeperated[4])!, fuelLitresPerHour: Double(aSeperated[5])!))
}
}
}
}
catch {
print("Error")
}
}

how do i make code check inputs before accepting all kinds of strings

I am trying to get a valid word from a set of scrabbled letters but all inputs (invalid ones,numbers included) are accepted by my code and checked against a list of words directly. How can i check the inputs against the displayed scrabbled letters so that only words containing letters from the scrabbled ones are accepted before checking the record?
import comp102x.IO; //a library from an edx course(COMP 102x)
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import javax.swing.JOptionPane;
import java.util.Random;
public class FormWords {
public void searchWord() throws IOException
{
Random random = new Random();
String [] randAlphs = {"o","b","e","k","a","i","c","d","f","g","h","k","u"};
int r = random.nextInt(randAlphs.length);
int a = random.nextInt(randAlphs.length);
int n = random.nextInt(randAlphs.length);
int d = random.nextInt(randAlphs.length);
int o = random.nextInt(randAlphs.length);
int m = random.nextInt(randAlphs.length);
int w = random.nextInt(randAlphs.length);
int i = random.nextInt(randAlphs.length);
int s = random.nextInt(randAlphs.length);
//prompt's user for input
String answer = JOptionPane.showInputDialog("form words with the following: " + randAlphs[r]+ randAlphs[a]+ randAlphs[n]+ randAlphs[d]+ randAlphs[o]+ randAlphs[m]+ randAlphs[w]+ randAlphs[s]);
/*searches the record to check if input exists
*/
boolean exist = searchFromRecord("record.txt", answer);
if (exist)
{
JOptionPane.showMessageDialog(null, "Congratulation!The word \"" + answer + "\" is a valid English word.");
}
else
{
// System.out.println("Sorry b ut the word \"" + answer + "\" is not a valid English word.");
JOptionPane.showMessageDialog(null, "Sorry but the word \"" + answer + "\" is not a valid English word.");
}
}
/**
* Searches the record and returns if a specified word is in the record.
*
* #param recordName The name of the record text file.
* #param word The word to be searched.
* #return true if the word presents in the record, false otherwise.
*/
private boolean searchFromRecord(String recordName, String word) throws IOException
{
// Please write your code after this line
File inputFile = new File("record.txt");
Scanner input = new Scanner(inputFile);
while(input.hasNextLine()){
if(word.equalsIgnoreCase(input.nextLine())){
return true;
}
}
return false;
}
}
Before your "prompt's user for input" code. You can use and HashSet in java and add all the letter into de HashSet. Code snippet like this:
Set<String> scrabbledLettersSet = new HashSet<String>();
scrabbledLettersSet.add(randAlphs[a]);
scrabbledLettersSet.add(randAlphs[n]);
scrabbledLettersSet.add(randAlphs[d]);
scrabbledLettersSet.add(randAlphs[o]);
scrabbledLettersSet.add(randAlphs[m]);
scrabbledLettersSet.add(randAlphs[w]);
scrabbledLettersSet.add(randAlphs[i]);
scrabbledLettersSet.add(randAlphs[s]);
Then before you do searchFromRecord method, you can use the set to check whether you input is valid or not. Code snippet is like this:
bool containsScrabbledLetters = false;
for(int i = 0 ; i < answer.length() ; ++ i) {
if (scrabbledLettersSet.contains(answer.substring(i, i + 1))) {
containsScrabbledLetters = true;
break;
}
}
boolean exist = false;
if (containsScrabbledLetters)
exist = searchFromRecord("record.txt", answer);
The above code means that if at least one letter in input string is the scrabbled letter, the input is OK, If you means all letters int the input string must exist in the scrabbled letters, you can use the following code:
bool containsScrabbledLetters = true;
for(int i = 0 ; i < answer.length() ; ++ i) {
if (!scrabbledLettersSet.contains(answer.substring(i, i + 1))) {
containsScrabbledLetters = false;
break;
}
}
boolean exist = false;
if (containsScrabbledLetters)
exist = searchFromRecord("record.txt", answer);

Resources