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.
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.
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 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);
I have a fairly simple stored java procedure in an oracle database. The intended purpose is to read the contents of a folder which resides on the Oracle server. If it encounters a folder it will step into the folder and write the name of the contents into a global temp table, and move on to the next folder. The Java procedure compiles fine and submits into the database with no issues. When it's called by a stored Oracle procedure it runs successfully as well. But produces no results into the global temp table. I am using TOAD and i'm not sure how to put a break or view the variables during run time so i'm kind of flying blind. And i'm admittedly not great a java.
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED BALT_CHECK."WebDirList" AS
import java.io.*;
import java.sql.*;
import java.util.Date;
import java.text.SimpleDateFormat;
public class WebDirList
{
public static void getList(String rootdirectory) throws SQLException
{
File path = new File( rootdirectory );
String[] rootDirList = path.list();
String element;
for( int x = 0; x < rootDirList.length; x++)
{
element = rootDirList[x];
String newPath = rootdirectory + "/" + rootDirList[x] ;
File f = new File(newPath);
if (f.isFile()){
/* Do Nothing */
} else {
/*if it is a folder than load the subDirPath variable with the newPath variable */
File subDirPath = new File( newPath+"/");
String[] subDirList = subDirPath.list();
String efileName;
for(int i = 0; i < subDirList.length; i++)
{
efileName = subDirList[i];
String fpath = subDirPath + "/" + subDirList[i];
File nf = new File(fpath);
long len;
Date date;
String ftype;
String sqlDate;
SimpleDateFormat df = new SimpleDateFormat( "yyyy-MM-dd hh:mm:ss");
if (f.isFile()) {
len = f.length();
date = new Date(f.lastModified());
sqlDate = df.format(date);
#sql { INSERT INTO WEB_DIRLIST (FILENAME, LENGTH, CREATEDATE)
VALUES (:efileName, :len, to_date(:sqlDate, 'YYYY-MM-DD HH24:MI:SS')) };
}else{
/* Do nothing */
}
}
}
}
}
}
/
Procedure is created as
CREATE OR REPLACE procedure BALT_CHECK.get_webdir_list( p_directory in varchar2)
as language java
name 'WebDirList.getList( java.lang.String )';
/
Procedure is called as
exec get_webdir_list( '/transfer_edi/hs122/');
in the folder /transfer/edi/hs122/ are 10 sub directories each have between 1 and 100 items in them at any given time.
I'm not sure how you check the results (same session or not). Do you perform commit somewhere? There are some specifics with global temp tables (there is option whether data is purged after commit or not). You may wish to initially try with permanent one until you sort out the problem.
It may be useful if you add some logging (e.g. to another table). E.g. rootDirList.length may be a good indicator to check.
Some other remarks:
The /* Do nothing */ branches in your if statements are adding additional noise. Good to remove them.
Perhaps would be better to use .isDirectory() if you want to check if the paths is a directory (instead of isFile).
There were a few errors in this code that prevented it from writing to the database. Based on Yavor's suggestion of writing String variables to a temp table I was able to find that I had duplicated "/" on the file path e.g. (/transfer_edi/hs122//Acctg). I also found I had an incorrect data type on one of my columns in my data table that I was writing too. I also switched to a regular table instead of a global temp table which was deleting after commit. Again thanks Yavor. Regardless of all that I ended up re-writing the entire thing. I realized that I needed to traverse down the directory structure to get all the files so here is the final code that worked for me. Again i'm not a java guy so i'm sure this could be done better.
This link helped me quite a bit
http://rosettacode.org/wiki/Walk_a_directory/Recursively#Java
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED BALT_CHECK."WebDocs" AS
import java.io.*;
import java.sql.*;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.lang.String;
public class WebDocs
{
public static long fileID;
public static void GetDocs(String rootdirectory) throws SQLException
{
stepinto(rootdirectory);
}
public static void stepinto(String rootdirectory) throws SQLException
{
File path = new File( rootdirectory );
String[] DirList = path.list();
for( int x = 0; x < DirList.length; x++)
{
String newPath = rootdirectory + DirList[x];
if (newPath != null) {
File f = new File(newPath);
if (f.isDirectory()) {
GetDocs(newPath +"/");
}
if (f.isFile()){
WriteFile(f);
}else{
}
}
}
}
public static void WriteFile(File file) throws SQLException
{
String fileName;
String filePath;
String elementID;
long len;
Date date;
String sqlDate;
SimpleDateFormat df = new SimpleDateFormat( "yyyy-MM-dd hh:mm:ss");
fileID = fileID + 1;
elementID = String.valueOf(fileID);
fileName = file.getName();
filePath = file.getPath();
len = file.length();
date = new Date(file.lastModified());
sqlDate = df.format(date);
#sql { INSERT INTO WEB_STATICDOCS (ID, FILE_NAME, FILE_SIZE, CREATE_DATE, FILE_PATH)
VALUES (:elementID, :fileName, :len, to_date(:sqlDate, 'YYYY-MM-DD HH24:MI:SS'), :filePath) };
}
}
/
Oracle Stored Procedure
CREATE OR REPLACE procedure BALT_CHECK.getWebDocs( p_directory in varchar2)
as language java
name 'WebDocs.GetDocs( java.lang.String )';
/
Calling the stored Procedure
exec getWebDocs( '/transfer_edi/hs122/');
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.