I have a program where the user chooses a filepath that is getting passed as a string.
Now I have a function that should create a BufferedInputStream taking that string and assigning it to a InputStream.
try (final InputStream is = IOUtils.toInputStream(pathToFile) ) { ...
My problem here is that I am getting a ByteArrayInputStream instead of a "normal" BufferedInputStream. If I print the variable "is".
Is there a way to guarantee that it has to be a BufferedInputStream or can I cast to a BufferedInputStream?
I also tried this:
try (final InputStream is = new ByteArrayInputStream(pathToFile.getBytes(StandardCharsets.UTF_8)) ) {
But this didn't work.
Okay I dont know if that might be a workaround but:
try (final InputStream is = IOUtils.toInputStream(pathToFile) ) {
final InputStream xs = new BufferedInputStream(is);
Works for me. XS is a BufferedInputStream now.
you can get input stream as below
try(InputStream input = new BufferedInputStream(new FileInputStream(pathToFile)))
Related
is it possible to write/create an exe file in Java?
I can successfully read it but writing the exact same data that has been read to a new file seems to create some trouble because Windows tell's me it's not supported for my pc anymore.
This is the code I'm using to read the file where path is a String given with the actual path (it's in the .jar itself that's why I'm using ResourceAsStream()):
try {
InputStream inputStream = FileIO.class.getResourceAsStream(path);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
ArrayList<String> _final = new ArrayList<String>();
String line;
while ((line = reader.readLine()) != null) {
_final.add(line);
}
inputStream.close();
return _final.toArray(new String[_final.size()]);
}catch(Exception e) {
return null;
}
This is the code I'm using to write the file:
public static void writeFileArray(String path, String[] data) {
String filename = path;
try{
FileWriter fileWriter = new FileWriter(filename);
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
for(String d : data) {
bufferedWriter.write(d + "\n");
}
bufferedWriter.close();
}
catch(IOException ex){
System.out.println("FileIO failed to write file, IO exception");
}
}
So it doesn't give me any error's or something and the file size of the original .exe and the 'transferred' .exe stays the same, but it doesn't work anymore. Am I just doing it wrong? Did I forget something? Can u even do this with Java?
Btw I'm not that experienced with reading/writing files..
Thanks for considering my request.
I'm going to guess that you're using a Reader when you should be using a raw input stream. Use BufferedInputStream instead of BufferedReader.
BufferedInputStream in = new BufferedInputStream( inputStream );
The problem is that Reader interprets the binary as your local character set instead of the data you want.
Edit: if you need a bigger hint start with this. I just noticed you're using a BufferedWriter too, that won't work either.
try {
InputStream inputStream = FileIO.class.getResourceAsStream(path);
BufferedInputStream in = new BufferedInputStream( inputStream );
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] bytes = new byte[ 1024 ];
for( int length; ( length = ins.read( bytes ) ) != -1; )
bos.write( bytes, 0, length );
}
inputStream.close();
return bos;
When you are using Java 7 or newer, you should copy a resource to a file using
public static void copyResourceToFile(String resourcePath, String filePath) {
try(InputStream inputStream = FileIO.class.getResourceAsStream(resourcePath)) {
Files.copy(inputStream, Paths.get(filePath));
}
catch(IOException ex){
System.out.println("Copying failed. "+ex.getMessage());
}
}
This construct ensures correct closing of the resources even in the exceptional case and the JRE method ensures correct and efficient copying of the data.
It accepts additional options, e.g. to specify that the target file should be overwritten in case it already exists, you would use
public static void copyResourceToFile(String resourcePath, String filePath) {
try(InputStream inputStream = FileIO.class.getResourceAsStream(resourcePath)) {
Files.copy(inputStream, Paths.get(filePath), StandardCopyOption.REPLACE_EXISTING);
}
catch(IOException ex){
System.out.println("Copying failed. "+ex.getMessage());
}
}
You are using InputStreams for strings, .exe files are bytes!
Try using a ByteArrayInputStream and ByteArrayOutputStream.
Edit: completing with markspace's answer:
new BufferedInputStream(new ByteArrayInputStream( ... ) )
I have to use a method whose signature is like this
aMethod(FileInputStream);
I call that method like this
FileInputStream inputStream = new FileInputStream(someTextFile);
aMethod(inputStream);
I want to remove/edit some char which is being read from someTextFile before it being passed into aMethod(inputStream);
I cannot change aMethod's signature or overload it. And, it just take a InputStream.
If method taking a string as param, then I wouldn't be asking this question.
I am InputStream noob. Please advise.
you can convert a string into input stream
String str = "Converted stuff from reading the other inputfile and modifying it";
InputStream is = new ByteArrayInputStream(str.getBytes());
Here is something that might help. It will grab your .txt file. Then it will load it and go through line by line. You have to fill in the commented areas to do what you want.
public void parseFile() {
String inputLine;
String filename = "YOURFILE.txt";
Thread thisThread = Thread.currentThread();
ClassLoader loader = thisThread.getContextClassLoader();
InputStream is = loader.getResourceAsStream(filename);
try {
FileWriter fstream = new FileWriter("path/to/NEWFILE.txt");
BufferedWriter out = new BufferedWriter(fstream);
BufferedReader reader = new BufferedReader(
new InputStreamReader(is));
while((inputLine = reader.readLine()) != null) {
String[] str = inputLine.split("\t");
if(/* IF WHAT YOU WANT IS IN THE FILE ADD IT */) {
// DO SOMETHING OR ADD WHAT YOU WANT
out.append(str);
out.newLine();
}
}
reader.close();
out.close();
} catch (Exception e) {
e.getMessage();
}
}
Have you looked at another class FilterInputStream which also extends InputStream which may fit into your requirement?
From the documentation for the class
A FilterInputStream contains some other input stream, which it uses as its basic source of data, possibly transforming the data along the way or providing additional functionality.
Also have a look at this question which also seems to be similar to your question.
How can I convert InputStreamReader to InputStream? I have an InputStream which contains some string and byte data and I want to parse it. So I wrap my InputStream to BufferedReader. Then I read 3 lines from it. After that I want to get the rest of data(bytes) as is. But if I try to get it nothing happens.
Code snippet:
BufferedReader br = new BufferedReader(new InputStreamReader(is,"UTF-8"));
String endOfData = br.readLine();
String contentDisposition = br.readLine();
String contentType = br.readLine();
file = new File(filename);
if(file.exists()) file.delete();
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
byte[] data = new byte[8192];
int len = 0;
while (-1 != (len = is.read(data)) )
{
fos.write(data, 0, len);
Log.e("len", len+"");
}
fos.flush();
fos.close();
is.close();
The file is empty. If I don't wrap InputStream it works fine, but I need to read 3 lines and remove it.
Thanks.
If you want to mix text and byte data together, you should use OutputStream.writeUTF to write out those 3 lines, this way one single InputStream will be able to retrieve all the data that you need.
Take a look at commons-io's ReaderInputStream: it is a little heavy handed, but you can wrap the BufferedReader with that and read it as an input stream again.
It's pretty hard to mix byte and character input correctly, especially once you start throwing buffered readers / streams into the mix. I'd suggest that you either pick one and stick with it (converting your bytes to strings as necessary; care with the encoding!) or wrap the entire thing in a ZipOutputStream so you can have multiple logical "files" with different contents.
Is there any possible way to create FileInputStream with mark supported feature as true?
Wrap your Fileinputstream inside a BufferedInputStream.
The buffered streams support marks.
Wrap it in BufferedInputStream.
instead of
FileInputStream fis = new FileInputStream(...);
do this:
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(...));
and use bis instead of fis; nothing else should have to change in your code.
BufferedInputStreams are not magic. They will only support marking for as large as their underlying buffers and these buffers are going to take up memory. So if you go down this route its important that you understand the usage case and potentially call the BufferedInputStream constructor with the appropriatedly sized buffer. If the underlying file starts to get large and you mark far enough back then this technique may not work for you.
Try something like this
public FileInputStream fstream;
public DataInputStream in;
public BufferedInputStream bs;
public String path;
public void myExample() throws IOException{
path = "yourPath";
try {
fstream = new FileInputStream(path);
in = new DataInputStream(fstream);
bs = new BufferedInputStream(new InputStreamReader(in));
//do something
br.close(); //when do something is completed
} catch (FileNotFoundException ex) {
JOptionPane.showMessageDialog(null, "File not found");
}
}
I have this piece of code which I'm hoping will be able to tell me how much data I have downloaded (and soon put it in a progress bar), and then parse the results through my Sax Parser. If I comment out basically everything above the //xr.parse(new InputSource(request.getInputStream())); line and swap the xr.parse's over, it works fine. But at the moment, my Sax parser tells me I have nothing. Is it something to do with is.read (buffer) section?
Also, just as a note, request is a HttpURLConnection with various signatures.
/*Input stream to read from our connection*/
InputStream is = request.getInputStream();
/*we make a 2 Kb buffer to accelerate the download, instead of reading the file a byte at once*/
byte [ ] buffer = new byte [ 2048 ] ;
/*How many bytes do we have already downloaded*/
int totBytes,bytes,sumBytes = 0;
totBytes = request.getContentLength () ;
while ( true ) {
/*How many bytes we got*/
bytes = is.read (buffer);
/*If no more byte, we're done with the download*/
if ( bytes <= 0 ) break;
sumBytes+= bytes;
Log.v("XML", sumBytes + " of " + totBytes + " " + ( ( float ) sumBytes/ ( float ) totBytes ) *100 + "% done" );
}
/* Parse the xml-data from our URL. */
// OLD, and works if comment all the above
//xr.parse(new InputSource(request.getInputStream()));
xr.parse(new InputSource(is))
/* Parsing has finished. */;
Can anyone help me at all??
Kind regards,
Andy
'I could only find a way to do that
with bytes, unless you know another
method?'.
But you haven't found a method. You've just written code that doesn't work. And you don't want to save the input to a String either. You want to count the bytes while you're parsing them. Otherwise you're just adding latency, i.e. wasting time and slowing everything down. For an example of how to do it right, see javax.swing.ProgressMonitorInputStream. You don't have to use that but you certainly do have to use a FilterInputStream of some sort, probaby one you write yourself, that is wrapped around the request input stream and passed to the parser.
Your while loop is consuming the input stream and leaving nothing for the parser to read.
For what you're trying to do, you might want to look into implementing a FilterInputStream subclass wrapping the input stream.
You are building an InputStream over another InputStream that consumes its data before.
If you want to avoid reading just single bytes you could use a BufferedInputStream or different things like a BufferedReader.
In any case it's better to obtain the whole content before parsing it! Unless you need to dynamically parse it.
If you really want to keep it on like you are doing you should create two piped streams:
PipedOutputStream pipeOut = new PipedOutputStream();
PipedInputStream pipeIn = new PipedInputStream();
pipeIn.connect(pipeOut);
pipeOut.write(yourBytes);
xr.parse(pipeIn);
Streams in Java, like their name suggest you, doesn't have a precise dimension neither you know when they'll finish so whenever you create an InputStream, if you read from them you cannot then pass the same InputStream to another object because data is already being consumed from the former one.
If you want to do both things (downloading and parsing) together you have to hook between the data received from the HTTPUrlConncection you should:
first know the length of the data being downloaded, this can be obtained from HttpUrlConnection header
using a custom InputStream that decorates (this is how streams work in Java, see here) updading the progressbar..
Something like:
class MyInputStream extends InputStream
{
MyInputStream(InputStream is, int total)
{
this.total = total;
}
public int read()
{
stepProgress(1);
return super.read();
}
public int read(byte[] b)
{
int l = super.read(b);
stepProgress(l);
return l;
}
public int read(byte[] b, int off, int len)
{
int l = super.read(b, off, len);
stepProgress(l);
return l
}
}
InputStream mis= new MyInputStream(request.getInputStream(), length);
..
xr.parse(mis);
You can save your data in a file, and then read them out.
InputStream is = request.getInputStream();
if(is!=null){
File file = new File(path, "someFile.txt");
FileOutputStream os = new FileOutputStream(file);
buffer = new byte[2048];
bufferLength = 0;
while ((bufferLength = is.read(buffer)) > 0)
os.write(buffer, 0, bufferLength);
os.flush();
os.close();
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
FileInputStream fis = new FileInputStream(file);
xpp.setInput(new InputStreamReader(fis));
}