Hello im trying to do something like this:
private Byte[] getImage() throws IOException {
String imageUrl = ServletContext.class.getClassLoader()
.getResource("static/anImage.jpg")
.getFile();
Byte[] byteObject = new Byte[imageUrl.getBytes().length];
int i = 0;
for (Byte b : imageUrl.getBytes()){
byteObject[i++] = b;
}
return byteObject;
}
But it's wrong. So how to pick up a file from specific directory? Thanks.
ps.
I can do something like this:
File file = new File("image.jpg");
byte[] content = Files.readAllBytes(file.toPath());
But still its a path only from the main folder. Dont know how to program for the resources/images folder.
In Spring you can use Resources to achieve your goal:
Resource resource = new ClassPathResource("static/anImage.jpg");
byte[] bytes = resource.getInputStream().readAllBytes();
Don't reinvent the wheel and use e.g. Apache Commons for convert a File to byte array. Read more FileUtils.readFileToByteArray(File input)
The way you loading resources seems to be the proper one.
Ensure that the loaded file is in proper location (src/main/resources).
Do you have any particular error or stack trace which describes the issue.
Related
I'm trying something new,
There is an application who send data to a memory-mapped file located at Local\MemFileName
I would like to read it in java,
I tried some tutorials like https://www.baeldung.com/java-mapped-byte-buffer, https://howtodoinjava.com/java7/nio/memory-mapped-files-mappedbytebuffer/
But all seem to read a file in JVM, or I did not understand...
How can I read the content of the file Located in windows system Local\MemFileName
Thanks!
Following: Example code of what i tried
public class Main {
private static final String IRSDKMEM_MAP_FILE_NAME = StringEscapeUtils.unescapeJava("Local\\IRSDKMemMapFileName");
private static final String IRSDKDATA_VALID_EVENT = StringEscapeUtils.unescapeJava("Local\\IRSDKDataValidEvent");
public static final CharSequence charSequence = "Local\\IRSDKMemMapFileName";
public static void main(String[] args) throws IOException, InterruptedException {
System.out.println(charSequence);
try (RandomAccessFile file = new RandomAccessFile(new File(IRSDKMEM_MAP_FILE_NAME), "r")) {
//Get file channel in read-only mode
FileChannel fileChannel = file.getChannel();
//Get direct byte buffer access using channel.map() operation
MappedByteBuffer buffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size());
// the buffer now reads the file as if it were loaded in memory.
System.out.println("Loaded " + buffer.isLoaded()); //prints false
System.out.println("capacity" + buffer.capacity()); //Get the size based on content size of file
//You can read the file from this buffer the way you like.
for (int i = 0; i < buffer.limit(); i++) {
System.out.println((char) buffer.get()); //Print the content of file
}
}
}
}
To read a memory mapped file:
Open a FileChannel on the file using FileChannel.open.
Invoke the map method on the FileChannel to create a MappedByteBuffer covering the area of the file you want to read.
Read the data from the MappedByteBuffer.
The solution for me was to use a WindowsService.class implementing methods from JNA library, as you can see:
My Library
With this I could open a file mapped in Windows system.
All the previous answers was correct for a file accessible from JVM, but from outside the JVM it was impossible.
Thanks !
I have a spring boot application and I am trying to merge two pdf files. The one I am getting as a byte array from another service and the one I have it locally in my resources file: /static/documents/my-file.pdf. This is the code of how I am getting byte array from my file from resources:
public static byte[] getMyPdfContentForLocale(final Locale locale) {
byte[] result = new byte[0];
try {
final File myFile = new ClassPathResource(TEMPLATES.get(locale)).getFile();
final Path filePath = Paths.get(myFile.getPath());
result = Files.readAllBytes(filePath);
} catch (IOException e) {
LOGGER.error(format("Failed to get document for local %s", locale), e);
}
return result;
}
I am getting the file and getting the byte array. Later I am trying to merge this two files with the following code:
PDFMergerUtility pdfMergerUtility = new PDFMergerUtility();
pdfMergerUtility.addSource(new ByteArrayInputStream(offerDocument));
pdfMergerUtility.addSource(new ByteArrayInputStream(merkblattDocument));
ByteArrayOutputStream os = new ByteArrayOutputStream();
pdfMergerUtility.setDestinationStream(os);
pdfMergerUtility.mergeDocuments(null);
os.toByteArray();
But unfortunately it throws an error:
throw new IOException("Page tree root must be a dictionary");
I have checked and it makes this validation before it throws it:
if (!(root.getDictionaryObject(COSName.PAGES) instanceof COSDictionary))
{
throw new IOException("Page tree root must be a dictionary");
}
And I really have no idea what does this mean and how to fix it.
The strangest thing is that I have created totally new project and tried the same code to merge two documents (the same documents) and it works!
Additionally what I have tried is:
Change the spring boot version if it is ok
Set the mergeDocuments method like this: pdfMergerUtility.mergeDocuments(setupMainMemoryOnly())
Set the mergeDocuments method like this: pdfMergerUtility.mergeDocuments(setupTempFileOnly())
Get the bytes with a different method not using the Files from java.nio:
And also executed this in a different thread
Merging files only locally stored (in resources)
Merging the file that I am getting from another service - this works btw and that is why I am sure he is ok
Can anyone help with this?
The issue as Tilman Hausherr said is in that resource filtering that you can find in your pom file. If you have a case where you are not allowed to modify this then this approach will help you:
final String path = new
ClassPathResource(TEMPLATES.get(locale)).getFile().getAbsolutePath();
final File file = new File(path);
final Path filePath = Paths.get(file.getPath());
result = Files.readAllBytes(filePath);
and then just pass the bytes to the pdfMergerUtility object (or even the whole file instead of the list of bytes).
I have the following file, which contains a binary representation of an .MSG file :
binaryMessage.txt
And I put it in my Eclipse workspace, in the following folder - src/main/resources/test :
I want to use the string which is within this text file , within the following JUnit code, so I tried the following way :
request.setContent("src/main/resources/test/binaryMessage");
mockMvc.perform(post(EmailController.PATH__METADATA_EXTRACTION_OPERATION)
.contentType(MediaType.APPLICATION_JSON)
.content(json(request)))
.andExpect(status().is2xxSuccessful());
}
But this doesn't work. Is there a way I can pass in the string the file directly without using IO code ?
You can't read a file without using IO code (or libraries that use IO code). That said, it's not that difficult to read the file into memory so you can send it.
To read a binary file into a byte[] you can use this method:
private byte[] readToByteArray(InputStream is) throws IOException {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
return baos.toByteArray();
} finally {
if (is != null) {
is.close();
}
}
}
Then you can do
request.setContent(readToByteArray(getClass().getResourceAsStream("test/binaryMessage")));
In addition to my comment on Samuel's answer, I just noticed that you depend on your concrete execution directory. I personally don't like that and normally use the class loader's functions to find resources.
Thus, to be independent of your working directory, you can use
getClass().getResource("/test/binaryMessage")
Convert this to URI and Path, then use Files.readAllBytes to fetch the contents:
Path resourcePath = Paths.get(getClass().getResource("/test/binaryMessage").toURI());
byte[] content = Files.readAllBytes(resourcePath);
... or even roll that into a single expression.
But to get back to your original question: no, this is I/O code, and you need it. But since the dawn of Java 7 (in 2011!) this does not need to be painful anymore.
I need to parse a java file (actually a .pdf) to an String and go back to a file. Between those process I'll apply some patches to the given string, but this is not important in this case.
I've developed the following JUnit test case:
String f1String=FileUtils.readFileToString(f1);
File temp=File.createTempFile("deleteme", "deleteme");
FileUtils.writeStringToFile(temp, f1String);
assertTrue(FileUtils.contentEquals(f1, temp));
This test converts a file to a string and writtes it back. However the test is failing.
I think it may be because of the encodings, but in FileUtils there is no much detailed info about this.
Anyone can help?
Thanks!
Added for further undestanding:
Why I need this?
I have very large pdfs in one machine, that are replicated in another one. The first one is in charge of creating those pdfs. Due to the low connectivity of the second machine and the big size of pdfs, I don't want to synch the whole pdfs, but only the changes done.
To create patches/apply them, I'm using the google library DiffMatchPatch. This library creates patches between two string. So I need to load a pdf to an string, apply a generated patch, and put it back to a file.
A PDF is not a text file. Decoding (into Java characters) and re-encoding of binary files that are not encoded text is asymmetrical. For example, if the input bytestream is invalid for the current encoding, you can be assured that it won't re-encode correctly. In short - don't do that. Use readFileToByteArray and writeByteArrayToFile instead.
Just a few thoughts:
There might actually some BOM (byte order mark) bytes in one of the files that either gets stripped when reading or added during writing. Is there a difference in the file size (if it is the BOM the difference should be 2 or 3 bytes)?
The line breaks might not match, depending which system the files are created on, i.e. one might have CR LF while the other only has LF or CR. (1 byte difference per line break)
According to the JavaDoc both methods should use the default encoding of the JVM, which should be the same for both operations. However, try and test with an explicitly set encoding (JVM's default encoding would be queried using System.getProperty("file.encoding")).
Ed Staub awnser points why my solution is not working and he suggested using bytes instead of Strings. In my case I need an String, so the final working solution I've found is the following:
#Test
public void testFileRWAsArray() throws IOException{
String f1String="";
byte[] bytes=FileUtils.readFileToByteArray(f1);
for(byte b:bytes){
f1String=f1String+((char)b);
}
File temp=File.createTempFile("deleteme", "deleteme");
byte[] newBytes=new byte[f1String.length()];
for(int i=0; i<f1String.length(); ++i){
char c=f1String.charAt(i);
newBytes[i]= (byte)c;
}
FileUtils.writeByteArrayToFile(temp, newBytes);
assertTrue(FileUtils.contentEquals(f1, temp));
}
By using a cast between byte-char, I have the symmetry on conversion.
Thank you all!
Try this code...
public static String fetchBase64binaryEncodedString(String path) {
File inboundDoc = new File(path);
byte[] pdfData;
try {
pdfData = FileUtils.readFileToByteArray(inboundDoc);
} catch (IOException e) {
throw new RuntimeException(e);
}
byte[] encodedPdfData = Base64.encodeBase64(pdfData);
String attachment = new String(encodedPdfData);
return attachment;
}
//How to decode it
public void testConversionPDFtoBase64() throws IOException
{
String path = "C:/Documents and Settings/kantab/Desktop/GTR_SDR/MSDOC.pdf";
File origFile = new File(path);
String encodedString = CreditOneMLParserUtil.fetchBase64binaryEncodedString(path);
//now decode it
byte[] decodeData = Base64.decodeBase64(encodedString.getBytes());
String decodedString = new String(decodeData);
//or actually give the path to pdf file.
File decodedfile = File.createTempFile("DECODED", ".pdf");
FileUtils.writeByteArrayToFile(decodedfile,decodeData);
Assert.assertTrue(FileUtils.contentEquals(origFile, decodedfile));
// Frame frame = new Frame("PDF Viewer");
// frame.setLayout(new BorderLayout());
}
I'm trying to generate a PDF document using FOP. The pdf generation code is kept in a servlet and the xsl is in a specific folder in the WebContent folder.
How can I access this xsl file by giving a relative path? It works only if I give the complete path in the File object.
I need to generate the xml content dynamically. How can I give this dynamically generated xml as the source instead of a File object?
Please provide your suggestions.
To get the path you can just do:
String path = s.getServletContext().getRealPath("/WEB-INF/somedir/hdfeeh");
s is the class that implements HTTPServlet.You can also use this.getServletContext() if its your servlet class.
Then pass this as a parameter.
As far as using dynamically generated XML, the library you're using should support using an input stream, write your XML, convert it to a byte array, then wrap it in a ByteArrayInputStream and use this.
For a direct and independent container implementation, you can access the resourcewith the following method getResource() inside your servlet:
/start servlet/
public InputStream getResource(String resourcePath) {
ServletContext servletContext = getServletContext();
InputStream openStream = servletContext.getResourceAsStream( resourcePath );
return openStream;
}
public void testConsume() {
String path = "WEB-INF/teste.log";
InputStream openStream = getResource( path );
int c = -1;
byte[] bb = new byte[1024];
while ( -1 != ( c = openStream.read( bb ) ) ) {
/* consume stream */
}
openStream.close();
}
/end servlet/
I used the following method to read the file under web content
BufferedReader reader = new BufferedReader(new InputStreamReader(request.getSession().getServletContext().getResourceAsStream("/json/sampleJson.json")));
Now all the file content is available in the reader object.