I want to pick only those files which have "txt" extension and are more than 1 minute old. Is there a way to enforce both of these conditions in the listFiles method?
To ensure it picks only txt files, this is how I did
Collection<File> myFiles = FileUtils.listFiles(FileUtils.getFile(inputPath),
FileFilterUtils.suffixFileFilter(".txt"),
null);
I could find isFileOlder() method in FileUtils but how to impose both restrictions to it?
Please suggest some way.
You want to use the AndFileFilter.
This lets you combine any two file filters as a Boolean. As there isn't a delivered file filter for the age criteria, you'll still need to create one, following the lines of the other comment.
You could roll your own IOFileFilter , which would do both checks :
public class MyFileFilter implements IOFileFilter {
String extension;
Date maxDate;
public MyFileFilter(String extension, Date maxDate){
this.extension = extension;
this.maxDate = maxDate;
}
#Override
public boolean accept(File dir, String name) {
return false;
}
#Override
public boolean accept(File file) {
boolean suffixMatches = file.getName().endsWith(extension);
boolean timeMatches = FileUtils.isFileOlder(file, maxDate);
return suffixMatches && timeMatches ;
}
}
Then you would call it this way :
String extension = ".txt";
// compute current date minus 1 minute
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
cal.add(Calendar.MINUTE, -1);
Date maxDate = cal.getTime();
Collection<File> myFiles = FileUtils.listFiles(FileUtils.getFile(inputPath),new MyFileFilter(extension,maxDate) ,
null);
Related
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.
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.
I have specific text file looking like this:
name: meeting_name1
description:
04/18/2012 00:00:00
05/18/2012 00:00:00
... (more dates)
07/18/2012 00:00:00
name: meeting_name2
description: some_desc
04/18/2012 00:00:00
05/18/2012 00:00:00
... (more dates)
07/18/2012 00:00:00
(etc)
I have java object looking like this:
class Meeting {
String name;
String description;
List<Date> dates;
}
My point is to read the file, parse values, create objects and save them to database.
I can read the file line by line and convert it to List<String>, ie. all data together.
`I can make and fill one java object with values and save it to database.
My issue here is how to find out that I'm at the end of dates and lines (name: meeting_name2) of new object begin.
So I could make something like List<List<String>> where List<String> would be equal to one object, ie. List<Meeting>?
Not sure if its understandable, sorry for formatting.
Assumption that you could read the file data to List variable. (See above answer)
List<String> lines = Files.readAllLines(Paths.get("FILE_NAME"));
Now, you can see below code as a demo. It is the simple loop and if else statament.
Hope it will help you.
public static void main(String[] args) throws ParseException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
List<String> data = new ArrayList<>();
data.add("name: meeting_name1");
data.add("description: some_desc");
data.add("07/18/2012 00:00:00");
data.add("07/18/2012 00:00:00");
data.add("name: meeting_name2");
data.add("description: some_desc");
data.add("07/18/2012 00:00:00");
List<Meeting> result = new ArrayList<>();
Meeting temp = null;
for (String line : data) {
if (line.startsWith("name:")) {
temp = new Meeting(line.split(":")[1].trim());
result.add(temp);
} else if (line.startsWith("description:")) {
temp.setDescription(line.split(":")[1].trim());
} else {
temp.getDates().add(simpleDateFormat.parse(line)); // Use date for
}
}
System.out.println(result.get(0).getName() + ": " + result.get(0).getDates().size()); // meeting_name1: 2
System.out.println(result.get(1).getName() + ": " + result.get(1).getDates().size()); // meeting_name2: 1
}
static class Meeting {
String name;
String description;
List<Date> dates;
public String getName() {
return name;
}
public List<Date> getDates() {
return dates;
}
Meeting(String name) {
this.name = name;
this.dates = new ArrayList<>();
}
public void setDescription(String description) {
this.description = description;
}
}
One possibility would be to read all lines first. You would not need to worry about the end of lines with:
List<String> lines = Files.readAllLines(Paths.get("FILE_NAME"));
then iterarate through the array,
if a line starts with "name:" you make a new object and add the data like that:
List<Meeting> meetings = new ArrayList();
Meeting currentMeeting;
for (String line : lines) {
if(line.startsWith("name:"))
{
currentMeeting = new Meeting();
meetings.add(currentMeeting);
//...add data (name)
}
//...add more data (description and dates)
}
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)
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.