groovy input into file iterate over map - groovy

Hi I got the map and loop iterate over the map.
def map = [file.txt : file2.txt,
file3.txt : fil4.txt,
file5.txt : file6.txt]
map.each { k,v ->
collection = new file("k").readLines()
collection2 = new file("v").readLines.findResult()
def commons = collection.intersect(collection2)
}
I want every "commons" collection save into a file, not overwriting this file over the next iterations.
Is there a possibility to do such a thing in the loop?

Suppose you already have your list of files to merge, then the only thing you need to do is to write the lines of each file into the output file, you can do something like this:
def files = ['file1.txt', 'file3.txt', 'file2.txt']
def file = new File('output.txt')
def outputFile = file.newPrintWriter()
def mergeFile = { fileName ->
File sourceFile = new File(fileName)
sourceFile.eachLine{ line ->
outputFile.println(line)
}
}
files.each(mergeFile)
out.close()
This will merge the contents of all your files, there is another thing, you may need to specify the folder of the files, so I suggest to use the constructor that receives the folder.
File output = new File(folder, filename)

Related

groovy saving lines from file into collection

Hi I want do save collection from textfile in groovy and save only chosen lines.
I have a file contains that plaintext:
!!file-number1:
!!123.sql
!!123.jpeg
!!333.jpeg
!!texttextext.jpeg
and I want to save it to collection with that result
collection = ['123.jpeg', '333.jpeg', 333.jpeg', 'textextex.jpeg']
Only .jpeg and without "!!"
String filePath = "path/to/file.txt"
File myFile = new File(filePath)
def collection = myFile.collect().retainAll {it == '*.jpeg'}
println collection
And my question is how to remove or ignore things like "!!" and how to print that collection, because i got only output "true".
You can use findResults to "filter" and "map" in one go. e.g.
def lines = """!!file-number1:
!!123.sql
!!123.jpeg
!!333.jpeg
!!texttextext.jpeg"""
println lines.readLines().findResults{ def m = it =~ /!!(.*\.jpeg)/; m ? m[0][1] : null }
// → [123.jpeg, 333.jpeg, texttextext.jpeg]
Or a little bit easier to read, without using the Matcher object:
String filePath = "path/to/file.txt"
def lines = new File(filePath)
.collect()
.findAll { it ==~ /.*jpeg/ }
.collect { it[2..-1] }
println lines
In your example, retainAll() modifies the initial collection and returns a boolean value. See here: https://docs.groovy-lang.org/latest/html/groovy-jdk/java/util/Collection.html

Applying function to a list of file-paths and writing csv output to the respective paths

How do I apply a function to a list of file paths I have built, and write an output csv in the same path?
read file in a subfolder -> perform a function -> write file in the
subfolder -> go to next subfolder
#opened xml by filename
with open(r'XML_opsReport 100001.xml', encoding = "utf8") as fd:
Odict_parsedFromFilePath = xmltodict.parse(fd.read())
#func called in func below
def activity_to_df_one_day (list_activity_this_day):
ib_list = [pd.DataFrame(list_activity_this_day[i], columns=list_activity_this_day[i].keys()).drop("#uom") for i in range(len(list_activity_this_day))]
return pd.concat(ib_list)
#Processes parsed xml and writes csv
def activity_to_df_all_days (Odict_parsedFromFilePath, subdir): #writes csv from parsed xml after some processing
nodes_reports = Odict_parsedFromFilePath['opsReports']['opsReport']
list_activity = []
for i in range(len(nodes_reports)):
try:
df = activity_to_df_one_day(nodes_reports[i]['activity'])
list_activity.append(df)
except KeyError:
continue
opsReport = pd.concat(list_activity)
opsReport['dTimStart'] = pd.to_datetime(opsReport['dTimStart'], infer_datetime_format =True)
opsReport.sort_values('dTimStart', axis=0, ascending=True, inplace=True, kind='quicksort', na_position='last')
opsReport.to_csv("subdir\opsReport.csv") #write to the subdir
def scanfolder(): #fetches list of file-paths with desired starting name.
list_files = []
for path, dirs, files in os.walk(r'C:\..\xml_objects'): #directory containing several subfolders
for f in files:
if f.startswith('XML_opsReport'):
list_files.append(os.path.join(path, f))
return list_files
filepaths = scanfolder() #list of file-paths
Every function works well, the xml processing is good, so I am not sharing the xml structure. There are 100+ paths in filepaths , each a different subdirectory. I want to be able to apply above flow in future as well, where I can get filepaths and perform desired actions. It's important to write the csv file to it's sub directory.
To get the directory that a file is in, you can use:
import os
for root, dirs, files, in os.walk(some_dir):
for f in files:
print(root)
output_file = os.path.join(root, "output_file.csv")
print(output_file)
Is that what you're looking for?
Output:
somedir
somedir\output_file.csv
See also Python 3 - travel directory tree with limited recursion depth and Find current directory and file's directory.
Was able to solve with os.path.join.
exceptions_path_list =[]
for i in filepaths:
try:
with open(i, encoding = "utf8") as fd:
doc = xmltodict.parse(fd.read())
activity_to_df_all_days (doc, i)
except ValueError:
exceptions_path_list.append(os.path.dirname(i))
continue
def activity_to_df_all_days (Odict_parsedFromFilePath, filepath):
...
...
...
opsReport.to_csv(os.path.join(os.path.dirname(filepath), "opsReport.csv"))

How to Read the csv file data one by one and put into variable Using Groovy

Here i am facing One problem that. i want to read the csv file data and one by one put it into a variable and that variable i want to assign a next Http Request let say ids.csv file which consisting of values like this
23333
23334
23335
22336
23336
I am using Jsr223 PreProcessor code:
def csvfile = new File('D:/datas/id/ids.csv')
def lines =csvfile.readLines()
lines.each { String line ->
vars.put('Id_value', line.toString())
}
If it is wrong, how to do this with simple code?
You can emulate JMeter CSV data set which add variables with different suffixes, example in tutorial:
String Filename = vars.get("GETfile");
String fileContents = new File(Filename).getText('UTF-8');
def lines = 0 ;
fileContents.eachLine { line ->
lines++;
vars.put("CSVLine_" + lines, line);
}
vars.put("GETfileLength",lines.toString()) ;
and then loop the variables using ForEach Controller:
You need to add a some form of counter to your JMeter Variables reference names, your current code will create only one Id_value variable with the value of 23336, you need to amend it like:
def csvfile = new File('D:/datas/id/ids.csv')
def lines =csvfile.readLines()
lines.eachWithIndex {line, idx ->
vars.put('Id_value_' + idx, line)
}
And you will get:
Id_value_0=23333
Id_value_1=23334
Id_value_2=23335
Id_value_3=22336
Id_value_4=23336
More information:
Groovy Collection.eachWithIndex()
Groovy is the New Black

Using groovy to append to a certain line number in a file

Rather than appending to the end of a file, I am trying to replace or append to a certain line using groovy File manipulation.
Is there a method to do this?
append adds to end of file while write overwrites existing file:
def file = new File("newFilename")
file.append("I wish to append this to line 8")
In general, with Java and Groovy file handling, you can only append to the end of files. There is no way to insert information, although you can overwrite data anywhere without shifting the position of what follows.
This means that to append to a specific line that is not at the end of the file you need to rewrite the whole file.
For example:
def file = new File("newFilename")
new File("output").withPrintWriter { out ->
def linenumber = 1
file.eachLine { line ->
if (linenumber == 8)
out.print(line)
out.println("I wish to append this to line 8")
} else {
out.println(line)
}
linenumber += 1
}
}
For small files you can use the following piece of code:
def f = new File('file')
def lines = f.readLines()
lines = lines.plus(7, "I'm a new line!")
f.text = lines.join('\n')

groovy replace data from file with space

i want to replace string from a file.
i have a line like this:
qwe{data:"dede-dddd-ssss",login:"user",display:"screen"},abc,xyz
i want to replace all string starting from data to login with spaces
i try this i can only replace the string, is there a way to replace with a starting and endpoint for string?
def source = new File("c:\\sq\\file1.txt")
def dest = new File("c:\\sq\\file2.txt")
def fileText = source.text
def filedest = dest.text
for ( index in 1..9 ) {
fileText = (fileText =~ /data/).replaceFirst("")
This code has an anchored version (to {) of the regex:
def fileText = '''\
qwe{data:"dede-dddd-ssss",login:"user",display:"screen1"},abc,xyz
...
qwe{data:"data2",login:"user2",display:"screen2"},abc,xyz
...
qwe{data:"data3",login:"user3",display:"screen3"},abc,xyz\
'''
fileText = fileText.replaceAll(/(?<=\{)\s*data:[^,]+,\s*login:[^,]+,/ , '')
println fileText
Output:
qwe{display:"screen1"},abc,xyz
...
qwe{display:"screen2"},abc,xyz
...
qwe{display:"screen3"},abc,xyz
Try also in the online groovy web console
UPDATE
If a understand correctly your request: this following code read the input text from source (c:\\sq\\file1.txt) and put the modified text into destination file dest (c:\\sq\\file2.txt):
def source = new File("c:\\sq\\file1.txt")
def dest = new File("c:\\sq\\file2.txt")
dest.write(source.text
.replaceAll(/(?<=\{)\s*data:[^,]+,\s*login:[^,]+,/ , '') )
If you want it in the files, then you can try below, and find the updated data in test2.txt:
note:please update the file paths as per your environment
Courtesy #GsusRecovery for regex
def fileContent = new File('/tmp/test.txt').text
def replacedContent = fileContent.replaceAll(/(?<=\{)\s*data:[^,]+,\s*login:[^,]+,/ , '')
def newFile = new File('/tmp/test2.txt')
newFile.write(replacedContent)
I'm not entirely clear on what your desired outcome is. If you want to remove the "data" and "login" fields and the corresponding values from the input strings, such that your example of:
qwe{data:"dede-dddd-ssss",login:"user",display:"screen"},abc,xyz
becomes:
qwe{display:"screen"},abc,xyz then you can easily use a regex to do this.
The following code:
​String str = """qwe{data:"dede-dddd-ssss",login:"user",display:"screen"},abc,xyz"​​""
str = str.replaceFirst("​​​​​​​​​​​​​data.*login:\".+?\",", '')
println str​
Prints qwe{display:"screen"},abc,xyz

Resources