Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I've tried many methods of reading files and I have found that none of them work. I am not using the default libraries. I'm using a framework that is found from here
I'm trying to read it and insert it line by line into a String array. Every method I've tried requires a Context, but because this is not initialized the same way as a default android application, it doesn't have a context to use getAssets. Is there any other way of reading a text file?
I tried using this set of code, but it didn't work because it required assets.
InputStream iS;
resources = AndroidGame.resources;
if (loadFromRawFolder) {
int rID = resources.getIdentifier("raw/store_app", "raw", "com.cciamlazy.pixunited");
iS = resources.openRawResource(rID);
} else {
iS = resources.getAssets().open(inFile);
}
byte[] buffer = new byte[iS.available()];
iS.read(buffer);
ByteArrayOutputStream oS = new ByteArrayOutputStream();
oS.write(buffer);
oS.close();
iS.close();
This code gives me errors and the resources != null. Gives me the error:
android.content.res.Resources$NotFoundException: Resource ID #0x0
Full class code
package com.cciamlazy.pixunited;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import android.app.Activity;
import android.content.res.Resources;
public class MapLoader extends Activity {
private static Resources resources;
public MapLoader() {
resources = getResources();
}
public static String LoadFile(String fileName, boolean loadFromRawFolder) throws IOException {
// Create a InputStream to read the file into
InputStream iS;
if (loadFromRawFolder) {
// get the resource id from the file name
// int rID = resources.getIdentifier(fileName, null, null);
int rID = resources.getIdentifier("raw/store_app", "raw",
"com.cciamlazy.activity");
// get the file as a stream
iS = resources.openRawResource(rID);
} else {
// get the file as a stream
iS = resources.getAssets().open(fileName);
}
// create a buffer that has the same size as the InputStream
byte[] buffer = new byte[iS.available()];
// read the text file as a stream, into the buffer
iS.read(buffer);
// create a output stream to write the buffer into
ByteArrayOutputStream oS = new ByteArrayOutputStream();
// write this buffer to the output stream
oS.write(buffer);
// Close the Input and Output streams
oS.close();
iS.close();
// return the output stream as a String
return oS.toString();
}
}
Hope this helps.....
add these two lines to your activity
private static Resources resources;
resources = getResources();
After that add this method.
public static String LoadFile(String fileName, boolean loadFromRawFolder)
throws IOException {
// Create a InputStream to read the file into
InputStream iS;
if (loadFromRawFolder) {
// get the resource id from the file name
// int rID = resources.getIdentifier(fileName, null, null);
int rID = resources.getIdentifier("raw/store_app", "raw",
"com.example.activity");
// get the file as a stream
iS = resources.openRawResource(rID);
} else {
// get the file as a stream
iS = resources.getAssets().open(fileName);
}
// create a buffer that has the same size as the InputStream
byte[] buffer = new byte[iS.available()];
// read the text file as a stream, into the buffer
iS.read(buffer);
// create a output stream to write the buffer into
ByteArrayOutputStream oS = new ByteArrayOutputStream();
// write this buffer to the output stream
oS.write(buffer);
// Close the Input and Output streams
oS.close();
iS.close();
// return the output stream as a String
return oS.toString();
}
Related
I've got a String array that contains the content for a downloadable file. I am converting it to a Stream for the download but there are some random values in the downloadfile. I don't know if it is due to the encoding and if yes, how can I change it?
var downloadButton = new DownloadLink(btn, "test.csv", () -> {
try {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
for (int i = 0; i < downloadContent.size(); i++) {
objectOutputStream.writeUTF(downloadContent.get(i));
}
objectOutputStream.flush();
objectOutputStream.close();
byte[] byteArray = byteArrayOutputStream.toByteArray();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArray);
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
objectInputStream.close();
return new ByteArrayInputStream(byteArray);
This is the DownloadLink class.
public class DownloadLink extends Anchor {
public DownloadLink(Button button, String fileName, InputStreamFactory fileProvider) {
super(new StreamResource(fileName, fileProvider), "");
getElement().setAttribute("download", fileName);
add(button);
getStyle().set("display", "contents");
}
}
this is the output file
ObjectOutputStream is part of the Java serialization system. In addition to the data itself, it also includes metadata about the original Java types and such. It's only intended for writing data that will later be read back using ObjectInputStream.
To create a file for others to download, you could instead use a PrintWriter that wraps the original output stream. On the other hand, you're using the output stream to create a byte[] which means that a more straightforward, but slightly less efficient, way would be to create a concatenated string from all the array elements and then use getBytes(StandardCharsets.UTF_8) on it to directly get a byte array.
Need to create a txt file by the available data and then need to send the file as rest response.
the app is deployed in container. i dont want to store it in any location on container or any location in spring boot resources. is there any way where we can create file at runtime buffer without giving any file location and then send it in rest response?
App is production app so i need a solution which is secure
A file is a file. You're using the wrong words - in java, the concept of a stream of data, at least for this kind of job, is called an InputStream or an OutputStream.
Whatever method you have that takes a File? That's the end of the road. A File is a file. You can't fake it. But, talk to the developers, or check for alternate methods, because there is absolutely no reason anything in java that does data processing requires a File. It should be requiring an InputStream or possibly a Reader. Or perhaps even there is a method that gives you an OutputStream or Writer. All of these things are fine - they are abstractions that lets you just send data to it, from a file, a network connection, or made up whole cloth, which is what you want.
Once you have one of those, it's trivial. For example:
String text = "The Text you wanted to store in a fake file";
byte[] data = text.getBytes(StandardCharsets.UTF_8);
ByteArrayInputStream in = new ByteArrayInputStream(data);
whateverSystemYouNeedToSendThisTo.send(in);
Or for example:
String text = "The Text you wanted to store in a fake file";
byte[] data = text.getBytes(StandardCharsets.UTF_8);
try (var out = whateverSystemYouNeedToSendThisTo.getOUtputStream()) {
out.write(data);
}
Take a look at the function below:
Imports
import com.google.common.io.Files;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import java.io.*;
import java.nio.file.Paths;
Function:
#GetMapping(value = "/getFile", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
private ResponseEntity<byte[]> getFile() throws IOException {
File tempDir = Files.createTempDir();
File file = Paths.get(tempDir.getAbsolutePath(), "fileName.txt").toFile();
String data = "Some data"; //
try (FileWriter fileWriter = new FileWriter(file)) {
fileWriter.append(data).flush();
} catch (Exception ex) {
ex.printStackTrace();
}
byte[] zippedData = toByteArray(new FileInputStream(file));
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentDisposition(ContentDisposition.builder("attachment").filename("file.txt").build());
httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
httpHeaders.setContentLength(zippedData.length);
return ResponseEntity.ok().headers(httpHeaders).body(zippedData);
}
public static byte[] toByteArray(InputStream in) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] buffer = new byte[in.available()];
int len;
// read bytes from the input stream and store them in buffer
while ((len = in.read(buffer)) != -1) {
// write bytes from the buffer into output stream
os.write(buffer, 0, len);
}
return os.toByteArray();
}
In a nutshell, you want to store data in memory. Basic building block for this is array of bytes - byte[].
In JDK there are two classes to connect IO world with byte array - ByteArrayInputStream and ByteArrayOutputStream.
Rest is just same, as when dealing with files.
Example 1
#GetMapping(value = "/image")
public #ResponseBody byte[] getImage() throws IOException {
InputStream in = getClass()
.getResourceAsStream("/com/baeldung/produceimage/image.jpg");
return IOUtils.toByteArray(in);
}
Example 2:
#GetMapping("/get-image-dynamic-type")
#ResponseBody
public ResponseEntity<InputStreamResource> getImageDynamicType(#RequestParam("jpg") boolean jpg) {
MediaType contentType = jpg ? MediaType.IMAGE_JPEG : MediaType.IMAGE_PNG;
InputStream in = jpg ?
getClass().getResourceAsStream("/com/baeldung/produceimage/image.jpg") :
getClass().getResourceAsStream("/com/baeldung/produceimage/image.png");
return ResponseEntity.ok()
.contentType(contentType)
.body(new InputStreamResource(in));
}
Ref: https://www.baeldung.com/spring-controller-return-image-file
I need to create a test where I need to pass an InputStream as input which would be a zipfile. Is there a way we can create InputStream directly instead creating in memory / local file copies so that stream can be used for testing.
If I understand your question correctly you want to create a ZIP file in-memory (i.e. not on disk) from hard-coded data. This is certainly possible using the following classes:
java.io.ByteArrayInputStream
java.io.ByteArrayOutputStream
java.util.zip.ZipOutputStream
java.util.zip.ZipEntry
Here's an example:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class Main {
public static void main(String[] args) throws IOException {
// Destination of the ZIP file (an in-memory byte array)
ByteArrayOutputStream boas = new ByteArrayOutputStream();
/*
* Write the ZIP file. This creates a single entry named "file.txt"
* with "Hello, World!" as its contents.
*/
try (ZipOutputStream zos = new ZipOutputStream(boas)) {
zos.putNextEntry(new ZipEntry("file.txt"));
zos.write("Hello, World!".getBytes());
zos.closeEntry();
}
// Create an InputStream to read the raw bytes of the ZIP file
ByteArrayInputStream bois = new ByteArrayInputStream(boas.toByteArray());
/*
* The following writes the ZIP file to disk, specifically to a file named "test.zip"
* in the working directory. The purpose of this is to allow you to run the code
* and see a tangible result (i.e. lets you inspect the resulting ZIP file). Obviously
* you would not do this in your own code since you want to avoid writing the ZIP file
* to disk.
*
* Note: Will fail if the file already exists.
*/
Files.copy(bois, Path.of("test.zip"));
}
}
Elaborating on some of the answers found above let me describe a situation I encountered and how I solved it. I encountered a situation where I receive files that are PGP encrypted (.pgp, .asc etc) so I had to decrypt the file (.txt) itself be passing it into a stream reader to parse the line entries. Instead of saving the decrypted file as temporarily file in the file system before reading it in to parse the entries. I did it in memory as follows.
I had a function which pipes the InputStream into a ByteArrayOutputStream (instead of FileOutputStream, retrieve the byte array and initialize it as ByteArrayInputStream and printed out each entry with a reader
InputStream encFileIn = new FileInputStream("some_encrypted_file.asc");
byte[] decryptFile = util.decryptFile(encFileIn);
BufferedReader reader = new BufferedReader(new InputStreamReader(
new ByteArrayInputStream(decryptFile), StandardCharsets.UTF_8));
reader.lines().forEach(f -> System.out.println(f));
Here are some code snippets on piping the InputStream inside my decrypt function which may not be applicable to you as I am working with PGP files. So you maybe try to directly instantiate a ByteArrayInputStream as is
public static void pipeAll(InputStream inStr, OutputStream outStr)
throws IOException
{
byte[] bs = new byte[BUFFER_SIZE];
int numRead;
while ((numRead = inStr.read(bs, 0, bs.length)) >= 0)
{
outStr.write(bs, 0, numRead);
}
}
public static byte[] readAll(InputStream inStr)
throws IOException
{
ByteArrayOutputStream buf = new ByteArrayOutputStream();
pipeAll(inStr, buf);
return buf.toByteArray();
}
Under my Spring 4.3/Maven 3.3 project I have an image file, a PNG file, at:
src/main/resources/images/account.png
I have a util java application file that reads in an image, and it writes it to the database field. The code is as follows:
private static String _accountFilename = "src/main/resources/images/account.png";
private byte[] getByteArrayFromFile(String filename)
{
FileInputStream fileInputStream = null;
File file = new File(filename);
byte[] bFile = new byte[(int) file.length()];
try
{
// convert file into array of bytes
fileInputStream = new FileInputStream(file);
fileInputStream.read(bFile);
fileInputStream.close();
for (int i = 0; i < bFile.length; i++)
{
System.out.print((char) bFile[i]);
}
System.out.println("Done");
}
catch (Exception e)
{
e.printStackTrace();
}
return bFile;
}
public String getImageData(byte[] imageByteArray)
{
Base64.Encoder encoder = Base64.getEncoder();
String base64 = encoder.encodeToString(imageByteArray);
base64 = "data:image/png;base64," + base64;
return base64;
}
The String that comes back from "getImageData" works great. I can put that String in the MySQL database, in a table, and the field is defined as TEXT.
I can pull that base64 encoded data back, and display the image.
Now, If I am calling this code from a Spring Service instead of an application, then the image "src/main/resources/images/account.png" is not found.
After researching on the Net for some time, there are many, many examples of getting a file from "resources" and many of these did not work for me. Since I am in Spring, I tried a few things and finally this worked:
#Value(value = "classpath:images/account.png")
private Resource defaultAccountImage;
private byte[] getByteArrayFromFile(Resource image)
{
InputStream inputStream = null;
byte[] bFile = null;
try
{
bFile = new byte[(int) image.contentLength()];
// convert file into array of bytes
inputStream = image.getInputStream();
inputStream.read(bFile);
inputStream.close();
for (int i = 0; i < bFile.length; i++)
{
System.out.print((char) bFile[i]);
}
System.out.println("Done");
}
catch (Exception e)
{
e.printStackTrace();
}
return bFile;
}
private String getImageData(byte[] imageByteArray)
{
Base64.Encoder encoder = Base64.getEncoder();
String base64 = encoder.encodeToString(imageByteArray);
base64 = "data:image/png;base64," + base64;
return base64;
}
public String getDefaultAccountImage()
{
byte[] accountImage = getByteArrayFromFile(defaultAccountImage);
String fileString = getImageData(accountImage);
return fileString;
}
When I look at the String/Image data between the first way with the standalone java app, and the second way with the #Value and inputstream, there is a definite different in the string data.
part of the string data is similar, but then it drastically changes, and they don't match. As a result the text data for the image from the second method doesn't display as an image.
So, I was hoping I could get this image text data, and it would be the same, but it is not. If I can use my web-service, which calls the business service which calls this ImageUtil code where I use the #Value to get the image resource and it saves the text string correctly, that would be great.
If you have any advice, I would very much appreciate it. Thanks!
UPDATE 1:
This is a multi-maven project:
parent-project
entity
dao
service
ws
When I run my test code within the Service layer, the suggested solution works great! The images are found and the byte string gets loaded as it should be. And then I compiled the code into a jar.
The entity.jar gets created first.
The dao.jar gets created and pulls in the entity.jar.
The service.jar gets created and pulls in the dao.jar. This layer also has the /resources/images/account.png file. But this image is now in the jar.
The ws.WAR file pulls in the service.jar file ...
so the code in the answer does not find the image in the resources.
When I run the tests from the ws layer, I get a FileNotFoundException.
So ... now I am researching on how to get an image from jar ...
Does this change how I should be getting my image byte array?
You can get the file from the Resource, and proceed like the first example which works. Seems redundant, but if you can get the file, then you can test a number of things:
Write the file to disk and check the content
Write the file to disk and compare the sizes, etc.
import java.io.File;
import java.io.FileInputStream;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
#Value(value = "classpath:images/account.png")
private Resource defaultAccountImage;
private byte[] getByteArrayFromFile(Resource image) {
FileInputStream fileInputStream = null;
byte[] bFile = null;
try {
File file = image.getFile();
bFile = new byte[(int) file.length()];
// convert file into array of bytes
fileInputStream = new FileInputStream(file);
fileInputStream.read(bFile);
fileInputStream.close();
for (int i = 0; i < bFile.length; i++) {
System.out.print((char) bFile[i]);
}
System.out.println("Done");
} catch (Exception e) {
e.printStackTrace();
}
return bFile;
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
How can we read or use the contents of outputstream.
In my case, I am using a method having signature.
public static OutputStream decryptAsStream(InputStream inputStream,
String encryptionKey)
This method return OutputStream. I want get OutputStream to String.
Is it possible to pipe the output from an java.io.OutputStream to a String in Java?
How can we read or use the contents of outputstream.
In general you can't. An OutputStream is an object that you write bytes to. The general API doesn't provide any way to get the bytes back.
There are specific kinds of output stream that would allow you to get the bytes back. For instance:
A ByteArrayOutputStream has a method for getting the byte array contents.
A PipeOutputStream has a corresponding PipeInputStream that you can read from.
If you use a FileOutputStream to write to file, you can typically open a FileInputStream to read the file contents ... provided you know the file pathname.
Looking at that method, it strikes me that the method signature is wrong for what you are trying to do. If the purpose is to provide an encrypter for a stream, then the method should return an InputStream. If the purpose is to write the encrypted data somewhere, then the method should return void and take an extra parameter that is the OutputStream that the method should write to. (And then the caller can use an OutputStream subclass to capture the encrypted data ... if that is what is desired.)
Another alternative that would "work" is to change the method's signature to make the return type ByteArrayOutputStream (or a file name). But that is not a good solution because it takes away the caller's ability to decide where the encrypted output should be sent.
UPDATE
Regarding your solution
OutputStream os = AESHelper.decryptAsStream(sourceFile, encryptionKey);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos = (ByteArrayOutputStream) os;
byte[] imageBytes = baos.toByteArray();
response.setContentType("image/jpeg");
response.setContentLength(imageBytes.length);
OutputStream outs = response.getOutputStream();
outs.write(imageBytes);
That could work, but it is poor code:
If AESHelper.decryptAsStream is a method that you wrote (and it looks like it is!), then you should declare it as returning a ByteArrayOutputStream.
If it is already declared as returning a ByteArrayOutputStream you should assign it directly to baos.
Either way, you should NOT initialize baos to a newly created ByteArrayOutputStream instance that immediately gets thrown away.
It is also worth noting that the Content-Type is incorrect. If you sent that response to a browser, it would attempt to interpret the encrypted data as an image ... and fail. In theory you could set a Content-Encoding header ... but there isn't one that is going to work. So the best solution is to send the Content-Type as "application/octet-stream".
You can do something like following :
OutputStream output = new OutputStream()
{
private StringBuilder string = new StringBuilder();
#Override
public void write(int x) throws IOException {
this.string.append((char) x );
}
public String toString(){
return this.string.toString();
}
};
Mainly you can use outputstreams to send the file contents as #The New Idiot mentioned. .pdf files, zip file, image files etc.
In such scenarios, get the output stream of your servlet and to that write the contentes
OutputStream outStream = response.getOutputStream();
FileInputSteram fis = new FileInputStream(new File("abc.pdf));
byte[] buf = new byte[4096];
int len = -1;
while ((len = fis.read(buf)) != -1) {
outStream .write(buf, 0, len);
}
response.setContentType("application/octect");(if type is binary) else
response.setContentType("text/html");
outStream .flush();
outStream.close();
If you got the OutputStream from the response , you can write the contents of the OutputStream to the response which will be sent back to the browser . Sample code :
OutputStream outStream = response.getOutputStream();
response..setHeader("Content-Disposition", "attachment; filename=datafile.xls");
response.setContentType("application/vnd.ms-excel");
byte[] buf = new byte[4096];
int len = -1;
while ((len = inStream.read(buf)) != -1) {
outStream.write(buf, 0, len);
}
outStream.flush();
outStream.close();
Read this : Content-Disposition:What are the differences between “inline” and “attachment”?
In your case the method definition is :
public static OutputStream decryptAsStream(InputStream inputStream,
String encryptionKey)
So you can get the OutputStream from that method as :
OutputStream os = ClassName.decryptAsStream(inputStream,encryptionKey);
And then use the os .