Parse filename by split() to compare two common fields - java

I need to extract String parts from each file in a folder(files) having the following extensions as png,jpg,jpeg,PNG,JPG,JPEG. The file naming convention is as below(These are 2 different files but the only thing they have in common is the TIMESTAMP which will be required to get the FILENAME:
AIRLINECODE_PARTNERCODE_INVOICENO_timestamp.FILETYPE
FILENAME.FILETYPE_timestamp
Example file names:
ET_PRH_4_20170309140404.png
gosalyn.png_20170309140404
After reading the field from the first, I need to write each of the capital fields to the database (for eg AIRLINECODE, PARTNERCODE to columns in db). I am looping to iterate through "eachFile" in "files". The capital words are depicting the fields which will be added to the columns in the database. So AIRLINE_CODE has a column in the db and ET will be placed in it and so on for the others.
The following is the code I have written so far, so could you kindly guide how I can compare the second file's timestamp with the first and storing it in a field called "timestamp". Your help will be much appreciated. Thank you
import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
public class Pathnames {
public void readFilename() {
// try-catch block to handle exceptions
try {
File f = new File("C:\\Users\\rsaeed\\Desktop\\files");
FilenameFilter filter = new FilenameFilter() {
#Override
public boolean accept(File f, String name) {
return name.endsWith(".png") || name.endsWith(".PNG") || name.endsWith(".jpg") || name.endsWith(".JPG") || name.endsWith(".jpeg") || name.endsWith(".JPEG");
}
};
// using a File class as an array
File[] files = f.listFiles(filter);
if(files != null) {
for(File eachFile : files) {
String[] partsOfName = eachFile.getName().split("_|\\."); // this part is correct and giving result in array as [ET, PRH, 4, 20170309140404, png]
//System.out.println(Arrays.toString(partsOfName));
// the following is wrong so what should be the code here that each file with .png_ is split and timestamp stored in secondFile array after which I can compare the two timestamps
if(eachFile.getName().contains(".png_")) {
String[] secondFile = eachFile.getName().split("\\_");
System.out.println(Arrays.toString(secondFile));
}
final String timestamp = partsOfName[3];
//System.out.println(timestamp);
}
}
// Get the names of the files by using the .getName() method
for (int i = 0; i < files.length; i++) {
System.out.println(files[i].getName());
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
public static void main(String args[]) {
Pathnames p = new Pathnames();
p.readFilename();
}
}

I will first share with you a little hint
#Override
public boolean accept(File f, String name) {
// Here you can leave the toLowerCase() to easy your life for sake of comparison since PNG and png is the same for you (this doesn't change the original name)
name = name.toLowerCase();
return name.endsWith(".png") || name.endsWith(".jpg") || name.endsWith(".jpeg");
}
To finally split your secondFile (i'm guessing for what you write this was your difficulty)
I made a simply regex to split as you requested:
So gosalyn.png_20170309140404 will be stored as [gosalyn, png, 20170309140404]
This regex will solve your problem "\.|\_"
'\.' is for any '.'
'|' is just like || (or)
'\_' is for any '_'

Related

How do I parse a text file to write certain lines in another text file using java?

I am learning how to work with files in Java. I have a sample file which contains key pairs and it values. I am trying to find a key pairs and if it matches, then output file would be updated with both, key pair and it's value. I am able to get key pairs in output file but unable to get values too. Stringbuilder may work here to append strings but I don't know how.
Below are my input and output files.
Input File:
born time 9 AM London -- kingNumber 1234567890 -- address: abc/cd/ef -- birthmonth: unknown
born time 9 AM Europe -- kingNumber 1234567890 -- address: abc/cd/ef -- birthmonth: december
Expected Output File:
kingNumber 1234567890 birthmonth unknown
kingNumber 1234567890 birthmonth unkbown
Current Output File:
kingNumber birthmonth
kingNumber birthmonth
I am able to write key pair ("kingNumber" and "birthmonth" in this case) to output file but I am not sure what I can do to get it's value too.
String kn = "kingNumber:";
String bd = "birthmonth:";
try {
File f = new File("sample.txt");
Scanner sc = new Scanner(f);
FileWriter fw = new FileWriter("output.txt");
while(sc.hasNextLine()) {
String lineContains = sc.next();
if(lineContains.contains(kn)) {
fw.write(kn + "\n");
// This is where I am stuck. What
// can I do to get it's value (number in this case).
}
else if(lineContains.contains(bd)) {
fw.write(bd);
// This is where I am stuck. What
// can I do to get it's value (birthday in this case).
}
}
} catch (IOException e) {
e.printStackTrace();
}
you could use java.util.regex.Pattern & java.util.regex.Matcherwith a pattern alike:
^born\stime\s([a-zA-Z0-9\s]*)\s--\skingNumber\s(\d+)\s--\saddress:\s([a-zA-Z0-9\s/]*)\s--\sbirthmonth:\s([a-zA-Z0-9\s]*)$
write less, do more.
I have written a simple parser that it following data format from your example.
You will need to call it like this:
PairParser parser = new PairParser(lineContains);
then you can get value from the parser by pair keys
How to get value:
parser.getValue("kingNumber")
Note that keys do not have trailing column character.
The parser code is here:
package com.grenader.example;
import java.util.HashMap;
import java.util.Map;
public class PairParser {
private Map<String, String> data = new HashMap<>();
/**
* Constructor, prepare the data
* #param dataString line from the given data file
*/
public PairParser(String dataString) {
if (dataString == null || dataString.isEmpty())
throw new IllegalArgumentException("Data line cannot be empty");
// Spit the input line into array of string blocks based on '--' as a separator
String[] blocks = dataString.split("--");
for (String block : blocks)
{
if (block.startsWith("born time")) // skip this one because it doesn't looks like a key/value pair
continue;
String[] strings = block.split("\\s");
if (strings.length != 3) // has not exactly 3 items (first items is empty), skipping this one as well
continue;
String key = strings[1];
String value = strings[2];
if (key.endsWith(":"))
key = key.substring(0, key.length()-1).trim();
data.put(key.trim(), value.trim());
}
}
/**
* Return value based on key
* #param key
* #return
*/
public String getValue(String key)
{
return data.get(key);
}
/**
* Return number of key/value pairs
* #return
*/
public int size()
{
return data.size();
}
}
And here is the Unit Test to make sure that the code works
package com.grenader.example;
import com.grenader.example.PairParser;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
public class PairParserTest {
#Test
public void getValue_Ok() {
PairParser parser = new PairParser("born time 9 AM London -- kingNumber 1234567890 -- address: abc/cd/ef -- birthmonth: unknown");
assertEquals("1234567890", parser.getValue("kingNumber"));
assertEquals("unknown", parser.getValue("birthmonth"));
}
#Test(expected = IllegalArgumentException.class)
public void getValue_Null() {
new PairParser(null);
fail("This test should fail with Exception");
}
#Test(expected = IllegalArgumentException.class)
public void getValue_EmptyLine() {
new PairParser("");
fail("This test should fail with Exception");
}
#Test()
public void getValue_BadData() {
PairParser parser = new PairParser("bad data bad data");
assertEquals(0, parser.size());
}
}

Reading a text file with boolean values into an array list as objects

I am trying to read a file of string int and boolean values into an array list as object blocks. The string values go into the array list just fine, its the boolean values I'm having trouble with. Every time I encounter the variable 'active'there is a mismatch exception. Please help! The text file for if the block is a wizard goes in this order
name (string)
location (string)
active (boolean) ... the one I'm having issues with
skill level (int)
friendliness (int)
I included the driver class as well as the Witch class which contains the
variable 'active' originally.
Driver class that adds objects to the array list based on what the scanner
reads from the file
package project2;
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
public class Project2 {
public static void main(String[] args) {
Scanner inputFileScanner1 = null;
//file name
String listFile = "list.txt";
// Check to see if file exists
try {
inputFileScanner1 = new Scanner(new File(listFile));
} catch (FileNotFoundException e) {
System.out.println("Error opening file.");
System.exit(1);
}
//create Individuals arraylist and Location arraylist
ArrayList < Individual > Individual = new ArrayList < > ();
ArrayList < String > Location = new ArrayList < > ();
//declare variables to read file contents into the arraylist
String wizName, witchName, individualName, location, position,
profession = null, line = null;
int wizLevel, witchSkillLevel, friendliness;
boolean active;
//while there is a next line, if the line equals Wizard, the next four lines
// are wizard name, location, position and level
while (inputFileScanner1.hasNext()) {
line = inputFileScanner1.nextLine();
if (line.trim().equals("Wizard")) {
wizName = inputFileScanner1.nextLine().trim();
location = inputFileScanner1.nextLine().trim();
position = inputFileScanner1.nextLine().trim();
wizLevel = inputFileScanner1.nextInt();
//create wizard object
Individual wizard = new Wizard(wizName, location, position, profession, wizLevel);
//fill arraylist with wizard objects
Individual.add(wizard);
Location.add(location);
} //if the next line is Witch, the next five lines are
// witch name, location, yes/no active, skill level, and friendliness
//in that order
else if (line.trim().equals("Witch")) {
witchName = inputFileScanner1.nextLine().trim();
location = inputFileScanner1.nextLine().trim();
active = inputFileScanner1.nextBoolean();
witchSkillLevel = inputFileScanner1.nextInt();
friendliness = inputFileScanner1.nextInt();
//create witch object
Individual witch = new Witch(witchName, location, profession, witchSkillLevel, friendliness, active);
//fill the arraylist with witch objects
Individual.add(witch);
Location.add(location);
} else {
profession = line.trim();
individualName = inputFileScanner1.nextLine().trim();
location = inputFileScanner1.nextLine().trim();
Individual i = new Individual(profession, individualName, location);
Individual.add(i);
Location.add(location);
}
java.util.Collections.sort(Individual);
java.util.Collections.sort(Location);
}
System.out.println("List of friends and possible allies: " + Location);
inputFileScanner1.close();
}
}
//Witch class which holds values that are in the text file. active is the boolean value Im having trouble with
package project2;
public class Witch extends Individual implements Magical {
private int skill;
private int friendly;
//Constructor with witch parameters
public Witch(String name, String location, String profession,
int skill, int friendly, boolean active) {
}
//default constructor
public Witch() {
this("", "", "", 0, 0, false);
}
//overridden abstract method from magical interface
#Override
public void assess() {
System.out.print(this.friendly + " " + this.skill + " " + super.toString());
}
}
<!-- end snippet -->
Text file :
enter image description here
When you pull in your boolean variable do something like this.
if(inputFileScanner1.nextLine().trim().equals("yes"))
{
active = true;
}
else
{
active = false;
}
Okay, the problem is that the file contains the strings yes and no, that are not directly parsable as booleans (should be true or false).
If you can change the original data file somehow, I would suggest to use the two true and false keywords, otherwise, the #Sendrick Jefferson solution will do the job (at your own risk: every typo, as for instance "ye", will be translated into false).

Split string not working properly

I have trouble splitting a name by a space, and I can't seem to figure out why. Could someone please provide me with a solution?
My code is like this:
public void getPlayerNames(int id){
try {
Document root = Jsoup.connect("http://www.altomfotball.no/element.do?cmd=team&teamId=" + id).get();
Element table = root.getElementById("sd_players_table");
Elements names = table.getElementsByTag("a");
for(Element name : names){
getPlayers().add(new Player(name.text()));
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
which returns the name of football players as a string. The names are retrieved such as Mario Balotelli, Steven Gerrard, and so on, and I assumed I could use string.split(" "); to get me the first and last names, but whenever I try to access the second space of the string array it gives me an index out of bounds exception. Here is the code trying to fetch me the first name
/**
* Method to get the first name of a player
*/
public static String getFirstName(String name){
String[] nameArray = name.split(" ");
return nameArray[0];
}
Thanks for answers!
Sindre M
EDIT ######
So I got it to work, but thanks for the effort. The problem was that even though I could not see it in a simple sysout statement, the names actually contained a "&nbsp"; character, so I solved it by running a replaceAll("&nbsp ;" , " ") on the names for a better formatting.
If you're trying to write a screen-scraper you need to be more defensive in your code... Definitely test the length of the array first and log any unexpected inputs so you can incorporate them later...
public static String getFirstName(String name) {
String[] nameArray = name.split(" ");
if (nameArray.length >= 1) { // <== check length before you access nameArray[0]
return nameArray[0];
} else {
// log error
}
return null;
}
Additionally java.util.Optional in Java 8 provides a great alternative to returning null...
public static Optional<String> getFirstName(String name) {
String[] nameArray = name.split(" ");
if (nameArray.length >= 1) {
return Optional.of(nameArray[0]);
} else {
// log error
}
return Optional.empty();
}
You might be getting in the actual string as you are retrieving from html page. try to debug and check.
package com.appkart.examples;
public class SplitProgram {
public void firstNameArray(String nameString) {
String strArr[] = nameString.split(",");
for (String name : strArr) {
String playerName = name.trim();
String firstName = playerName.substring(0, playerName.indexOf(" "));
System.out.println(firstName);
}
}
public static void main(String[] args) {
String nameString = "Mario Balotelli, Steven Gerrard";
SplitProgram program = new SplitProgram();
program.firstNameArray(nameString);
}
}
I think that the correct answer should be:
String[] nameArray = name.split("\\s+");
But to be honest, there are couple of answers at stackoverflow.
Eg.
How to split a String by space
How do I split a string with any whitespace chars as delimiters?
First try to replace white space as
string.replace(" ","");
then try to split with [,] as
String strAr[] = string.split(",");

how to read two consecutive commas from .csv file format as unique value in java

Suppose csv file contains
1,112,,ASIF
Following code eliminates the null value in between two consecutive commas.
Code provided is more than it is required
String p1=null, p2=null;
while ((lineData = Buffreadr.readLine()) != null)
{
row = new Vector(); int i=0;
StringTokenizer st = new StringTokenizer(lineData, ",");
while(st.hasMoreTokens())
{
row.addElement(st.nextElement());
if (row.get(i).toString().startsWith("\"")==true)
{
while(row.get(i).toString().endsWith("\"")==false)
{
p1= row.get(i).toString();
p2= st.nextElement().toString();
row.set(i,p1+", "+p2);
}
String CellValue= row.get(i).toString();
CellValue= CellValue.substring(1, CellValue.length() - 1);
row.set(i,CellValue);
//System.out.println(" Final Cell Value : "+row.get(i).toString());
}
eror=row.get(i).toString();
try
{
eror=eror.replace('\'',' ');
eror=eror.replace('[' , ' ');
eror=eror.replace(']' , ' ');
//System.out.println("Error "+ eror);
row.remove(i);
row.insertElementAt(eror, i);
}
catch (Exception e)
{
System.out.println("Error exception "+ eror);
}
//}
i++;
}
how to read two consecutive commas from .csv file format as unique value in java.
Here is an example of doing this by splitting to String array. Changed lines are marked as comments.
// Start of your code.
row = new Vector(); int i=0;
String[] st = lineData.split(","); // Changed
for (String s : st) { // Changed
row.addElement(s); // Changed
if (row.get(i).toString().startsWith("\"") == true) {
while (row.get(i).toString().endsWith("\"") == false) {
p1 = row.get(i).toString();
p2 = s.toString(); // Changed
row.set(i, p1 + ", " + p2);
}
...// Rest of Code here
}
The StringTokenizer skpis empty tokens. This is their behavious. From the JLS
StringTokenizer is a legacy class that is retained for compatibility reasons although its use is discouraged in new code. It is recommended that anyone seeking this functionality use the split method of String or the java.util.regex package instead.
Just use String.split(",") and you are done.
Just read the whole line into a string then do string.split(",").
The resulting array should have exactly what you are looking for...
If you need to check for "escaped" commas then you will need some regex for the query instead of a simple ",".
while ((lineData = Buffreadr.readLine()) != null) {
String[] row = line.split(",");
// Now process the array however you like, each cell in the csv is one entry in the array

ArrayIndexOutOfBoundsException in Java when using split

I am trying to read file and split its line to get some context(Computer Name and Date), the code gives few lines of outputs then gives the following exception:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at FILE_MAIN.getComputerName(FILE_MAIN.java:34)
at FILE_MAIN.readFiles(FILE_MAIN.java:24)
at FILE_MAIN.main(FILE_MAIN.java:12)
Code:
import java.util.*;
import java.io.*;
import java.util.Scanner;
public class FILE_MAIN
{
public static void main(String[] args) throws FileNotFoundException
{
File folder = new File("folderName/");
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++)
{
readFiles(listOfFiles[i].getName());
}
}
public static void readFiles(String fileName) throws FileNotFoundException
{
FileReader dataFile = new FileReader("yukt/"+fileName);
try (Scanner FileRead = new Scanner(dataFile))
{
while (FileRead.hasNextLine() && FileRead.nextLine().isEmpty()==false)
{
String[] split;
String line = FileRead.nextLine();
split = line.split("\\|",-1);
String computerName=getComputerName(split[0]);
System.out.println(computerName);
}
}
}
public static String getComputerName(String splited)
{
String[] split1;
String[] split2;
split1=splited.split("\\:",-1);
split2=split1[1].split("\\ ",-1);
return("a");
}
public static String getDate(String splited)
{
String[] split1=splited.split("\\(",-1);
String[] split2=split1[1].split("\\ ",-1);
return(split2[0]);
}
}
The main function gets names of the files in a folder, and passes each file to the readFiles function where each line is split into 3 parts by a delimeter(|) and parts are send to getComputerName and getDate function which returns its values after further splitting the strings.
Here is an example of a line of the file, all the lines are similar to this:
[CD8C] ComputerName:NITIN UserID:GO ankurjain Station 9900 LanId: | (11/24 19:50:30) | Client is disconnected from agent.
There is no protection for split1 containing a single element:
split1=splited.split("\\:",-1);
split2=split1[1].split("\\ ",-1); // Accesses second element of split1
Add protection and decide if it is an error for there to be no : in the input string or just use whole string if no ::
split1=splited.split("\\:",-1);
if (split1.length > 1)
{
split2=split1[1].split("\\ ",-1);
}
split1=splited.split("\\:",-1);
split2=split1[1].split("\\ ",-1);
split1 must not be doing what you think.
i.e. it is not splitting, cos split1[1] is not valid.
You should really check the result of the first split before trying to use it's results.
I had similar issue where I had to check weather string sub part contains given string or not. But String in question had many variation. Instead of using if loop I used ternary operator -
StringUtils.containsIgnoreCase("Test String",
("split me".split(":").length > 1)
? "split me".split(":")[1] : "Can't split")
split2=split1[1] gives you java.lang.ArrayIndexOutOfBoundsException: 1 the error. The Array does not have 2 elements so index on 1 will throw an error.
You could add a check to make sure it has atleast 2 elements by putting the assignement in a if statement
if (split1.lenght > 1){
split2=split1[1].split("\\ ",-1);
}

Categories