Read test data from excel - java

I am using POM framework and test data I kept in a properties file (This code is working without any issue) but as per the current requirement, I should keep the test data in excel file. As per my code data is reading from excel but values are not sending to chrome(i cross-checked by printing the values in the console) when I debug I got to know that Data is returning a null value. The issue is with p.load(fs1); Line because data is not loading.
// below code is for properties file and its working without any issue.
/* public static String readTestData(String key) throws IOException {
String filename = "testData";
String path = System.getProperty("user.dir") + "/data/testData.properties";
if (path == null || path.length() == 0) {
path = System.getProperty("user.dir") + "/data/" + filename + ".properties";
}
Properties p = new Properties();
FileInputStream fs = new FileInputStream(path);
System.out.print("File Input Stream value is "+fs);
p.load(fs);
System.out.println("Value of login username is "+(String)p.get(key));
return (String) p.get(key);
}*/
// Below code is for reading test data from xlsx
public static String readTestData(String key) throws IOException {
String filename = "testData";
String path = System.getProperty("user.dir") + "/data/testData.xlsx";
if (path == null || path.length() == 0) {
path = System.getProperty("user.dir") + "/data/" + filename + ".xlsx";
}
Properties p = new Properties();
FileInputStream fs = new FileInputStream(path);
Workbook SapWorkbook = null;
StringBuffer sbf = new StringBuffer();
SapWorkbook = new XSSFWorkbook(fs);
Sheet SapSheet = SapWorkbook.getSheet("Sheet1");
int rowCount = SapSheet.getLastRowNum()-SapSheet.getFirstRowNum();
for (int i = 0; i < rowCount+1; i++) {
Row row = SapSheet.getRow(i);
//Create a loop to print cell values in a row
for (int j = 0; j < row.getLastCellNum(); j++) {
//Print Excel data in console
sbf.append(row.getCell(j).getStringCellValue());
System.out.print(row.getCell(j).getStringCellValue()+"|| ");
}
System.out.println();
}
byte[] bytes = sbf.toString().getBytes();
ByteArrayInputStream fs1 = new ByteArrayInputStream(bytes);
p.load(fs1);
System.out.println("Value of login username is "+(String)p.get(key));
return (String) p.get(key);
}
public static void enterText(String key, String data) throws IOException, InterruptedException {
try {
waitForPresenceAndVisibilityOfElementry(readobjectRepo(key));
WebElement ele = driver.findElement(By.xpath(readobjectRepo(key)));
ele.clear();
Thread.sleep(1200);
System.out.println("about to read Base page");
ele.sendKeys(readTestData(data));
System.out.println("data read");
startExtent.log(LogStatus.PASS, "Entering data.. " + readTestData(data) + " is sucessful");
Thread.sleep(1200);
} catch (Exception e) {
e.printStackTrace();
reportFailure("Click on element is unsucessful");
}
}
In the console result.
loginUserName|| ABCD#gmail.com||
loginPassword|| abc#1a||
Value of login username is null

Your code looks quite messy and could do with some clean up. This block is pointless:
String filename = "testData";
String path = System.getProperty("user.dir") + "/data/testData.xlsx";
if (path == null || path.length() == 0) {
path = System.getProperty("user.dir") + "/data/" + filename + ".xlsx";
}
You are just hard coding the same thing in different ways, stick to just
String path = System.getProperty("user.dir") + "/data/testData.xlsx";
It's pretty unclear what you are trying to do here, but I'm going to guess you want the value in the second column that is associated with a key that is in the first column. All of the stuff creating a properties object seems completely obsolete, so I've rewritten your code to be this:
Workbook SapWorkbook = new XSSFWorkbook(fs);
Sheet SapSheet = SapWorkbook.getSheet("Sheet1");
int rowCount = SapSheet.getLastRowNum() - SapSheet.getFirstRowNum();
for (int i = 0; i < rowCount + 1; i++) {
Row row = SapSheet.getRow(i);
if (key.equals(row.getCell(0).getStringCellValue())) {
return row.getCell(1).getStringCellValue();
}
}
throw new IllegalArgumentException(String.format("%s not found!", key));
This will now scroll through each row searching for the first instance of your "key" and will then return the associated "value". If it doesn't find a key it will throw an exception. To package it all up as a single method:
public static String readTestData(String key) throws IllegalArgumentException, IOException {
String path = System.getProperty("user.dir") + "/data/testData.xlsx";
FileInputStream fs = new FileInputStream(path);
Workbook SapWorkbook = new XSSFWorkbook(fs);
Sheet SapSheet = SapWorkbook.getSheet("Sheet1");
int rowCount = SapSheet.getLastRowNum() - SapSheet.getFirstRowNum();
for (int i = 0; i < rowCount + 1; i++) {
Row row = SapSheet.getRow(i);
if (key.equals(row.getCell(0).getStringCellValue())) {
return row.getCell(1).getStringCellValue();
}
}
throw new IllegalArgumentException(String.format("%s not found!", key));
}

Related

I'm having trouble setting the value of a variable that will update my test

My problem is in the part where I'm doing the "if/else" conditions, when I call the function that will perform the comparisons and will define if the test passed or not and will send some information, I'm receiving null.
Problems are among the asterisks. If anyone can help me
This is my code :
public static void fxSpot_GBP_JPY(TradeData data, TradeData output) throws Exception {
if (data == null) {
fail("The input data object was not correctly filled");
}
if (output == null) {
fail("The output data object was not correctly filled");
}
//Used to set the comment, the status and update to JIRA
FieldsJSON fields = new FieldsJSON();
String assertionError = "";
List<String> inputs = new ArrayList<String>();
List<String> outputs = new ArrayList<String>();
String newDate = Utils.formatTimeZoneMinute(data.getTradeDate());
String asOfTrade = Utils.formatTimeZoneMinute(data.getAsOfTradeDate());
String executionDate = Utils.formatTimeZoneMinute(output.getExecutionDateTime());
try {
//Add the data in the list
inputs.add(data.getTransactionNumber()); outputs.add(output.getBloombergId());
inputs.add(newDate); outputs.add(output.getTradeDate());
inputs.add(asOfTrade); outputs.add(executionDate);
inputs.add(data.getSettlementDate()); outputs.add(output.getValueDate());
inputs.add(data.getTradeAmount()); outputs.add(output.getAmount2());
inputs.add(data.getCustomerAccountCounterparty()); outputs.add(output.getMiPartyId());
inputs.add(data.getPrincipalLoanAmount()); outputs.add(output.getAmount());
inputs.add(data.getSecurityPrice()); outputs.add(output.getRate());
inputs.add(data.getISOCodeOf1stCurrency()); outputs.add("BRL");//output.getCurrency2()
inputs.add(data.getISOCodeOf2ndCurrency()); outputs.add(output.getCurrency1());
//Compare values
System.out.println("-------------------");
int y = 0;
int x = 0;
for(String input : inputs) {
for(String out : outputs) {
if(y == x) {
if(input.equals(out)) {
WriterCSV.setOk("Ok");
**String comment = input + " = " + out;
fields.setComment(comment);
fields.setStatus("PASS");**
System.out.println("ok - " + input + " = " + out);
}else {
WriterCSV.setOk("not Ok");
**String comment = input + " = " + out;
fields.setComment(comment);
fields.setStatus("FAIL");**
System.out.println("not Ok - " + input + " = " + out);
}
}
x = x+1; // count of the list of output
}
y = y+1; // count of the list of inputs
x = 0; // reset to 0 the count of outputs
}
// evidence with the name and value of fields compared
WriterCSV.reportSpot_CSV(data,output);
}
Here is my test:
#Test
#Tag("compare")
public void CompareSpot() throws Exception {
//Create a list to read the CSVfile
List<DTOTradeData> dto;
//Used to get the TradeData of list dto.
DTOTradeData dtd = new DTOTradeData();
// Read a csvFile and return a list with the values to new xml
dto = CSVReader.readCSV("spot.csv");
//The xpath of xml
FileDriverSpot spot = new FileDriverSpot();
FileDriver output = new FileDriverSpotOutput();
FieldsJSON fields = new FieldsJSON();
//new xml = dataInput and the outputFile = dataOutput
TradeData dataInput = new TradeData();
TradeData dataOutput = new TradeData();
for (int i = 0; i < dto.size(); i++) {
dtd = dto.get(i); // get TradeData
dtd.getTradeData().setDriver(spot); // set the driver
if (fileExist(Setup.xmlPath + dtd.getInputFile() + ".xml")) {
dataInput = Reader.read(spot, Setup.xmlPath + dtd.getInputFile() + ".xml");
dataOutput = Reader.read(output, Setup.spotPath + dtd.getOutputFile());
try {
// make the comparison
**FunctionalTest.fxSpot_GBP_JPY(dataInput, dataOutput);**
}
catch(AssertionError e) {
String comment = e.toString();
fields.setComment(comment);
}
} else {
fail("The file: " + dtd.getTemplateFile()
+ " needs to go through the writing process before being compared.");
}
//Convert the file to base64
String inputData = UpdateTestStatus.convertToBase64(Setup.xmlPath + dtd.getInputFile() + ".xml");
String outputData = UpdateTestStatus.convertToBase64(Setup.spotPath + dtd.getOutputFile());
String evidenceCompared = UpdateTestStatus.convertToBase64(Setup.reportPath+"ReportSpot.csv");
System.out.println(UpdateTestStatus.updateTestRun(**fields.getStatus(),fields.getComment()**,
inputData,dtd.getInputFile()+ ".xml", //data of the XML and the name of the file
outputData,dtd.getOutputFile(),
evidenceCompared,"ReportSpot.csv",
Setup.testExec, dtd.getJiraId()).asString()); // ID testExecution and ID of
}
}
The test and the code under test each create a separate instance of FieldsJSON. Data set in one instance will not be visible in the other (unless the data is declared static, in which case there's no need to create instances).
You can fix this by using a single instance, either passed to the fxSpot_GBP_JPY method from the test, or returned from that method to the test.

Blank row after header

I am writing existing excel by merging many excel files, after generating of final excel file blank row is adding up after headers.
Below is my code which reads data from multiple files and write to particular blank file which have pivot formulas set.
I tried even by
1. Setting createRow(0) , then started filling data from next row.
2. Tried of maintaining int counter, but still didn't work
3. Tried incrementing getLastRowNum() count, but no use
public class DCSReadImpl implements ReadBehavior {
Logger log = Logger.getLogger(DCSReadImpl.class.getName());
#SuppressWarnings("resource")
#Override
public Sheet readReport(Workbook workbook,Map<String,String> masterMap, Properties properties) {
//int firstRow = 0;
int outRowCounter = 0;
String fileToMove= "";
boolean headers = true;
Row outputRow = null;
Sheet outputSheet = null;
Workbook wb = new XSSFWorkbook();
try {
outputSheet = wb.createSheet("Data");
log.info("**** Set headers start"); // this used to be different method
int cellNo = 0;
outputRow = outputSheet.createRow(0);
for(String headerName : ReportConstants.DCS_OUTPUT_HEADER){
outputRow.createCell(cellNo).setCellValue(headerName);
cellNo++;
}
//outRowCounter++;
log.info("**** Set headers completed");
log.info("Read input file(s) for DCS report");
log.info("Input File Path : " + properties.getProperty(ReportConstants.DCS_INPUT_PATH));
File inputDir = new File(properties.getProperty(ReportConstants.DCS_INPUT_PATH));
File[] dirListing = inputDir.listFiles();
if (0 == dirListing.length) {
throw new Exception(properties.getProperty(ReportConstants.DCS_INPUT_PATH) + " is empty");
}
for (File file : dirListing) {
log.info("Processing : " + file.getName());
fileToMove = file.getName();
XSSFWorkbook inputWorkbook = null;
try {
inputWorkbook = new XSSFWorkbook(new FileInputStream(file));
} catch (Exception e) {
throw new Exception("File is already open, please close the file");
}
XSSFSheet inputsheet = inputWorkbook.getSheet("Sheet1");
Iterator<Row> rowItr = inputsheet.iterator();
int headItr = 0;
//log.info("Validating headers : " + file.getName());
while (rowItr.hasNext()) {
Row irow = rowItr.next();
Iterator<Cell> cellItr = irow.cellIterator();
int cellIntItr = 0;
String key = "";
int rowN = outputSheet.getLastRowNum() + 1;
outputRow = outputSheet.createRow(rowN);
Cell outCell = null;
while (cellItr.hasNext()) {
Cell inputCell = cellItr.next();
if (0 == inputCell.getRowIndex()) {
if (!FileUtility.checkHeaders(headItr, inputCell.getStringCellValue().trim(),
ReportConstants.DCS_INPUT_HEADER)) {
throw new Exception("Incorrect header(s) present in Input File, Expected : "
+ ReportConstants.DCS_INPUT_HEADER[headItr]);
}
headItr++;
} else {
//outCell = outputRow.createCell(cellIntItr);
if (0 == inputCell.getColumnIndex()) {
key = inputCell.getStringCellValue().trim();
} else if (2 == inputCell.getColumnIndex()) {
key = key + ReportConstants.DEL + inputCell.getStringCellValue().trim();
}
if (7 == cellIntItr){
outCell = outputRow.createCell(cellIntItr);
outCell.setCellValue(getValue(masterMap, key, 0));
cellIntItr++;
outCell = outputRow.createCell(cellIntItr);
outCell.setCellValue(getValue(masterMap, key, 1));
cellIntItr++;
outCell = outputRow.createCell(cellIntItr);
outCell.setCellValue(getValue(masterMap, key, 2));
cellIntItr++;
}
// Check the cell type and format accordingly
switch (inputCell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC:
outCell = outputRow.createCell(cellIntItr);
outCell.setCellValue(inputCell.getNumericCellValue());
break;
case Cell.CELL_TYPE_STRING:
outCell = outputRow.createCell(cellIntItr);
outCell.setCellValue(inputCell.getStringCellValue().trim());
break;
}
cellIntItr++;
}
}
//outRowCounter ++ ;
}
if(!fileToMove.isEmpty()){
FileUtility.checkDestinationDir(""+properties.get(ReportConstants.DCS_ARCHIVE_PATH));
FileUtility.moveFile(properties.get(ReportConstants.DCS_INPUT_PATH) + fileToMove,
properties.get(ReportConstants.DCS_ARCHIVE_PATH)+fileToMove+FileUtility.getPattern());
}
}
} catch (Exception e) {
log.error("Exception occured : ", e);
}
FileOutputStream outputStream;
try {
outputStream = new FileOutputStream("D:\\DCS\\Output\\Krsna_"+FileUtility.getPattern()+".xlsx");
wb.write(outputStream);
} catch (Exception e) {
e.printStackTrace();
}
return outputSheet;
}
private String getValue(Map<String, String> masterMap, String cellKey, int index) {
String value = masterMap.get(cellKey);
if (null != value) {
String cellValue[] = value.split("\\" + ReportConstants.DEL);
return cellValue[index];
} else {
return "";
}
}
}
There should not be blank row after header row. That is in between of 0th row and 1st row (hope my understanding is correct on row indexing). I know this is very basic question :-(

want to print a particular cell's all the row values in excel in java

After getting a paticular item name and price I store it in excel sheet. Now I compare their price and get lowest price, but how can i print that lowest price all detail
my code is
public static void getMinPhonePrice() throws Exception {
File file = new File("C:\\Users\\user\\Desktop\\demo.xlsx");
FileInputStream fs = new FileInputStream(file);
XSSFWorkbook wb=new XSSFWorkbook(fs);
String min = wb.getSheetAt(0).getRow(0).getCell(1).getStringCellValue();
int value_min = Integer.parseInt(min.substring(1).replace(",", ""));
String getText = null;
XSSFSheet sh1= wb.getSheetAt(0);
for(int j=0;j<3;j++) {
getText = sh1.getRow(0).getCell(j).getStringCellValue();
System.out.println(getText);
}
for (int i = 1; i <=sh1.getLastRowNum(); i++) {
String c = sh1.getRow(i).getCell(1).getStringCellValue();
int value = Integer.parseInt(c.substring(1).replace(",", ""));
if(value < value_min) {
value_min=value;
for(int k=0;k<3;k++) {
getText = sh1.getRow(i).getCell(k).getStringCellValue();
System.out.println("minimum item detail"+getText);
}
}
}
}
}
but it not printing my minimum item detail
It seems like you don't need nested loop, and you need store other cell to string variable. Please try the bellow code.
File file = new File("phone_compare.xlsx");
FileInputStream fs = new FileInputStream(file);
XSSFWorkbook wb=new XSSFWorkbook(fs);
String min = wb.getSheetAt(0).getRow(0).getCell(1).getStringCellValue();
int value_min = Integer.parseInt(min.substring(1).replace(",", ""));
String getText = null;
String str1 = wb.getSheetAt(0).getRow(0).getCell(0).getStringCellValue();
String str2 = wb.getSheetAt(0).getRow(0).getCell(2).getStringCellValue();
getText = str1 +" " +value_min +" " +str2;
XSSFSheet sh1= wb.getSheetAt(0);
for (int i = 0; i <=sh1.getLastRowNum(); i++) {
String c = wb.getSheetAt(0).getRow(i).getCell(1).getStringCellValue();
int value = Integer.parseInt(c.substring(1).replace(",", ""));
if(value < value_min) {
value_min=value;
str1 = wb.getSheetAt(0).getRow(i).getCell(0).getStringCellValue();
str2 = wb.getSheetAt(0).getRow(i).getCell(2).getStringCellValue();
getText = str1 +" " +value_min +" " +str2;
}
}
System.out.println(getText);
}

Unable to write new excel using Apache POI after removing duplicate rows

I am new to Apache POI.
I have written a small code for removing duplicate records from a excel file. I am successfully able to identify the duplicate records across sheets but when writing to a new file after removing records, no output is being generated.
Please help where I am goin wrong?
Am I writing properly ?? Or am missing something?
public static void main(String args[]) {
DataFormatter formatter = new DataFormatter();
HSSFWorkbook input_workbook;
HSSFWorkbook workbook_Output_Final;
HSSFSheet input_workbook_sheet;
HSSFRow row_Output;
HSSFRow row_1_index;
HSSFRow row_2_index;
String value1 = "";
String value2 = "";
int count;
//main try catch block starts
try {
FileInputStream input_file = new FileInputStream("E:\\TEST\\Output.xls"); //reading from input file
input_workbook = new HSSFWorkbook(new POIFSFileSystem(input_file));
for (int sheetnum = 0; sheetnum < input_workbook.getNumberOfSheets(); sheetnum++) { //traversing sheets
input_workbook_sheet = input_workbook.getSheetAt(sheetnum);
int input_workbook_sheet_total_row = input_workbook_sheet.getLastRowNum(); //fetching last row nmber
for (int input_workbook_sheet_row_1 = 0; input_workbook_sheet_row_1 <= input_workbook_sheet_total_row; input_workbook_sheet_row_1++) { //traversing row 1
for (int input_workbook_sheet_row_2 = 0; input_workbook_sheet_row_2 <= input_workbook_sheet_total_row; input_workbook_sheet_row_2++) {
row_1_index = input_workbook_sheet.getRow(input_workbook_sheet_row_1); //fetching one iteration row index
row_2_index = input_workbook_sheet.getRow(input_workbook_sheet_row_2); //fetching sec iteration row index
if (row_1_index != row_2_index) {
count = 0;
value1 = "";
value2 = "";
for (int row_1_index_cell = 0; row_1_index_cell < row_1_index.getLastCellNum(); row_1_index_cell++) { //traversing cell for each row
try {
value1 = value1 + formatter.formatCellValue(row_1_index.getCell(row_1_index_cell)); //fetching row cells value
value2 = value2 + formatter.formatCellValue(row_2_index.getCell(row_1_index_cell)); //fetching row cells value
} catch (NullPointerException e) {
}
count++;
if (count == row_1_index.getLastCellNum()) {
if (value1.hashCode() == value2.hashCode()) { //remove the duplicate logic
System.out.println("deleted : " + row_2_index);
System.out.println("------------------");
input_workbook_sheet.removeRow(row_2_index);
}
}
}
}
}
}
}
FileOutputStream fileOut = new FileOutputStream("E:\\TEST\\workbook.xls");
input_workbook.write(fileOut);
fileOut.close();
input_file.close();
} catch (Exception e) {
//e.printStackTrace();
}
//main try catch block ends
}
A couple of things to note:
you swallow any kind of Exception; Igotsome nullpointers with my test data, and that would prevent the workbook from being written
when removing rows, it is an old trick to move backwards through the row numbers because then you don't have to adjust for the row number you have just removed
the code empties the row, but it doesn't move all rows upwards (=there is a gap after the delete). If you want to remove that gap, you can work with shiftRows
you compare things by hashcode, which is possible (in some use cases), but I feel like .equals() is what you want to do. See also Relationship between hashCode and equals method in Java
Here's some code that worked for my test data, feel free to comment if something doesn't work with your data:
public static void main(String args[]) throws IOException {
DataFormatter formatter = new DataFormatter();
HSSFWorkbook input_workbook;
HSSFWorkbook workbook_Output_Final;
HSSFSheet input_workbook_sheet;
HSSFRow row_Output;
HSSFRow row_1_index;
HSSFRow row_2_index;
String value1 = "";
String value2 = "";
int count;
FileInputStream input_file = new FileInputStream("c:\\temp\\test.xls");
input_workbook = new HSSFWorkbook(new POIFSFileSystem(input_file));
for (int sheetnum = 0; sheetnum < input_workbook.getNumberOfSheets(); sheetnum++) {
input_workbook_sheet = input_workbook.getSheetAt(sheetnum);
int input_workbook_sheet_total_row = input_workbook_sheet.getLastRowNum();
for (int input_workbook_sheet_row_1 = input_workbook_sheet_total_row; input_workbook_sheet_row_1 >=0; input_workbook_sheet_row_1--) { // traversing
for (int input_workbook_sheet_row_2 = input_workbook_sheet_total_row; input_workbook_sheet_row_2 >= 0 ; input_workbook_sheet_row_2--) {
row_1_index = input_workbook_sheet.getRow(input_workbook_sheet_row_1);
row_2_index = input_workbook_sheet.getRow(input_workbook_sheet_row_2);
if (row_1_index != null && row_2_index != null && row_1_index != row_2_index) {
count = 0;
value1 = "";
value2 = "";
int row_1_max = row_1_index.getLastCellNum() - 1;
for (int row_1_index_cell = 0; row_1_index_cell < row_1_max; row_1_index_cell++) {
try {
value1 = value1 + formatter.formatCellValue(row_1_index.getCell(row_1_index_cell));
value2 = value2 + formatter.formatCellValue(row_2_index.getCell(row_1_index_cell));
} catch (NullPointerException e) {
e.printStackTrace();
}
count++;
if (value1.equals(value2)) {
System.out.println("deleted : " + row_2_index.getRowNum());
System.out.println("------------------");
input_workbook_sheet.removeRow(row_2_index);
input_workbook_sheet.shiftRows(
row_2_index.getRowNum() + 1,
input_workbook_sheet_total_row,
-1,
true,
true);
}
}
}
}
}
}
FileOutputStream fileOut = new FileOutputStream("c:\\temp\\workbook.xls");
input_workbook.write(fileOut);
fileOut.close();
input_file.close();
input_workbook.close();
}

How to increment the filename number if the file exists

How can I increment the filename if the file already exists?
Here's the code that I am using -
int num = 0;
String save = at.getText().toString() + ".jpg";
File file = new File(myDir, save);
if (file.exists()) {
save = at.getText().toString() + num + ".jpg";
file = new File(myDir, save);
num++;
}
This code works, but only two files are saved, like file.jpg and file2.jpg.
This problem is to always initialize num = 0, so if file exists, it saves file0.jpg and does not check whether file0.jpg exists.
So, to code work. You should check until it is available:
int num = 0;
String save = at.getText().toString() + ".jpg";
File file = new File(myDir, save);
while(file.exists()) {
save = at.getText().toString() + (num++) + ".jpg";
file = new File(myDir, save);
}
Try this:
File file = new File(myDir, at.getText().toString() + ".jpg");
for (int num = 0; file.exists(); num++) {
file = new File(myDir, at.getText().toString() + num + ".jpg");
}
// Now save/use your file here
In addition to the first answer, I made some more changes:
private File getUniqueFileName(String folderName, String searchedFilename) {
int num = 1;
String extension = getExtension(searchedFilename);
String filename = searchedFilename.substring(0, searchedFilename.lastIndexOf("."));
File file = new File(folderName, searchedFilename);
while (file.exists()) {
searchedFilename = filename + "(" + (num++) + ")" + extension;
file = new File(folderName, searchedFilename);
}
return file;
}
int i = 0;
String save = at.getText().toString();
String filename = save +".jpg";
File f = new File(filename);
while (f.exists()) {
i++;
filename =save+ Integer.toString(i)+".jpg";
f = new File(filename);
}
f.createNewFile();
You can avoid the code repetition of some of the answers here by using a do while loop
Here's an example using the newer NIO Path API introduced in Java 7
Path candidate = null;
int counter = 0;
do {
candidate = Paths.get(String.format("%s-%d",
path.toString(), ++counter));
} while (Files.exists(candidate));
Files.createFile(candidate);
Kotlin version:
private fun checkAndRenameIfExists(name: String): File {
var filename = name
val extension = "pdf"
val root = Environment.getExternalStorageDirectory().absolutePath
var file = File(root, "$filename.$extension")
var n = 0
while (file.exists()) {
n += 1
filename = "$name($n)"
file = File(root, appDirectoryName + File.separator + "$filename.$extension")
}
return file
}
Another simple logic solution to get the unique file name under a directory using Apache Commons IO using WildcardFileFilter to match the file name and get the number of exists with the given name and increment the counter.
public static String getUniqueFileName(String directory, String fileName) {
String fName = fileName.substring(0, fileName.lastIndexOf("."));
Collection<File> listFiles = FileUtils.listFiles(new File(directory), new WildcardFileFilter(fName + "*", IOCase.INSENSITIVE), DirectoryFileFilter.DIRECTORY);
if(listFiles.isEmpty()) {
return fName;
}
return fName.concat(" (" + listFiles.size() + ")");
}
This is the solution I use to handle this case. It works for folders as well as for files.
var destination = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "MyFolder")
if (!destination.exists()) {
destination.mkdirs()
} else {
val numberOfFileAlreadyExist =
destination.listFiles().filter { it.name.startsWith("MyFolder") }.size
destination = File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
"MyFolder(${numberOfFileAlreadyExist + 1})"
)
destination.mkdirs()
}
Having needed to solve this problem in my own code, I took Tejas Trivedi's answer, made it work like Windows when you happen to download the same file several times.
// This function will iteratively to find a unique file name to use when given a file: example (###).txt
// More or less how Windows will save a new file when one already exists: 'example.txt' becomes 'example (1).txt'.
// if example.txt already exists
private File getUniqueFileName(File file) {
File originalFile = file;
try {
while (file.exists()) {
String newFileName = file.getName();
String baseName = newFileName.substring(0, newFileName.lastIndexOf("."));
String extension = getExtension(newFileName);
Pattern pattern = Pattern.compile("( \\(\\d+\\))\\."); // Find ' (###).' in the file name, if it exists
Matcher matcher = pattern.matcher(newFileName);
String strDigits = "";
if (matcher.find()) {
baseName = baseName.substring(0, matcher.start(0)); // Remove the (###)
strDigits = matcher.group(0); // Grab the ### we'll want to increment
strDigits = strDigits.substring(strDigits.indexOf("(") + 1, strDigits.lastIndexOf(")")); // Strip off the ' (' and ').' from the match
// Increment the found digit and convert it back to a string
int count = Integer.parseInt(strDigits);
strDigits = Integer.toString(count + 1);
} else {
strDigits = "1"; // If there is no (###) match then start with 1
}
file = new File(file.getParent() + "/" + baseName + " (" + strDigits + ")" + extension); // Put the pieces back together
}
return file;
} catch (Error e) {
return originalFile; // Just overwrite the original file at this point...
}
}
private String getExtension(String name) {
return name.substring(name.lastIndexOf("."));
}
Calling getUniqueFileName(new File('/dir/example.txt') when 'example.txt' already exists while generate a new File targeting '/dir/example (1).txt' if that too exists it'll just keep incrementing number between the parentheses until a unique file is found, if an error happens, it'll just give the original file name.
I hope this helps some one needing to generate a unique file in Java on Android or another platform.
This function returns the exact new file with an increment number for all kind of extensions.
private File getFileName(File file) {
if (file.exists()) {
String newFileName = file.getName();
String simpleName = file.getName().substring(0, newFileName.indexOf("."));
String strDigit = "";
try {
simpleName = (Integer.parseInt(simpleName) + 1 + "");
File newFile = new File(file.getParent() + "/" + simpleName + getExtension(file.getName()));
return getFileName(newFile);
}
catch (Exception e){
}
for (int i=simpleName.length()-1; i>=0; i--) {
if (!Character.isDigit(simpleName.charAt(i))) {
strDigit = simpleName.substring(i + 1);
simpleName = simpleName.substring(0, i+1);
break;
}
}
if (strDigit.length() > 0) {
simpleName = simpleName + (Integer.parseInt(strDigit) + 1);
}
else {
simpleName += "1";
}
File newFile = new File(file.getParent() + "/" + simpleName + getExtension(file.getName()));
return getFileName(newFile);
}
return file;
}
private String getExtension(String name) {
return name.substring(name.lastIndexOf("."));
}

Categories

Resources