Get latest file based on file name pattern in java - java

Have file name pattern as YYYYMDD or YYYYMMDD as below.
Have list of files with below pattern in a directory.
Have to read the latest file based on the file name in java.
How to do this?
xxx_2016103
....
xxx_20161104

If you have your filenames in a list, you can create a custom comparator to sort the list based on the date in the filename.
public class FilenamesWithDateSuffixComparator implements Comparator<String> {
private static final int ONE_DIGIT_MONTH_FORMAT = "yyyyMdd".length();
#Override
public int compare(String o1, String o2) {
String date1 = o1.substring(o1.lastIndexOf("_") + 1);
String date2 = o2.substring(o2.lastIndexOf("_") + 1);
// If the dates only have one digit for the month, insert a zero.
if (date1.length() == ONE_DIGIT_MONTH_FORMAT) {
date1 = date1.substring(0, 4) + "0" + date1.substring(5);
}
if (date2.length() == ONE_DIGIT_MONTH_FORMAT) {
date2 = date2.substring(0, 4) + "0" + date2.substring(5);
}
return date1.compareTo(date2);
}
}
Then, you can sort the list using the comparator:
Collections.sort(fileNamesList, new FilenamesWithDateSuffixComparator());
Or using the list short method in Java 8:
fileNamesList.sort(new FilenamesWithDateSuffixComparator());

Best solution is to fetch the dates, map them to files, and let the fact that TreeMap objects implement SortedMap so they are ordered do the work for you.
Map<Date,File> filedatemap = new TreeMap<Date,File>();
for(File f : inputdir.listFiles()) { //Assumption: inputdir is a File object pointing to the target directory.
String filename = f.getName();
DateFormat df = new SimpleDateFormat("YYYYMMdd");
Date filedate = df.parse(filename, new ParsePosition(filename.getLastIndexOf('_'));
filedatemap.put(filedate,f);
}
File latestfile = filedatemap.lastEntry().getValue(); //Last entry because natural order of Date is chronological.
//Go do things with that file
For best results, take Zircon's comment to heart and pad your single digit Months/Days with 0 so that that SimpleDateFormat will parse correctly.

Create a small class FileDateWrapper containing String filename; DateTime date;
Collect all the filenames in a List<FileDateWrapper> (leave date null for now)
Use some date/time API like Joda or java.time (Java 8 +) to create two date formats (as you have described)
Go through the list, striping off the _ character (.split()) and then attempting to parse the resulting string on both formats (eg. using parseDateTime(String). Store the date that was succesfully parsed in the field of your FileDateWrapper
Implement Comparator or Comparable and sort your list of FileDateWrapper (or Collections.max)

Related

Selecting files by date in java [duplicate]

I'm trying to filter the files by date and to read each file. I have a find() method that read each filename and it returns a files start by "B" in array. The second method filesort(), it will return all the file dates from filename that sent from find() method. In main method I want to read the file by the specific date i'm giving. if all the files has the same date, it reads all the file. However, from the files one of the file has different date it will throw error.
public static String[] find(String rootPath){
File root = new File(rootPath);
// Filter files whose name start with "B"
FilenameFilter beginswithm = new FilenameFilter() {
public boolean accept(File directory, String filename) {
return filename.startsWith("B");
}
};
// array to store filtered file names
String[] files = root.list(beginswithm);
String[] no = { "nofile" };
if (files == null) {
return no;
}
return files;
}
public String filesort() throws ParseException {
String path = "C:";
String [] filesList = find(path);
for (String file : filesList) {
File st = new File(file);
String name=st.getName();
name= name.replaceAll("\\D+", "");
String Datename = name.substring(0, 8);
DateFormat formatter = new SimpleDateFormat("yyyymmdd");
Date date = (Date)formatter.parse(Datename);
SimpleDateFormat newFormat = new SimpleDateFormat("mm/dd/yyyy");
String finalString = newFormat.format(date);
return finalString;
}
return "error";
}
public static void main(String[] args){
String path = "C:";
String [] filesList = find(path);
for (String file : filesList) {
if(filesort().equals("04/17/2019"))//to read all files that has 04/17/2018
{
reader = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(path + "//" +file))));
String content;
while ((content = reader.readLine()) != null) {
System.out.println(content);
}
}
else if (!filesort().equals("04/17/2019")||filesort()==null ) {
System.out.println("incorect date");
}
}
this are the files I'm trying to read
BProce.Arr.20190416.server10.gz
BProce.Arr.20190417..ball10.gz
BProce.Arr.20190417.ball23.gz
because the first file is 04/16/2019, it will throw incorrect date. if 3 of them has 04/17/2019, it will read without issue.
but for now i want to read only the file that has a date 04/17/2019
If we look the problem from another point, it seems very simple to achieve what you want. I will give basic logic.
Read files name from directory. here is example how to do it
Store the names in ArrayList
Sort the ArrayList using Collections following link helps you
Now you have sorted file names of directory whenever you need access just access ArrayList element and using it access real file
Happy Coding, Please let me know if you have still problem
To find file which name is start on 'B' and contains specific date just follow this procedure.
You can find all file using this code with the File class.
public File[] find(String path) {
File dir = new File(path);
File[] listOfFiles = null;
if (dir.isDirectory()) {
listOfFiles = dir.listFiles();
}
return fileList;
}
From this list of file you can get file name then check this file name start with 'B' and
check whether it contains specific date. String object has startsWith() method. You don't need to change date string as Date object. Simply you can check filename contains date string or not.
Never use the terrible Date, DateFormat, or SimpleDateFormat classes. Use only java.time classes.
The Answer by Rishoban looks correct. Add to that this discussion of parsing date.
Ask if each File object represents a file versus a directory by calling File::isFile. Call File::getName to produce a String with the text of the file name. Then use String::startsWith and String::substring to analyze the file name. Pull out the text of a possible date. Validate by attempting to parse the text as a LocalDate. Define a DateTimeFormatter with a formatting pattern to match your expected inputs.
LocalDate targetDate = LocalDate.of( 2019 , Month.APRIL , 17 ) ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM/dd/uuuu" ) ;
int lengthOfExpectedDateInput = 10 ; // "01/23/2019" is 10 characters long.
String fileName = file.getName() ;
if( file.isFile() && fileName.startsWith( "B" ) ) {
String possibleDateInput = fileName.substring( 1 , 1 + lengthOfExpectedDateInput ) ; // Annoying zero-based index counting where 1 means the 2nd position.
try {
LocalDate ld = LocalDate.parse( possibleDateInput , f ) ; // Parse string as a `LocalDate` object. If input fails to match formatting pattern, a `DateTimeParseException` is thrown.
if( ld.isEqual( targetDate ) ) {
// Handle a valid file with expected file name.
…
}
} catch ( DateTimeParseException e ) {
// Handle unexpected file name.
…
}
}
By the way, educate the publisher of these file names about the ISO 8601 standard. A date should be in format YYYY-MM-DD.
Your Question is really a duplicate of many others. Search Stack Overflow before posting.

How to solve this error "String Cannot be converted to Date"?

Hello I am trying to store the birthdate of the user in database with the code below:
private void btnActionPerformed(java.awt.event.ActionEvent evt) {
String username = txtUserName.getText();
String password = txtPassword.getText();
String email = txtEmail.getText();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String birthdate = sdf.format(JDateChooser.getDate());
Users user = new Users();
user.setUserName(cin);
user.setPassWord(firstName);
user.setEmail(email);
user.setBirthDate(birthdate);
try {
int count = Users.getInstance().insert(user);
if(count == 1){
JOptionPane.showMessageDialog(null,"success");
reset();
}else{
JOptionPane.showMessageDialog(null,"Faild");
}
} catch (Exception ex) {
Logger.getLogger(AddNewPatient.class.getName()).log(Level.SEVERE, null, ex);
}
}
I got an error which says String connot be converted to Date in the line "user.setBirthDate(birthdate);"
Because the parameter birthdate is assigned as Date type in the encapsulation(setBirthDate)
is there any way to solve this issue, I am new in java programming and I am trying to improve my skills in java.
If this returns a Date:
JDateChooser.getDate()
And what you need is a Date, then don't convert it to a String. Just keep it as a Date:
Date birthdate = JDateChooser.getDate();
// later...
user.setBirthDate(birthdate);
Note that you can then also remove this line, since you're not using the variable it declares:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
In general you want to keep data types in their raw form pretty much as often as possible. Unless there's a specific need for something to be represented as a string (displaying it to the user, sending it over a serialized API of some kind, etc.) then just use the data as-is instead of converting it to something else.
After you get the date with JDateChooser.getDate(), you are immediately converting it to a string: sdf.format(JDateChooser.getDate());
You should store the returned Date from JDateChooser.getDate() as an actual Date object.
Date birthdate = JDateChooser.getDate();
Then you can use it in your other function directly:
user.setBirthDate(birthdate);
If you do need the date as a string for some other purpose (perhaps display to the user), you can store a formatted string version in a different variable:
String birthdateString = sdf.format(birthdate);
Otherwise, if you don't need a string version, you can delete the line where you create sdf.

I'm trying to filter the files by date

I'm trying to filter the files by date and to read each file. I have a find() method that read each filename and it returns a files start by "B" in array. The second method filesort(), it will return all the file dates from filename that sent from find() method. In main method I want to read the file by the specific date i'm giving. if all the files has the same date, it reads all the file. However, from the files one of the file has different date it will throw error.
public static String[] find(String rootPath){
File root = new File(rootPath);
// Filter files whose name start with "B"
FilenameFilter beginswithm = new FilenameFilter() {
public boolean accept(File directory, String filename) {
return filename.startsWith("B");
}
};
// array to store filtered file names
String[] files = root.list(beginswithm);
String[] no = { "nofile" };
if (files == null) {
return no;
}
return files;
}
public String filesort() throws ParseException {
String path = "C:";
String [] filesList = find(path);
for (String file : filesList) {
File st = new File(file);
String name=st.getName();
name= name.replaceAll("\\D+", "");
String Datename = name.substring(0, 8);
DateFormat formatter = new SimpleDateFormat("yyyymmdd");
Date date = (Date)formatter.parse(Datename);
SimpleDateFormat newFormat = new SimpleDateFormat("mm/dd/yyyy");
String finalString = newFormat.format(date);
return finalString;
}
return "error";
}
public static void main(String[] args){
String path = "C:";
String [] filesList = find(path);
for (String file : filesList) {
if(filesort().equals("04/17/2019"))//to read all files that has 04/17/2018
{
reader = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(path + "//" +file))));
String content;
while ((content = reader.readLine()) != null) {
System.out.println(content);
}
}
else if (!filesort().equals("04/17/2019")||filesort()==null ) {
System.out.println("incorect date");
}
}
this are the files I'm trying to read
BProce.Arr.20190416.server10.gz
BProce.Arr.20190417..ball10.gz
BProce.Arr.20190417.ball23.gz
because the first file is 04/16/2019, it will throw incorrect date. if 3 of them has 04/17/2019, it will read without issue.
but for now i want to read only the file that has a date 04/17/2019
If we look the problem from another point, it seems very simple to achieve what you want. I will give basic logic.
Read files name from directory. here is example how to do it
Store the names in ArrayList
Sort the ArrayList using Collections following link helps you
Now you have sorted file names of directory whenever you need access just access ArrayList element and using it access real file
Happy Coding, Please let me know if you have still problem
To find file which name is start on 'B' and contains specific date just follow this procedure.
You can find all file using this code with the File class.
public File[] find(String path) {
File dir = new File(path);
File[] listOfFiles = null;
if (dir.isDirectory()) {
listOfFiles = dir.listFiles();
}
return fileList;
}
From this list of file you can get file name then check this file name start with 'B' and
check whether it contains specific date. String object has startsWith() method. You don't need to change date string as Date object. Simply you can check filename contains date string or not.
Never use the terrible Date, DateFormat, or SimpleDateFormat classes. Use only java.time classes.
The Answer by Rishoban looks correct. Add to that this discussion of parsing date.
Ask if each File object represents a file versus a directory by calling File::isFile. Call File::getName to produce a String with the text of the file name. Then use String::startsWith and String::substring to analyze the file name. Pull out the text of a possible date. Validate by attempting to parse the text as a LocalDate. Define a DateTimeFormatter with a formatting pattern to match your expected inputs.
LocalDate targetDate = LocalDate.of( 2019 , Month.APRIL , 17 ) ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM/dd/uuuu" ) ;
int lengthOfExpectedDateInput = 10 ; // "01/23/2019" is 10 characters long.
String fileName = file.getName() ;
if( file.isFile() && fileName.startsWith( "B" ) ) {
String possibleDateInput = fileName.substring( 1 , 1 + lengthOfExpectedDateInput ) ; // Annoying zero-based index counting where 1 means the 2nd position.
try {
LocalDate ld = LocalDate.parse( possibleDateInput , f ) ; // Parse string as a `LocalDate` object. If input fails to match formatting pattern, a `DateTimeParseException` is thrown.
if( ld.isEqual( targetDate ) ) {
// Handle a valid file with expected file name.
…
}
} catch ( DateTimeParseException e ) {
// Handle unexpected file name.
…
}
}
By the way, educate the publisher of these file names about the ISO 8601 standard. A date should be in format YYYY-MM-DD.
Your Question is really a duplicate of many others. Search Stack Overflow before posting.

Redefining values to FilenameFilter in Java

I have files present in a Directory with the format ddMMyyyyhhmmss (for example 190420120533481146Wj.jpeg). I am trying to pick only latest 10 files from this directory .
Now as you can see I am searching the file names by using the substring (1904201212) of the current date.
For example :
Actual Date :19042012121306
Subs value :190420121213
As you can see in the below program, I am starting my search with the current date minute value. If there aren't any files for the current date minute value,
I want to redefine my search to current date hour value, and if there aren't in that case
I want to further redefine it to current date value, if not found,
Redefine it to previous days like that.
public class Raa {
public static void main(String args[])
{
File myDir = new File("C:\\");
String res = new Raa().getTime();
System.out.println(res);
String substring = res.substring(0,12);
System.out.println(substring);
FilenameFilter select = new FileListFilter(substring);
File[] contents = myDir.listFiles(select);
for (File file : contents) {
System.out.println(file.getName());
}
}
public String getTime()
{
SimpleDateFormat sdf = new SimpleDateFormat("ddMMyyyyhhmmss");
Date curDate = new Date();
String strDate = sdf.format(curDate);
return strDate;
}
}
How can we continuously redefine searches programatically?
The best way to get the list of files is to use File.listFiles() and as documentation states that there is no guarantee about the order of the files returned. Therefore you need to write a Comparator that uses File.lastModified() and pass this, along with the array of files, to Arrays.sort().
File[] files = directory.listFiles();
Arrays.sort(files, new Comparator(){
public int compare(File file1, File file2)
{
return Long.valueOf(file1.lastModified()).compareTo(file2.lastModified());
}
});
Once you get the list of files then only fetch the first 10 elements in the array.

String to date with no format specified

I want to convert a string into a date, this is simple. But what I'd like to do it without knowing the date format.
Here is a situation: say I have 100 dates and all are in the same format but I'd like to write a Java program to find out this format for me. The result of this program should give me a list of all the possible formats.
For example:
06-06-2006
06-06-2009
...
06-13-2001 <- 99th record
the result of this will give me date format can be mm-dd-yyyy
If the 99th record also was 06-06-2006 the result should be mm-dd-yyyy and dd-mm-yyyy.
Can someone please help me with an example?
Seems sensible to create a set of formats you know about (DATE_FORMATS) and then test each line to see which formats understand every line. You should end up with a set of possibilities.
public class DateFormatDetector {
private static final Set<String> DATE_FORMATS = new HashSet<String>();
static {
DATE_FORMATS.add("yyyy-MM-dd");
DATE_FORMATS.add("dd-MM-yyyy");
DATE_FORMATS.add("MM-dd-yyyy");
}
public static Set<String> getPossibleDateFormats(List<String> dates) {
Set<SimpleDateFormat> candidates = new HashSet<SimpleDateFormat>();
for (String df : DATE_FORMATS) {
SimpleDateFormat candidate = new SimpleDateFormat(df);
candidate.setLenient(false);
candidates.add(candidate);
}
for (String date : dates) {
Iterator<SimpleDateFormat> it = candidates.iterator();
while (it.hasNext()) {
SimpleDateFormat candidate = it.next();
try {
// try to parse the string as a date
candidate.parse(date);
}
catch (ParseException e) {
// failed to parse, so this format is not suitable
it.remove();
}
}
}
Set<String> results = new HashSet<String>();
for (SimpleDateFormat candidate : candidates)
results.add(candidate.toPattern());
return results;
}
}
Try to use SimpleDateFormat prepare all possible formats and calculate parsed result.
The solution could be functional Java as described for example in the stack overflow

Categories

Resources