I'm having an issue with this line of code:
try (OutputStreamWriter fileout = new OutputStreamWriter(new FileOutputStream(Paths.get(path.toString(), TAGS_FILE.toString()).toString()), "UTF-16")) {
fileout.write(gson.toJson(imageList, listType));
fileout.flush();
fileout.close();
}
I was using UTF-8 originally and it was working fine, loaded fine and everything, but had to change to UTF-16 to preserve some special characters. It still writes out the file correctly, exact same as with UTF-8 (except with the special characters in-tact), but when it tries to load the file into another session I get "Expected BEGIN_ARRAY but was STRING..."
Is there a way around this?
Also, if this helps:
private final Type listType = new TypeToken<TreeSet<MyClass>>(){}.getType();
TreeSet<MyClass> imageList;
UPDATE:
private void move(File file, Path destination, boolean autoTag) {
String fileName = file.getName();
Matcher numberMatcher = leadingNumbersPattern.matcher(fileName);
// remove leading numbers
while (numberMatcher.find()) {
fileName = clean(fileName, leadingNumbersPattern);
}
Matcher artistMatcher = artistPattern.matcher(fileName);
Matcher newFileNameMatcher = newFileNamePattern.matcher(fileName);
if (artistMatcher.find() && newFileNameMatcher.find()) {
// set artist name
String artist = artistMatcher.group().substring(0, artistMatcher.group().length() - 1);
// set new picture name
String newFileName = newFileNameMatcher.group().substring(1);
Path newPath = Paths.get(destination.toString(), artist); // path to artist folder
new File(newPath.toString()).mkdirs(); // make artist folder
newPath = Paths.get(destination.toString(), artist, newFileName); // make path to new file location
try {
Files.move(file.toPath(), newPath, StandardCopyOption.REPLACE_EXISTING); // move file to new location
MyImage newImage = new MyImage(newPath.toString(), artist, newFileName);
Changing back to UTF-8 fixed the issue. I had to remake the json file; I guess the Thai characters had somehow slipped through when I converted everything to UTF-8 originally.
EDIT:
Found the cause! The load() method I was using to deserialize the file wasn't set to use UTF-8 on the FileInputStream. Adding this fixed the issue completely.
Related
I have a file in ISO-8859-1 containing german umlauts and I need to unmarshall it using JAXB. But before I need the content in UTF-8.
#Override
public List<Usage> convert(InputStream input) {
try {
InputStream inputWithNamespace = addNamespaceIfMissing(input);
inputWithNamespace = convertFileToUtf(inputWithNamespace);
ORDR order = xmlUnmarshaller.unmarshall(inputWithNamespace, ORDR.class);
...
I get the "file" as an InputStream. My idea was to read the file's content in UTF-8 and make another InputStream to use. This is what I've tried:
private InputStream convertFileToUtf(InputStream inputStream) throws IOException {
byte[] bytesInIso = ByteStreams.toByteArray(inputStream);
String stringIso = new String(bytesInIso);
byte[] bytesInUtf = new String(bytesInIso, ISO_8859_1).getBytes(UTF_8);
String stringUtf = new String(bytesInUtf);
return new ByteArrayInputStream(bytesInUtf);
}
I have those 2 Strings to check the contents, but even just reading the ISO file, it gives question marks where umlauts are (?) and converting that to UTF_8 gives strange characters like 1/2 and so on.
UPDATE
byte[] bytesInIso = ByteStreams.toByteArray(inputWithNamespace);
String contentInIso = new String(bytesInIso);
byte[] bytesInUtf = new String(bytesInIso, ISO_8859_1).getBytes(UTF_8);
String contentInUtf = new String(bytesInUtf);
Verifying contentInIso prints question marks instead of the umlauts and by checking contentInIso instead of umlauts, it has characters like "�".
#Override
public List<Usage> convert(InputStream input) {
try {
InputStream inputWithNamespace = addNamespaceIfMissing(input);
byte[] bytesInIso = ByteStreams.toByteArray(inputWithNamespace);
String contentInIso = new String(bytesInIso);
byte[] bytesInUtf = new String(bytesInIso, ISO_8859_1).getBytes(UTF_8);
String contentInUtf = new String(bytesInUtf);
ORDR order = xmlUnmarshaller.unmarshall(inputWithNamespace, ORDR.class);
This method convert it's called by another one called processUsageFile:
private void processUsageFile(File usageFile) {
try (FileInputStream fileInputStream = new FileInputStream(usageFile)) {
usageImporterService.importUsages(usageFile.getName(), fileInputStream, getUsageTypeValidated(usageFile.getName()));
log.info("Usage file {} imported successfully. Moving to archive directory", usageFile.getName());
If i take the code I have written under the UPDATE statement and put it immediately after the try, the first contentInIso has question marks but the contentInUtf has the umlauts. Then, by going into the convert, jabx throws an exception that the file has a premature end of line.
Regarding the behaviour you are getting,
String stringIso = new String(bytesInIso);
In this step, you construct a new String by decoding the specified array of bytes using the platform's default charset.
Since this is probably not ISO_8859_1, I think the String you are looking at becomes garbled here.
Placed the reports have overrided all the resultsi would like to print in a table with results but when i printed it overriding the results and it is printing only one line
am passing the values form other class file to print the results
i have tried using Buffered writer for writing the code
public void createTestSummaryHTMLTable(String sample,String samp[le,String sample,String passedText,String status) throws IOException {
File file=new File("C:\\AutomationResults\\Forms\\",foldername);
if(!file.exists()){
file.mkdir();}
final String FILE_PATH =(file+"/"+formname);
//final String FILE_PATH = "C:\\AutomationResults\\Forms\\"+formname;
final String FILE_EXTENSION = "html";
DateFormat df = new SimpleDateFormat("yyyyMMdd"); // add S if you need milliseconds
String filename = FILE_PATH + "_"+ df.format(new Date()) + "." + FILE_EXTENSION;
File file2 = new File(filename);
// if file doesnt exists, then create it
if (!file2.exists()) {
file2.createNewFile();
}
BufferedWriter html = new BufferedWriter(new FileWriter(file2));
html.write("<html><body bgcolor='#E6E6FA'><table border=1 cellpadding=0>");
html.write("<title>Automation Summary report </title>");
html.write("<br>");
html.write("<center><strong><em>Batch report heading</em></strong>");
html.write("<span style ='float; right;position:relative;right:30px;font weight:bold'>"+new Date().toString()+"</span>");
html.write("<tr>");
addlabel1(html,"Test Step Name");
addlabel1(html,"Test Step Description");
addlabel1(html,"Status");
addlabel1(html,"Screenshot");
html.write("</tr>");
html.write("<tr>");
html.newLine();
addlabel(html,sample);
addlabel(html,sample);
String status1 = "Passed";
if (status1.equals(status))
{
html.write("<td width='20'style='color:#00F00;font-weight:bold;text-align:center'>"+status+"</td>");
} else {
html.write("<td width='20'style='color:#A52A2A;font-weight:bold;text-align:center'>"+status+"</td>");
}
addlabel(html,"Screenshot");
html.write("</tr>");
html.write("</table></body></html>");
html.close();
}
Oh, I think i guessed your problem. The file written is a single long line.
That is because write only writes what you give it. You need to put a \n at the end of all your strings.
Alternatively, use Printwriter's println method to output to your file.
You can try adding a boolean parameter to FileWriter that helps to specify whether it should append to or override the existing content. If you pass true, it would open the file for writing in append mode.
Please change this line:
BufferedWriter html = new BufferedWriter(new FileWriter(file2));
To this:
BufferedWriter html = new BufferedWriter(new FileWriter(file2, true));
the actualresult
header is displaying for every row i dont need the header to display for all the rows result am getting is
expected result is
header should display only once
I am trying to attach a png file. Currently when I sent the email, the attachment is 2x bigger than the file should be and an invalid png file. Here is the code I currently have:
import com.sendgrid.*;
Attachments attachments = new Attachments();
String filePath = "/Users/david/Desktop/screenshot5.png";
String data = "";
try {
data = new String(Files.readAllBytes(Paths.get(filePath)));
} catch (IOException e) {
}
byte[] encoded = Base64.encodeBase64(data.getBytes());
String encodedString = new String(encoded);
attachments.setContent(encodedString);
Perhaps I am encoding the data incorrectly? What would be the correct way to 'get' the data to attach it?
With respect, this is why Python presents a problem to modern developers. It abstracts away important concepts that you can't fully understand in interpreted languages.
First, and this is a relatively basic concept, but you can't convert arbitrary byte sequences to a string and hope it works out. The following line is your first problem:
data = new String(Files.readAllBytes(Paths.get(filePath)));
EDIT: It looks like the library you are using expects the file to be base64 encoded. I have no idea why. Try changing your code to this:
Attachments attachments = new Attachments();
String filePath = "/Users/david/Desktop/screenshot5.png";
try {
byte[] encoded = Base64.encodeBase64(Files.readAllBytes(Paths.get(filePath)));
String encodedString = new String(encoded);
attachments.setContent(encodedString);
} catch (IOException e) {
}
The only issue you were having is that you were trying to represent arbitrary bytes as a string.
Take a look at the Builder class in the repository here. Example:
FileInputStream fileContent = new FileInputStream(filePath);
Attachments.Builder builder = new Attachments.Builder(fileName, fileContent);
mail.addAttachments(builder.build());
This question already has answers here:
inserting data in the middle of a text file through java
(2 answers)
Closed 9 years ago.
Suppose i have a text file named Sample.text.
i need advice on how to achieve this:
Sample.txt before running a program:
ABCD
while running the program, user will input string to be added starting at the middle
for example: user input is XXX
Sample.txt after running a program:
ABXXXCD
Basically you've got to rewrite the file, at least from the middle. This isn't a matter of Java - it's a matter of what file systems support.
Typically the way to do this is to open both the input file and an output file, then:
Copy the first part from the input file to the output file
Write the middle section to the output file
Copy the remainder of the input file to the output file
Optionally perform file renaming if you want the new file to have the same eventual name as the original file
The basic idea is to read the file contents into memory, say at program start, manipulate the string as desired, then write the entire thing back to the file.
So you would open and read in Sample.txt. In memory you have a string = "ABCD"
in your program execution, accept user input of XXX. Insert that into your string with your favorite string manipulation method. Now string = "ABXXXCD"
Finally you would overwrite Sample.txt with your updated string and close it.
If you were worried about corruption or something, you might save it to a secondary file, then verify its contents, delete the original, and rename the new to be the same as the original.
Actually i have did something like what you want, here try this code, its not a complete but it should give you a clear idea:
public void addString(String fileContent, String insertData) throws IOException {
String firstPart = getFirstPart(fileContent);
Pattern p = Pattern.compile(firstPart);
Matcher matcher = p.matcher(fileContent);
int end = 0;
boolean matched = matcher.find();
if (matched) {
end = matcher.end();
}
if(matched) {
String secondPart = fileContent.substring(end);
StringBuilder newFileContent = new StringBuilder();
newFileContent.append(firstPart);
newFileContent.append(insertData);
newFileContent.append(secondPart);
writeNewFileContent(newFileContent.toString());
}
}
Normally a new file would be created, but the following probably suffices (for non-gigabyte files). Mind the explicit encoding UTF-8; which you can ommit for the encoding of the operating system.
public static void insertInMidstOfFile(File file, String textToInsert)
throws IOException {
if (!file.exists()) {
throw new FileNotFoundException("File not found: " + file.getPath());
// Because file open mode "rw" would create it.
}
if (textToInsert.isEmpty()) {
return;
}
long fileLength = file.length();
long startPosition = fileLength / 2;
long remainingLength = fileLength - startPosition;
if (remainingLength > Integer.MAX_VALUE) {
throw new IllegalStateException("File too large");
}
byte[] bytesToInsert = textToInsert.getBytes(StandardCharsets.UTF_8);
try (RandomAccessFile fh = new RandomAccessFile(file, "rw")) {
fh.seek(startPosition);
byte[] remainder = new byte[(int)remainingLength];
fh.readFully(remainder);
fh.seek(startPosition);
fh.write(bytesToInsert);
fh.write(remainder);
}
}
Java 7 or higher.
Please tell me how to append data in docx file using java and docx4j.
What I'm doing is, I am using a template in docx format in which some field are dilled by java at run time,
My problem is for every group of data it creates a new file and i just want to append the new file into 1 file. and this is not done using java streams
String outputfilepath = "e:\\Practice/DOC/output/generatedLatterOUTPUT.docx";
String outputfilepath1 = "e:\\Practice/DOC/output/generatedLatterOUTPUT1.docx";
WordprocessingMLPackage wordMLPackage;
public void templetsubtitution(String name, String age, String gender, Document document)
throws Exception {
// input file name
String inputfilepath = "e:\\Practice/DOC/profile.docx";
// out put file name
// id of Xml file
String itemId1 = "{A5D3A327-5613-4B97-98A9-FF42A2BA0F74}".toLowerCase();
String itemId2 = "{A5D3A327-5613-4B97-98A9-FF42A2BA0F74}".toLowerCase();
String itemId3 = "{A5D3A327-5613-4B97-98A9-FF42A2BA0F74}".toLowerCase();
// Load the Package
if (inputfilepath.endsWith(".xml")) {
JAXBContext jc = Context.jcXmlPackage;
Unmarshaller u = jc.createUnmarshaller();
u.setEventHandler(new org.docx4j.jaxb.JaxbValidationEventHandler());
org.docx4j.xmlPackage.Package wmlPackageEl = (org.docx4j.xmlPackage.Package) ((JAXBElement) u
.unmarshal(new javax.xml.transform.stream.StreamSource(
new FileInputStream(inputfilepath)))).getValue();
org.docx4j.convert.in.FlatOpcXmlImporter xmlPackage = new org.docx4j.convert.in.FlatOpcXmlImporter(
wmlPackageEl);
wordMLPackage = (WordprocessingMLPackage) xmlPackage.get();
} else {
wordMLPackage = WordprocessingMLPackage
.load(new File(inputfilepath));
}
CustomXmlDataStoragePart customXmlDataStoragePart = wordMLPackage
.getCustomXmlDataStorageParts().get(itemId1);
// Get the contents
CustomXmlDataStorage customXmlDataStorage = customXmlDataStoragePart
.getData();
// Change its contents
((CustomXmlDataStorageImpl) customXmlDataStorage).setNodeValueAtXPath(
"/ns0:orderForm[1]/ns0:record[1]/ns0:name[1]", name,
"xmlns:ns0='EasyForm'");
customXmlDataStoragePart = wordMLPackage.getCustomXmlDataStorageParts()
.get(itemId2);
// Get the contents
customXmlDataStorage = customXmlDataStoragePart.getData();
// Change its contents
((CustomXmlDataStorageImpl) customXmlDataStorage).setNodeValueAtXPath(
"/ns0:orderForm[1]/ns0:record[1]/ns0:age[1]", age,
"xmlns:ns0='EasyForm'");
customXmlDataStoragePart = wordMLPackage.getCustomXmlDataStorageParts()
.get(itemId3);
// Get the contents
customXmlDataStorage = customXmlDataStoragePart.getData();
// Change its contents
((CustomXmlDataStorageImpl) customXmlDataStorage).setNodeValueAtXPath(
"/ns0:orderForm[1]/ns0:record[1]/ns0:gender[1]", gender,
"xmlns:ns0='EasyForm'");
// Apply the bindings
BindingHandler.applyBindings(wordMLPackage.getMainDocumentPart());
File f = new File(outputfilepath);
wordMLPackage.save(f);
FileInputStream fis = new FileInputStream(f);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
try {
for (int readNum; (readNum = fis.read(buf)) != -1;) {
bos.write(buf, 0, readNum);
}
// System.out.println( buf.length);
} catch (IOException ex) {
}
byte[] bytes = bos.toByteArray();
FileOutputStream file = new FileOutputStream(outputfilepath1, true);
DataOutputStream out = new DataOutputStream(file);
out.write(bytes);
out.flush();
out.close();
System.out.println("..done");
}
public static void main(String[] args) {
utility u = new utility();
u.templetsubtitution("aditya",24,mohan);
}
thanks in advance
If I understand you correctly, you're essentially talking about merging documents. There are two very simple approaches that you can use, and their effectiveness really depends on the structure and onward use of your data:
PhilippeAuriach describes one approach in his answer, which entails
appending all components within a MaindocumentPart instance to
another. In terms of the final docx file, this means the content
that appears in document.xml -- it won't take into account headers
and footers ( for example), but that may be fine for you.
You can insert multiple documents into a single docx file by inserting them
as AltChunk elements (see the docx4j documentation). This will
bring everything from one Word file into another, headers and all.
The downside of this is that your final document won't be a proper
flowing Word file until you open it and save it in MS Word itself
(the imported components remain as standalone files within the docx
bundle). This will cause you issues if you want to generated
'merged' files and then do something with them like render PDFs --
the merged content will simply be ignored.
The more complete (and complex) approach is to perform a "deep merge". This updates and maintains all references held within a document. Imported content becomes part of the main "flow" of the document (i.e. it is not stored as separate references), so the end result is a properly-merged file which can be rendered to PDF or whatever.
The downside to this is you need a good knowledge of docx structure and the API, and you will be writing a fair amount of code (I would recommend buying a license to Plutext's MergeDocx instead).
I had to deal with similar things, and here is what I did (probably not the most efficient, but working) :
create a finalDoc loading the template, and emptying it (so you have the styles in this doc)
for each data row, create a new doc loading the template, then replace your fields with your values
use the function below to append the doc filled with the datas to the finalDoc :
public static void append(WordprocessingMLPackage docDest, WordprocessingMLPackage docSource) {
List<Object> objects = docSource.getMainDocumentPart().getContent();
for(Object o : objects){
docDest.getMainDocumentPart().getContent().add(o);
}
}
Hope this helps.