I have an expression working inside a Report (jasperReport), the language to work with expressions i groovy. the expression is
= Util.textoComun("OCURRENCIA")+ " "+Util.aFecha($F{fecha}).
Everything in the same box, but i just want to apply a date pattern at the second part of expression (Util.aFecha(xx)), is this possible?
I don't wanna to separate in two boxes.
Util is a java class.
afecha does:
public static Date aFecha(String s)
{
try
{
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
formatter.setLenient(false);
return formatter.parse(s);
} catch (Exception ex) {
System.out.println("Error convertint la data: " + ex);
}
return null;
}
Right, so from the edit, it appears that $F{fecha} is returning you a String which you parse into a Date with Util.aFecha. In that case (and assuming this is Groovy), you should be able to do:
Util.textoComun("OCURRENCIA")+ " "+Util.aFecha($F{fecha}).format( 'EEE, d MMM yyyy' )
Related
I don't normally do Java in my daily work, although I wish I did since there is a class for everything (sometimes too many). Yesterday I spent the bulk of my day writing the program below. Tiny rant: java.util.scanner is less than intuitive, IMO. What I want to do with it is to scan a log file for two certain patterns and do some date arithmetic on it and print the results. This program works if I take my log file and delete non-matching lines then run it. I can do this with vi, sed, whatever, but I'm more interested in taking this utility and making it more usable for someone who isn't as comfortable with shell scripting or using vi. I'll be hammering on this a little more today but I wonder if there is some expertise here that can make me move forward more quickly.
import java.util.*;
import java.util.concurrent.*;
import java.text.SimpleDateFormat;
import java.util.regex.Pattern;
import java.util.regex.MatchResult;
import java.io.*;
import java.time.*;
import java.time.format.*;
public class TimeDiff {
private static SimpleDateFormat m_formatter = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss");
private static Pattern m_startRunPattern = Pattern.compile("start of run=([^,]+)");
private static Pattern m_currentTimePattern = Pattern.compile("current time=(.+)");
private String m_fileArg;
private File m_file;
private Scanner m_scanner;
public TimeDiff(String[] args)
{
if (args.length == 0) {
System.err.println("nope.");
System.exit(1);
}
m_fileArg = args[0];
m_file = new File(m_fileArg);
}
public String findPattern(Scanner fileScan, Pattern pattern)
{
String ret_val = null;
try {
ret_val = fileScan.findInLine(pattern);
MatchResult result = fileScan.match();
if (result.groupCount() > 0) {
ret_val = result.group(1);
}
}
catch (java.util.InputMismatchException e) {
System.out.println("failed at second");
}
catch (java.lang.IllegalStateException e) {
System.out.println("failed at second match " + e);
}
return ret_val;
}
public void run(String[] args) throws Exception
{
try (Scanner fileScan = new Scanner(m_file)) {
while (fileScan.hasNext()) {
String beginTimeStr = findPattern(fileScan, m_startRunPattern);
String endTimeStr = findPattern(fileScan, m_currentTimePattern);
if (beginTimeStr == null && endTimeStr == null) {
if (fileScan.hasNext()) {
fileScan.next();
}
}
else {
Date startDate = m_formatter.parse(beginTimeStr);
Date endDate = m_formatter.parse(endTimeStr);
long duration = endDate.getTime() - startDate.getTime();
long diffInSeconds = TimeUnit.MILLISECONDS.toSeconds(duration);
long diffInMinutes = TimeUnit.MILLISECONDS.toMinutes(duration);
long remainderSeconds = 0;
if (diffInMinutes > 0) {
remainderSeconds = diffInSeconds % diffInMinutes;
}
else {
remainderSeconds = diffInSeconds;
}
System.out.println("elapsed seconds: " + diffInSeconds + ", (" + diffInMinutes + " minutes, " + remainderSeconds + " seconds).");
if (fileScan.hasNext()) {
fileScan.next();
}
}
}
}
catch (IOException exception) {
System.out.println(exception);
}
}
public static void main(java.lang.String args[])
{
try {
TimeDiff app = new TimeDiff(args);
app.run(args);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
The massaged log file entries look like:
DealWithResponse.cpp, DealWithResponse(XMLSocketApp &, DOMDocument *), 247 2020-07-29 17:54:13 start of run=2020-07-29-17.53.31.216800, current time=2020-07-29-17.54.13.530384
DealWithResponse.cpp, DealWithResponse(XMLSocketApp &, DOMDocument *), 247 2020-07-29 17:54:13 start of run=2020-07-29-17.53.29.903984, current time=2020-07-29-17.54.13.805200
DealWithResponse.cpp, DealWithResponse(XMLSocketApp &, DOMDocument *), 247 2020-07-29 17:54:13 start of run=2020-07-29-17.53.14.356440, current time=2020-07-29-17.54.13.907528
DealWithResponse.cpp, DealWithResponse(XMLSocketApp &, DOMDocument *), 247 2020-07-29 23:16:01 start of run=2020-07-29-23.15.27.722784, current time=2020-07-29-23.16.01.016640
DealWithResponse.cpp, DealWithResponse(XMLSocketApp &, DOMDocument *), 247 2020-07-29 23:16:04 start of run=2020-07-29-23.15.39.955272, current time=2020-07-29-23.16.04.418160
DealWithResponse.cpp, DealWithResponse(XMLSocketApp &, DOMDocument *), 247 2020-07-29 23:16:05 start of run=2020-07-29-23.15.52.154920, current time=2020-07-29-23.16.05.480384
Of course, what the rest of the log file looks like contains business logic stuff (SQL, etc).
From the docs of Scanner's findInLine:
Attempts to find the next occurrence of the specified pattern ignoring delimiters. If the pattern is found before the next line separator, the scanner advances past the input that matched and returns the string that matched the pattern. If no such pattern is detected in the input up to the next line separator, then null is returned and the scanner's position is unchanged. This method may block waiting for input that matches the pattern.
What you're observing is findInLine not finding anything matching the pattern specified before hitting a newline, and thus returning null and not changing the position whatsoever.
Perhaps findWithinHorizon(pattern, 0) is more to your liking? This will keep looking, forever (until end of input) if need be, until it finds a match on your regexp.
It then returns the match. If you need the entire line, just expand on your regexp: "^.*current time = (.*)$" would always match an entire line.
A second tip: your exception handling is atrocious. if you catch an exception, handle it. 'print some text and carry right on as if nothing is wrong' is not handling it. Trivial solution: add throws Exception onto your main method (which is almost always a good idea in any case). Then just.. get rid of every try{ and catch{} block in your code. Makes it way shorter and easier to read, and better to boot!
I'm solving this problem:
problem
And what I did is this:
import java.io.*;
import static java.lang.System.exit;
import java.util.*;
//Driver for Abbreviations
public class AbbreviationsDriver {
//string of message
private static String message = "";
//List of Abbreviations
private static String[] AbbreviationsList;
//Abbreviations list file
private static File AbbreviationsListFile = new File("abbreviations.txt");
//message file
private static File inputMessageFile = new File("sample_msg.txt");
//output message file
private static File outputMessageFile = new File("sample_output.txt");
//main method
public static void main(String[] args) throws FileNotFoundException {
setAbbreviations(readFileList(AbbreviationsListFile));
System.out.println("list of abbriviations:\n" + Arrays.toString(AbbreviationsList));
setMessage(readFile(inputMessageFile));
System.out.println("\nMessage in input file:\n" + message);
writeFile(outputMessageFile,addTags(message, AbbreviationsList));
System.out.println("\nMessage with tag in output file:\n" + addTags(message, AbbreviationsList));
}
//method to add tags
public static String addTags(String toTag, String[] abbreviations){
for(String abbreviation:abbreviations)
if(toTag.contains(abbreviation)){
toTag = toTag.replaceAll(abbreviation, "<" + abbreviation + ">");
}
return toTag;
}
//method to read the file list
public static String[] readFileList(File fileInput){
String input = "";
try{
Scanner inputStream = new Scanner(fileInput);
while(inputStream.hasNextLine()){
input = input + inputStream.nextLine()+ "<String>";
}
inputStream.close();
// System.out.println("list in string: " + input);
return input.split("<String>");
}
catch(Exception exception){
System.out.println("error in getting string array from file:\t" + exception.getMessage());
exit(0);
return new String[] {""};
}
}
//method to read the file
public static String readFile(File fileInput){
String inputFile = "";
try{
Scanner inputStatement = new Scanner(fileInput);
while(inputStatement.hasNextLine()){
inputFile = inputFile + inputStatement.nextLine();
}
inputStatement.close();
return inputFile;
}
catch(Exception exception){
System.out.println("error in getting message from file:\t" + exception.getMessage());
exit(0);
return "";
}
}
//method to write the output file
public static void writeFile(File fileName, String outString){
try{
PrintWriter outputStatement = new PrintWriter(fileName);
outputStatement.print(outString);
outputStatement.close();
}
catch(Exception exception){
System.out.println("error in setting message of file:\t" + exception.getMessage());
exit(0);
}
}
//method to set abbreviations
public static void setAbbreviations(String[] newAbbreviationsList){
AbbreviationsList = newAbbreviationsList;
}
//setter to set message
public static void setMessage(String newMessage){
message = newMessage;
}
//input string
public static String inputString(){
return new Scanner(System.in).nextLine();
}
}
abbreviations.txt is here:
lol
:)
iirc
4
u
ttfn
and sample_msg.txt is here:
How are u today? Iirc, this is your first free day. Hope you are having fun! :)
but when I compile and run, the error message comes out:
list of abbriviations:
[lol, :), iirc, 4, u, ttfn]
Message in input file:
How are u today? Iirc, this is your first free day. Hope you are having fun! :)
Exception in thread "main" java.util.regex.PatternSyntaxException: Unmatched closing ')' near index 0
:)
^
at java.util.regex.Pattern.error(Pattern.java:1969)
at java.util.regex.Pattern.compile(Pattern.java:1706)
at java.util.regex.Pattern.<init>(Pattern.java:1352)
at java.util.regex.Pattern.compile(Pattern.java:1028)
at java.lang.String.replaceAll(String.java:2223)
at AbbreviationsDriver.addTags(AbbreviationsDriver.java:44)
at AbbreviationsDriver.main(AbbreviationsDriver.java:36)
Process finished with exit code 1
I don't know how to solve this error because I've never seen this error before.
Please help me!
You pass wrong parameter into replaceAll(). First parameter must be a regex. For your purpose, regex is not needed, so use replace() method instead.
You faced the error because ) is treated as a metacharacter in regex and therefore either it needs to be escaped or must be paired with its closing counterpart.
Solution
You need to treat abbreviations with metacharacters and strings without metacharacters differently. For strings with metacharacters (e.g. :) where ) is a metacharacter), you should use String#replace while for the strings without metacharacter you should use String#replaceAll.
When you use String#replaceAll, you should create a capturing group which includes word boundaries e.g. (\bu\b) so that only those u will be processed which appear as a word. Finally, you should replace the capturing group with <$1> where $1 refers to the first (in the code given below, there is only one capturing group) capturing group e.g. (\bu\b) will be replaced by <u>.
Demo:
public class Main {
public static void main(String[] args) {
String[] abbrWithoutMetaChars = { "lol", "iirc", "4", "u", "ttfn" };
String[] abbrWithMetaChars = { ":)" };
// Test string
String str = "How are u today? iirc, this is your first free day. Hope you are having fun! :)";
// Replace all abbr. without meta chars
for (String abbreviation : abbrWithoutMetaChars) {
str = str.replaceAll("(\\b" + abbreviation + "\\b)", "<$1>");
}
// Replace all abbr. with meta chars
for (String abbreviation : abbrWithMetaChars) {
str = str.replace(abbreviation, "<" + abbreviation + ">");
}
System.out.println(str);
}
}
Output:
How are <u> today? <iirc>, this is your first free day. Hope you are having fun! <:)>
The problem is actually tricky. For example, in the list of abbreviations, u should be interpreted as a word and not a letter, since in your expected output you don't surround the letter u in the word your with angle brackets but only the u that appears by itself. Hence your code needs to locate the abbreviation as a single word in the input.
Also, iirc appears in the abbreviations list but in the input you have Iirc (with a capital I) and in the expected output it should appear as <Iirc> and not as <iirc>. In other words you should ignore case when locating the abbreviation but you need to keep the case after surrounding the abbreviation with angle brackets.
Then you have :) in the abbreviations list but ) has special meaning in regular expression syntax so your code also needs to handle that situation.
All the above implies that you need to analyze the contents of the abbreviations list file in order to turn a raw abbreviation into a valid regular expression that you can then use to locate the abbreviation in the input text.
If you assume that the abbreviations list may contain every possible abbreviation, you would probably need a large amount of code to handle each one properly. Rather than do that, I just concentrated on your sample list which divides easily into two groups:
simple words
punctuation only
Note that the second group is also known as emoticons and some emoticons contain both letters and punctuation which my code, below, does not handle. As I said, my solution only pertains to your sample list of abbreviations.
Here is the code and below the code are some notes regarding it. Please not that I took the liberty of not just fixing your code, but refactoring it as well.
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
//Driver for Abbreviations
public class AbbreviationsDriver {
//Abbreviations list file
private static Path abbreviationsListPath = Paths.get("abbreviations.txt");
//message file
private static Path inputPath = Paths.get("sample_msg.txt");
//output message file
private static File outputMessageFile = new File("sample_output.txt");
//main method
public static void main(String[] args) throws FileNotFoundException {
List<String> abbreviationsList = readFileList(abbreviationsListPath);
System.out.println("List of abbreviations: " + abbreviationsList);
String message = readFile(inputPath);
System.out.println("\nMessage in input file:\n" + message);
String result = addTags(message, abbreviationsList);
writeFile(outputMessageFile, result);
System.out.println("\nMessage with tag in output file:\n" + result);
}
//method to add tags
public static String addTags(String toTag, List<String> abbreviations) {
for (String abbreviation : abbreviations) {
String regex;
if (abbreviation.contains(")")) {
regex = "(\\Q" + abbreviation + "\\E)";
}
else {
regex = "(?i)(\\b" + abbreviation + "\\b)";
}
toTag = toTag.replaceAll(regex, "<$1>");
}
return toTag;
}
//method to read the file list
public static List<String> readFileList(Path path) {
List<String> list;
try {
list = Files.readAllLines(path);
}
catch (IOException exception) {
list = List.of();
System.out.println("Failed to load: " + path);
exception.printStackTrace();
}
return list;
}
//method to read the file
public static String readFile(Path path) {
String inputFile;
try {
inputFile = Files.readString(path);
}
catch (IOException exception) {
System.out.println("Failed to read: " + path);
exception.printStackTrace();
inputFile = "";
}
return inputFile;
}
//method to write the output file
public static void writeFile(File fileName, String outString) {
try {
PrintWriter outputStatement = new PrintWriter(fileName);
outputStatement.print(outString);
outputStatement.close();
}
catch (Exception exception) {
System.out.println("Failed to write file: " + fileName);
exception.printStackTrace();
}
}
}
I use interface Path rather that class File so that I can use methods of class Files to read the text files that contain the abbreviations list and the input. Hence my code works with interface List rather than with an array of String.
Passing class members to methods as method parameters defeats the purpose of having a class member in the first place. Hence I removed the members message and AbbreviationsList.
The actual work of locating the abbreviations in the input and surrounding them with angle brackets, all occurs in method addTags. Here I handle each separate group of abbreviations. If the abbreviation contains the character ), I quote it by surrounding it with quote markers \Q and \E. (Refer to javadoc of class Pattern). Otherwise the abbreviation is a regular word, so I surround it with the word boundary marker \b. I also enclose each regular expression in parentheses so as to make it a capturing group. Note that the second regular expression begins with (?i) which means to ignore case. Hence iirc will match Iirc.
The replacement string is <$1>. The $1 is replaced with the string that was actually matched so any abbreviation found in the input will be replaced by the matched string surrounded with angle brackets.
Finally, here is the output when running the above code and using your sample data.
List of abbreviations: [lol, :), iirc, 4, u, ttfn]
Message in input file:
How are u today? Iirc, this is your first free day. Hope you are having fun! :)
Message with tag in output file:
How are <u> today? <Iirc>, this is your first free day. Hope you are having fun! <:)>
There are several ways to do this. Either you use regular expressions, or you do things the old-fashioned way by parsing word-by-word. Others have pointed out problems with your current code, due to using strings that contain regular expression metacharacters. In particular,
String doesNotWork = "I am :)".replaceAll(":)", "happy"); // invalid regex
This can be solved by quoting the string, so that metacharacters are converted into literals (it returns the string that would be written as "\\Q:)\\E", because \Q and \E are used as delimiters for quoting whole substrings, as opposed to \, which quotes the next only if it is non-alphabetical; and is otherwise used for a host of regex classes):
String worksAsExpected = "I am :)".replaceAll(Pattern.quote(":)"), "happy");
The most efficient way to process text is to do a single pass. This can be achieved by combining literal expressions with |s:
String regex = Stream.of("lol iirc 4".split(" "))
.map(s -> Pattern.quote(s)) // quotes each emoticon
.collect(Collectors.joining("|")); // joins with |
Matcher m = Pattern.compile(regex).matcher(input);
This yields surprisingly compact code, with nothing hardcoded. Finished code:
import java.util.regex.*;
import java.util.stream.*;
public class T {
public static String mark(
String[] needles, String startMark, String endMark, String input) {
String regex = Stream.of(needles)
.map(s -> s.matches("\\p{Alpha}+") ? // quotes each
"\\b" + Pattern.quote(s) + "\\b" : // to avoid yo<u>r
Pattern.quote(s)) // to handle emoticons
.collect(Collectors.joining("|")); // joins with |
Matcher m = Pattern.compile(regex).matcher(input);
StringBuffer output = new StringBuffer();
while (m.find()) {
m.appendReplacement(output, startMark + m.group() + endMark);
}
m.appendTail(output);
return output.toString();
}
public static void main(String ... args) {
System.out.println(mark(
"lol iirc 4 u ttfn :)".split(" "), // abbreviations
"<", ">", // markers to mark them with
"How are u today? iirc, this is your first free day. "
+ "Hope you are having fun! :)"));
}
}
I used #Arvind's trick of placing word-boundary metacharacters (\\b) only on alphabetical needles. This fixes all us in words being marked; but may yield strange results for 4s: writing a number with 4s in it will get it marked. Ultimately, natural language processing is hard. Regular expressions are great for very regular inputs.
Is there any way I could select specific text after specific text and keep selecting until that word is selected. And once selected then leave the remaining.
Here is the example
ABCDEF
JHJHJNJN<098978686
<jjg>
HGHJFGV XXXX
10-10-2018
JHKGHKGHG
JKHJHHJM
10-10-2019 JGHHGHGVH
HBVJHBHBB
Just want to select this date 10-10-2018 in whole content which always comes after XXX with couple of spaces. I can't use just regex with specific value(10-10-2018) because date can be changed and possible that date pattern somewhere is also present like in example in last line.
Please share your thoughts..!
Thanks
Assuming the example is correct, then the following regex will extract just the date using find() and ensure that DOTALL is set.
"XXXX.*?[\\s]+([\\d]{1,2}-[\\d]{1,2}-[\\d]{4})"
Basically, search for XXX followed by spaces/newline then find the date. It will be placed into a group and can then be extracted.
You can see the operation at this location, though be sure to select "DOTALL".
public String getDate(String input)
{
String date = "";
Pattern dte = Pattern.compile("XXXX.*?[\\s]+([\\d]{1,2}-[\\d]{1,2}-[\\d]{4})", Pattern.DOTALL);
Matcher m = dte.matcher(input);
if (m.find() && m.groupCount() > 0) {
date = m.group(1);
}
return date;
}
Test case
#Test
public void testData() throws Exception
{
RegEx_52879334 re = new RegEx_52879334();
String input = re.getInputData();
String date = re.getDate(input);
assertEquals("10-10-2018", date);
System.out.println("Found: " + date);
}
Output:
Found: 10-10-2018
I have a tab with name 'Preferences' where user can set the Date format in any format like DD/MM/YYYY, DD.MM.YYYY, MM/DD/YYYY etc and is applicable through out the web application
I have chosen a Date format DD.MM.YYYY and saved it
Now I need to validate a text field some where in my application where I give input say 01012001 and it should automatically take the input and convert to the preferred Date format 01.01.2001 where I have been saved in 'Preferences' tab
Could any one help me out how can I validate this in java?
In your case What I understand is you need to write function which will return you formatted date according to selected format.Below function will do the work and return you formatted string.
public String parseDate(StringBuilder dateString, String formatString) {
String separator = "";
String slashSeperator = "/";
if (formatString.contains(slashSeperator)) {
separator = slashSeperator;
} else {
String dotSeparator = ".";
if (formatString.contains(dotSeparator)) {
separator = dotSeparator;
}
}
if (dateString.length() == 8) {
dateString.insert(2, separator);
dateString.insert(5, separator);
} else {
return "False Date Entered";
}
return dateString.toString();
}
If you are using Java 8 you can check new Date library and its DateTimeFormatter. Use this formatter to parse date using Date.parse. Examples are included within docs.
I have a String that could be in many different formats. I need to be able to recognize the actual type of the value at runtime and then transform the value to that type.
For example. If I have a String Fri Feb 08 07:30:00 GMT 2013 this is actually a Date and a the String should be transformed into a date object and returned as such.
My current solution to this problem is to 'try' to convert it to a data type, if the conversion succeeds then all is good, if the conversion fails then move on to the next conversion attempt. This works, but is ugly and un-maintainable and I'm sure a better solution already exists out there.
Thanks.
You may use separate regular expression for each data type like this:
private final static Pattern DATE_PATTERN =
Pattern.compile (
"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat) " +
"(?:Jan|Feb|Mar|Apr|May|June?|July?|Aug|Sept?|Oct|Nov|Dec) " +
"\\d\\d \\d\\d:\\d\\d:\\d\\d \\S+ \\d\\d\\d\\d");
private final static Pattern DOUBLE_PATTERN =
Pattern.compile (
"[\\+\\-]?\\d+\\.\\d+(?:[eE][\\+\\-]?\\d+)?");
private final static Pattern INTEGER_PATTERN =
Pattern.compile (
"[\\+\\-]?\\d+");
public static Object stringToObject (String string)
{
if (DATE_PATTERN.matcher (string).matches ())
return stringToDate (string);
else if (DOUBLE_PATTERN.matcher (string).matches ())
return Double.valueOf (string);
else if (INTEGER_PATTERN.matcher (string).matches ())
return Integer.valueOf (string);
else return string;
}
public static void main(String[] args) {
String s = "Fri Feb 08 07:30:00 GMT 2013";
SimpleDateFormat FT = new SimpleDateFormat("EEE MMM dd hh:mm:ss z yyyy");
Date d;
try {
d = FT.parse(s);
System.out.println(d);
} catch (ParseException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
}
Try regular expression :
You can write a pattern for each data type you have, then match that pattern with each actual string you can associate a conversion for each match.
Here is a simple example (in pseudo Java):
String name = "Mike"; // This is an English name
String nameRegEx ="[A-Z][a-z]+"; //this patterns matches an english name
Matcher nameMatcher = new Matcher(regEx);
if (match.matches(name)){// I use the matches() method to verify the format of the string
Name nameObject = Converter.getNameObjectFromString(name);//I make the conversion
}
Checkout the java documentation for more details on matchers and regular expressions :
http://docs.oracle.com/javase/tutorial/essential/regex/
Your approach is fine, if the strings passed to you are out of your control. Just one more suggestion: You should apply every possible conversion and check for ambiguous strings. If multiple conversions succeed then the string is ambiguous and you should do some error handling, probably throwing an exception.