Read /Edit / Write jpg IPTC metadata in Java - java

I am using Apache Commons but it is not enough for me because it is so old technology. So ,i found iCafe and it seems better but I am having the error below. Any idea what i am doing wrong?
private static List<IPTCDataSet> createIPTCDataSet() {
List<IPTCDataSet> iptcs = new ArrayList<IPTCDataSet>();
iptcs.add(new IPTCDataSet(IPTCApplicationTag.COPYRIGHT_NOTICE, "Copyright 2014-2016, yuwen_66#yahoo.com"));
iptcs.add(new IPTCDataSet(IPTCApplicationTag.CATEGORY, "ICAFE"));
iptcs.add(new IPTCDataSet(IPTCApplicationTag.KEY_WORDS, "Welcome 'icafe' user!"));
return iptcs;
}
private static IPTC createIPTC() {
IPTC iptc = new IPTC();
iptc.addDataSets(createIPTCDataSet());
return iptc;
}
public static void main(String[] args) throws IOException {
FileInputStream fin = new FileInputStream("C:/Users/rajab/Desktop/test/ibo.jpeg");
FileOutputStream fout = new FileOutputStream("C:/Users/rajab/Desktop/test/ibo/ibo.jpeg");
List<Metadata> metaList = new ArrayList<Metadata>();
//metaList.add(populateExif(TiffExif.class));
metaList.add(createIPTC());
metaList.add(new Comments(Arrays.asList("Comment1", "Comment2")));
Metadata.insertMetadata(metaList, fin, fout);
}
}
and my EXCEPTION
run:
Exception in thread "main" java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
at com.icafe4j.image.meta.Metadata.(Unknown Source)
at vectorcleaner.Metadata1.populateExif(Metadata1.java:41)
at vectorcleaner.Metadata1.main(Metadata1.java:127)
Caused by: java.lang.ClassNotFoundException: org.slf4j.LoggerFactory
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 3 more
C:\Users\rajab\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53:
Java returned: 1
BUILD FAILED (total time: 0 seconds)

Not sure what exactly you want but here is what ICAFE can do with IPTC metadata:
Read IPTC from image.
Insert IPTC into image or update IPTC of existing image.
Delete IPTC from image.
For reading IPTC, here is an example:
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Iterator;
import com.icafe4j.image.meta.Metadata;
import com.icafe4j.image.meta.MetadataEntry;
import com.icafe4j.image.meta.MetadataType;
import com.icafe4j.image.meta.iptc.IPTC;
public class ExtractIPTC {
public static void main(String[] args) throws IOException {
Map<MetadataType, Metadata> metadataMap = Metadata.readMetadata(args[0]);
IPTC iptc = (IPTC)metadataMap.get(MetadataType.IPTC);
if(iptc != null) {
Iterator<MetadataEntry> iterator = iptc.iterator();
while(iterator.hasNext()) {
MetadataEntry item = iterator.next();
printMetadata(item, "", " ");
}
}
}
private void printMetadata(MetadataEntry entry, String indent, String increment) {
logger.info(indent + entry.getKey() (StringUtils.isNullOrEmpty(entry.getValue())? "" : ": " + entry.getValue()));
if(entry.isMetadataEntryGroup()) {
indent += increment;
Collection<MetadataEntry> entries = entry.getMetadataEntries();
for(MetadataEntry e : entries) {
printMetadata(e, indent, increment);
}
}
}
}
For insert/update IPTC, here is an example:
import java.io.IOException;
import java.util.List;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import com.icafe4j.image.meta.Metadata;
import com.icafe4j.image.meta.MetadataEntry;
import com.icafe4j.image.meta.MetadataType;
import com.icafe4j.image.meta.iptc.IPTCDataSet;
import com.icafe4j.image.meta.iptc.IPTCApplicationTag;
public class InsertIPTC {
public static void main(String[] args) throws IOException {
FileInputStream fin = new FileInputStream("C:/Users/rajab/Desktop/test/ibo.jpeg");
FileOutputStream fout = new FileOutputStream("C:/Users/rajab/Desktop/test/ibo/ibo.jpeg");
Metadata.insertIPTC(fin, fout, createIPTCDataSet(), true);
}
private static List<IPTCDataSet> createIPTCDataSet() {
List<IPTCDataSet> iptcs = new ArrayList<IPTCDataSet>();
iptcs.add(new IPTCDataSet(IPTCApplicationTag.COPYRIGHT_NOTICE, "Copyright 2014-2016, yuwen_66#yahoo.com"));
iptcs.add(new IPTCDataSet(IPTCApplicationTag.OBJECT_NAME, "ICAFE"));
iptcs.add(new IPTCDataSet(IPTCApplicationTag.KEY_WORDS, "Welcome 'icafe' user!"));
return iptcs;
}
}
The above example uses Metadata.insertIPTC instead of Metadata.insertMetadata because we need one more boolean parameter. If set to true, it will keep the existing IPTC data and only update the those we want. Some of the IPTC entries allow multiple values. In that case, we only append/add the new ones. For other unique entries, they will be replaced by the new ones.
Looks like you want to add key words and title. In your question, you already showed code to insert key words and in order to insert title, use OBJECT_NAME which can be found in the example above.
Note: you can add multiple key words as well. Some softwares can only handle one key words record. In that case, you can put all the key words in one record separated by semi-colon instead of insert multiple entries.

Related

Nullpointer Exception While Using Trying to Read Excel in Selenium

Hi guys i Searched Every Where Solution For But Can't Find. Why Am Getting Null Pointer Exception For This i Dunno. Please Sort Me This Out. It is Showing as Path is Only Wrong But i Specified it Correctly only.
My Code :
package UsingExcel;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import com.sun.rowset.internal.Row;
public class Demo
{
public void ReadExcel(String filepath,String filename,String Sheetname) throws IOException
{
File file = new File(filepath); // line 21
FileInputStream stream = new FileInputStream(file);
Workbook Mybook = null;
String FileExtensionnname = filename.substring(filename.indexOf("."));
if(FileExtensionnname.equals(".xlsx"))
{
Mybook = new XSSFWorkbook(stream);
}
else if(FileExtensionnname.equals(".xls"))
{
Mybook = new HSSFWorkbook(stream);
}
Sheet filesheet = Mybook.getSheet(Sheetname);
int rowcount = filesheet.getLastRowNum()-filesheet.getFirstRowNum();
for(int i=0;i<rowcount+1;i++)
{
org.apache.poi.ss.usermodel.Row row =filesheet.getRow(i);
for(int j=0;j<row.getLastCellNum();j++)
{
System.out.println(row.getCell(j).getStringCellValue()+ "||");
}
System.out.println();
}
}
public static void main(String[] args) throws IOException
{
Demo excelfile = new Demo();
String filepath = System.getProperty("E:\\Mybook.xlsx");
excelfile.ReadExcel(filepath, "Mybook.xlsx", "DemoExcel");
}
}
My Error is :
Exception in thread "main" java.lang.NullPointerException
at java.io.File.<init>(Unknown Source)
at UsingExcel.Demo.ReadExcel(Demo.java:21)
at UsingExcel.Demo.main(Demo.java:61)
Hope You Have Understood My Problem, Please Sort This out. But When am Testing a Login Page Using Excel That No Problem Will Be Coming, Now i Try To Print on The
Console it is Not Working.
Your filepath should just be
String filepath = "E:\\Mybook.xlsx", don't use System.getProperty.
From docs :
Gets the system property indicated by the specified key
A null is being passed to your method ReadExcel(...), because there is no System property defined as E:\Mybook.xlsx

How to manipulate content of a comment with Apache POI

I would like to find a comment in Docx document (somehow, by author or ID...), then create new content. I was able to create a comment, with the help of this answer, but had no luck with manipulation.
As said in my answer linked in your question, until now the XWPFdocument will only read that package part while creating. There is neither write access nor a possibility to create that package part. This is mentioned in XWPFDocument.java - protected void onDocumentRead(): code line 210: "// TODO Create according XWPFComment class, extending POIXMLDocumentPart".
So we need doing this ourself until now. We need providing class extending POIXMLDocumentPart for comments and registering this relation instead of only relation to the simple POIXMLDocumentPart. So that and changings can be made which were committed while writing the XWPFDocument.
Example:
import java.io.*;
import org.apache.poi.*;
import org.apache.poi.openxml4j.opc.*;
import org.apache.xmlbeans.*;
import org.apache.poi.xwpf.usermodel.*;
import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import javax.xml.namespace.QName;
import java.math.BigInteger;
import java.util.GregorianCalendar;
import java.util.Locale;
public class WordChangeComments {
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument(new FileInputStream("WordDocumentHavingComments.docx"));
for (POIXMLDocumentPart.RelationPart rpart : document.getRelationParts()) {
String relation = rpart.getRelationship().getRelationshipType();
if (relation.equals(XWPFRelation.COMMENT.getRelation())) {
POIXMLDocumentPart part = rpart.getDocumentPart(); //this is only POIXMLDocumentPart, not a high level class extending POIXMLDocumentPart
//provide class extending POIXMLDocumentPart for comments
MyXWPFCommentsDocument myXWPFCommentsDocument = new MyXWPFCommentsDocument(part.getPackagePart());
//and registering this relation instead of only relation to POIXMLDocumentPart
String rId = document.getRelationId(part);
document.addRelation(rId, XWPFRelation.COMMENT, myXWPFCommentsDocument);
//now the comments are available from the new MyXWPFCommentsDocument
for (CTComment ctComment : myXWPFCommentsDocument.getComments().getCommentArray()) {
System.out.print("Comment: Id: " + ctComment.getId());
System.out.print(", Author: " + ctComment.getAuthor());
System.out.print(", Date: " + ctComment.getDate());
System.out.print(", Text: ");
for (CTP ctp : ctComment.getPArray()) {
System.out.print(ctp.newCursor().getTextValue());
}
System.out.println();
//and changings can be made which were committed while writing the XWPFDocument
if (BigInteger.ONE.equals(ctComment.getId())) { //the second comment (Id 0 = first)
ctComment.setAuthor("New Author");
ctComment.setInitials("NA");
ctComment.setDate(new GregorianCalendar(Locale.US));
CTP newCTP = CTP.Factory.newInstance();
newCTP.addNewR().addNewT().setStringValue("The new Text for Comment with Id 1.");
ctComment.setPArray(new CTP[]{newCTP });
}
}
}
}
document.write(new FileOutputStream("WordDocumentHavingComments.docx"));
document.close();
}
//a wrapper class for the CommentsDocument /word/comments.xml in the *.docx ZIP archive
private static class MyXWPFCommentsDocument extends POIXMLDocumentPart {
private CTComments comments;
private MyXWPFCommentsDocument(PackagePart part) throws Exception {
super(part);
comments = CommentsDocument.Factory.parse(part.getInputStream(), DEFAULT_XML_OPTIONS).getComments();
}
private CTComments getComments() {
return comments;
}
#Override
protected void commit() throws IOException {
System.out.println("============MyXWPFCommentsDocument is committed=================");
XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
xmlOptions.setSaveSyntheticDocumentElement(new QName(CTComments.type.getName().getNamespaceURI(), "comments"));
PackagePart part = getPackagePart();
OutputStream out = part.getOutputStream();
comments.save(out, xmlOptions);
out.close();
}
}
}
This works for apache poi 3.17. Since apache poi 4.0.0 the ooxml part is separated. So there must be:
...
import org.apache.poi.ooxml.*;
...
import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
...

Saving an H2O model directly from Java

I'm trying to create and save a generated model directly from Java. The documentation specifies how to do this in R and Python, but not in Java. A similar question was asked before, but no real answer was provided (beyond linking to H2O doc, which doesn't contain a code example).
It'd be sufficient for my present purpose get some pointers to be able to translate the following reference code to Java. I'm mainly looking for guidance on the relevant JAR(s) to import from the Maven repository.
import h2o
h2o.init()
path = h2o.system_file("prostate.csv")
h2o_df = h2o.import_file(path)
h2o_df['CAPSULE'] = h2o_df['CAPSULE'].asfactor()
model = h2o.glm(y = "CAPSULE",
x = ["AGE", "RACE", "PSA", "GLEASON"],
training_frame = h2o_df,
family = "binomial")
h2o.download_pojo(model)
I think I've figured out an answer to my question. A self-contained sample code follows. However, I'll still appreciate an answer from the community since I don't know if this is the best/idiomatic way to do it.
package org.name.company;
import hex.glm.GLMModel;
import water.H2O;
import water.Key;
import water.api.StreamWriter;
import water.api.StreamingSchema;
import water.fvec.Frame;
import water.fvec.NFSFileVec;
import hex.glm.GLMModel.GLMParameters.Family;
import hex.glm.GLMModel.GLMParameters;
import hex.glm.GLM;
import water.util.JCodeGen;
import java.io.*;
import java.util.Map;
public class Launcher
{
public static void initCloud(){
String[] args = new String [] {"-name", "h2o_test_cloud"};
H2O.main(args);
H2O.waitForCloudSize(1, 10 * 1000);
}
public static void main( String[] args ) throws Exception {
// Initialize the cloud
initCloud();
// Create a Frame object from CSV
File f = new File("/path/to/data.csv");
NFSFileVec nfs = NFSFileVec.make(f);
Key frameKey = Key.make("frameKey");
Frame fr = water.parser.ParseDataset.parse(frameKey, nfs._key);
// Create a GLM and output coefficients
Key modelKey = Key.make("modelKey");
try {
GLMParameters params = new GLMParameters();
params._train = frameKey;
params._response_column = fr.names()[1];
params._intercept = true;
params._lambda = new double[]{0};
params._family = Family.gaussian;
GLMModel model = new GLM(params).trainModel().get();
Map<String, Double> coefs = model.coefficients();
for(Map.Entry<String, Double> entry : coefs.entrySet()) {
System.out.format("%s: %f\n", entry.getKey(), entry.getValue());
}
String filename = JCodeGen.toJavaId(model._key.toString()) + ".java";
StreamingSchema ss = new StreamingSchema(model.new JavaModelStreamWriter(false), filename);
StreamWriter sw = ss.getStreamWriter();
OutputStream os = new FileOutputStream("/base/path/" + filename);
sw.writeTo(os);
} finally {
if (fr != null) {
fr.remove();
}
}
}
}
Would something like this do the trick?
public void saveModel(URI uri, Keyed<Frame> model)
{
Persist p = H2O.getPM().getPersistForURI(uri);
OutputStream os = p.create(uri.toString(), true);
model.writeAll(new AutoBuffer(os, true)).close();
}
Make sure the URI has a proper form otherwise H2O will break on an npe. As for Maven you should be able to get away with the h2o core.
<dependency>
<groupId>ai.h2o</groupId>
<artifactId>h2o-core</artifactId>
<version>3.14.0.2</version>
</dependency>

Validate each filed against multiple constraints using CSV Parser

I am working on a requirement where I need to parse CSV record fields against multiple validations. I am using supercsv which has support for field level processors to validate data.
My requirement is to validate each record/row field against multiple validations and save them to the database with success/failure status. for failure records I have to display all the failed validations using some codes.
Super CSV is working file but it is checking only first validation for a filed and if it is failed , ignoring second validation for the same field.Please look at below code and help me on this.
package com.demo.supercsv;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import org.supercsv.cellprocessor.Optional;
import org.supercsv.cellprocessor.constraint.NotNull;
import org.supercsv.cellprocessor.constraint.StrMinMax;
import org.supercsv.cellprocessor.constraint.StrRegEx;
import org.supercsv.cellprocessor.constraint.UniqueHashCode;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.exception.SuperCsvCellProcessorException;
import org.supercsv.io.CsvBeanReader;
import org.supercsv.io.CsvBeanWriter;
import org.supercsv.io.ICsvBeanReader;
import org.supercsv.io.ICsvBeanWriter;
import org.supercsv.prefs.CsvPreference;
public class ParserDemo {
public static void main(String[] args) throws IOException {
List<Employee> emps = readCSVToBean();
System.out.println(emps);
System.out.println("******");
writeCSVData(emps);
}
private static void writeCSVData(List<Employee> emps) throws IOException {
ICsvBeanWriter beanWriter = null;
StringWriter writer = new StringWriter();
try{
beanWriter = new CsvBeanWriter(writer, CsvPreference.STANDARD_PREFERENCE);
final String[] header = new String[]{"id","name","role","salary"};
final CellProcessor[] processors = getProcessors();
// write the header
beanWriter.writeHeader(header);
//write the beans data
for(Employee emp : emps){
beanWriter.write(emp, header, processors);
}
}finally{
if( beanWriter != null ) {
beanWriter.close();
}
}
System.out.println("CSV Data\n"+writer.toString());
}
private static List<Employee> readCSVToBean() throws IOException {
ICsvBeanReader beanReader = null;
List<Employee> emps = new ArrayList<Employee>();
try {
beanReader = new CsvBeanReader(new FileReader("src/employees.csv"),
CsvPreference.STANDARD_PREFERENCE);
// the name mapping provide the basis for bean setters
final String[] nameMapping = new String[]{"id","name","role","salary"};
//just read the header, so that it don't get mapped to Employee object
final String[] header = beanReader.getHeader(true);
final CellProcessor[] processors = getProcessors();
Employee emp;
while ((emp = beanReader.read(Employee.class, nameMapping,
processors)) != null) {
emps.add(emp);
if (!CaptureExceptions.SUPPRESSED_EXCEPTIONS.isEmpty()) {
System.out.println("Suppressed exceptions for row "
+ beanReader.getRowNumber() + ":");
for (SuperCsvCellProcessorException e :
CaptureExceptions.SUPPRESSED_EXCEPTIONS) {
System.out.println(e);
}
// for processing next row clearing validation list
CaptureExceptions.SUPPRESSED_EXCEPTIONS.clear();
}
}
} finally {
if (beanReader != null) {
beanReader.close();
}
}
return emps;
}
private static CellProcessor[] getProcessors() {
final CellProcessor[] processors = new CellProcessor[] {
new CaptureExceptions(new NotNull(new StrRegEx("\\d+",new StrMinMax(0, 2)))),//id must be in digits and should not be more than two charecters
new CaptureExceptions(new Optional()),
new CaptureExceptions(new Optional()),
new CaptureExceptions(new NotNull()),
// Salary
};
return processors;
}
}
Exception Handler:
package com.demo.supercsv;
import java.util.ArrayList;
import java.util.List;
import org.supercsv.cellprocessor.CellProcessorAdaptor;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.exception.SuperCsvCellProcessorException;
import org.supercsv.util.CsvContext;
public class CaptureExceptions extends CellProcessorAdaptor {
public static List<SuperCsvCellProcessorException> SUPPRESSED_EXCEPTIONS =
new ArrayList<SuperCsvCellProcessorException>();
public CaptureExceptions(CellProcessor next) {
super(next);
}
public Object execute(Object value, CsvContext context) {
try {
return next.execute(value, context);
} catch (SuperCsvCellProcessorException e) {
// save the exception
SUPPRESSED_EXCEPTIONS.add(e);
if(value!=null)
return value.toString();
else
return "";
}
}
}
sample csv file
ID,Name,Role,Salary
a123,kiran,CEO,"5000USD"
2,Kumar,Manager,2000USD
3,David,developer,1000USD
when I run my program supercsv exception handler displaying this message for the ID value in the first row
Suppressed exceptions for row 2:
org.supercsv.exception.SuperCsvConstraintViolationException: 'a123' does not match the regular expression '\d+'
processor=org.supercsv.cellprocessor.constraint.StrRegEx
context={lineNo=2, rowNo=2, columnNo=1, rowSource=[a123, kiran, CEO, 5000USD]}
[com.demo.supercsv.Employee#23bf011e, com.demo.supercsv.Employee#50e26ae7, com.demo.supercsv.Employee#40d88d2d]
for field Id length should not be null and more than two and it should be neumeric...I have defined field processor like this.
new CaptureExceptions(new NotNull(new StrRegEx("\\d+",new StrMinMax(0, 2))))
but super csv ignoring second validation (maxlenght 2) if given input is not neumeric...if my input is 100 then its validating max lenght..but how to get two validations for wrong input.plese help me on this
SuperCSV cell processors will work in sequence. So, if it passes the previous constraint validation then it will check next one.
To achieve your goal, you need to write a custom CellProcessor, which will check whether the input is a number (digit) and length is between 0 to 2.
So, that both of those checks are done in a single step.

Find the second duplicate word

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class Example {
public static void main(String[] args) throws IOException
{
File fis=new File("D:/Testcode/Test.txt");
BufferedReader br;
String input;
String var = null;
if(fis.isAbsolute())
{
br=new BufferedReader(new FileReader(fis.getAbsolutePath()));
while ((input=br.readLine())!=null) {
var=input;
}
}
//String var="Duminy to Warner, OUT, Duminy gets a wicket again. He has been breaking...
if(var!=null)
{
String splitstr[]=var.split(",");
if(splitstr[0].contains("to"))
{
String ss=splitstr[0];
String a[]=ss.split("\\s+");
int value=splitstr[0].indexOf("to");
System.out.println("Subject:"+splitstr[0].substring(0,value));
System.out.println("Object:"+splitstr[0].substring(value+2));
System.out.println("Event:"+splitstr[1]);
int count=var.indexOf(splitstr[2]);
System.out.println("Narrated Information:"+var.substring(count));
}
}
}
}
The above program shown the following output:
Subject:Duminy
Object: Warner
Event: OUT
Narrated Information: Duminy gets a wicket again. He has been breaking....
my question is, the text may contain, For example: "Dumto to Warner, OUT, Duminy gets a wicket again. He has been breaking..." means, the above program wouldn't show output like above.. how to identity the text after the space for checking the condition
Instead of:
if(splitstr[0].contains("to")
Change it to:
if(splitstr[0].contains(" to ")
It should then work fine IMO.

Categories