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.
Related
This question already has an answer here:
java reader vs. stream
(1 answer)
Closed 7 years ago.
I am going over input output section and there are so much classes and interfaces that I am confused a little bit.
As documentation says InputStream is a byte based stream whereas Reader is character-based stream. But as I understood correctly the only difference between them is that Reader reads two bytes per time instead of one byte at a time as InputStream does.
Therefore I don't understand is there any difference:
Using InputStream
byte[] bytes = new byte[2];
InputStream in = new FileInputStream("input.txt");
int bytesRead = in.read(bytes);
while(bytesRead != -1) {
doSomethingWithData(data);
bytesRead = inputstream.read(data);
}
Using Reader
Reader reader = new InputStreamReader(new FileInputStream("input.txt"));
int data = reader.read();
while (data != -1) {
doSomethingWithData(data);
data = reader.read();
}
I am really confusing about these aspects. Explain please in details. Thanks.
You can use a Reader to read text data. And it's supports some character encoding like - ISO, UTF-8. If you want to read a text file with some encoding then you can use Readers like - BufferedReader, StringReader etc.
And you can use Stream (InputStream, OutputStream) to manipulate binary data. For example you want to read a image file then you can use FileInputStream and when you want to save it to disk then you can use FileOutputStream.
Can someone explain to me why can I use FileInputStream or FileReader for a BufferedReader? What's the difference? And at the same time what is the advantage of a Scanner over a BufferedReader? I was reading that it helps by tokenizing, but what does that mean?
try {
//Simple reading of bytes
FileInputStream fileInputStream = new FileInputStream("path to file");
byte[] arr = new byte[1024];
int actualBytesRead = fileInputStream.read(arr, 0, arr.length);
//Can read characters and lines now
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
String lineRead = bufferedReader.readLine();
char [] charArrr = new char[1024];
int actulCharsRead = bufferedReader.read(charArrr, 0, charArrr.length);
//File reader allows reading of characters from a file
FileReader fileReader = new FileReader("path to file");
actulCharsRead = fileReader.read(charArrr, 0, charArrr.length);
//It is a good idea to wrap a bufferedReader around a fileReader
BufferedReader betterFileReader = new BufferedReader(new FileReader(""));
lineRead = betterFileReader.readLine();
actulCharsRead = betterFileReader.read(charArrr, 0, charArrr.length);
//allows reading int, long, short, byte, line etc. Scanner tends to be very slow
Scanner scanner = new Scanner("path to file");
//can also give inputStream as source
scanner = new Scanner(System.in);
long valueRead = scanner.nextLong();
//might wanna check out javadoc for more info
} catch (IOException e) {
e.printStackTrace();
}
Dexter's answer is already useful, but some extra explanation might still help:
In genereal:
An InputStream only provides access to byte data from a source.
A Reader can be wrapped around a stream and adds proper text encoding, so you can now read chars.
A BufferedReader can be wrapped around a Reader to buffer operations, so instead of 1 byte per call, it reads a bunch at once, thereby reducing system calls and improving performance in most cases.
For files:
A FileInputStream is the most basic way to read data from files.
If you do not want to handle text encoding on your own, you can wrap it into a InputStreamReader, which can be wrapped into a BufferedReader.
Alternatively, you can use a FilerReader, which should basically do the same thing as FileInputStream + InputStreamReader.
Now if you do not want to just read arbitrary text, but specific data types (int, long, double,...) or regular expressions, Scanner is quite useful. But as mentioned, it will add some overhead for building those expressions, so only use it when needed.
Introduced in Java 8 is Files.lines. This supports sufficient simple file manipulation to relieve at least some Perl envy :-)
Files.lines(Paths.get("input.txt"))
.filter(line -> line.startsWith("ERROR:"))
.map(String::toUpperCase).forEach(System.out::println);
I want to convert an input stream to byte array. I know I can use IOUtils from commons-io. But I am practicing some basics in java io. I read an xml file using BufferedReader and tried writing it to a ByteArrayOutputStream using BufferedWriter. But its not working.
When I write directly to the ByteArrayOutputStream its working. Whats wrong in my code?
try (InputStream inputStream = getClass().getResourceAsStream(
"/productInventory.xml");
ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(
new OutputStreamWriter(arrayOutputStream));
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(inputStream));) {
String line = "";
while ((line = bufferedReader.readLine()) != null) {
bufferedWriter.write(line);
}
System.out.println(arrayOutputStream.size());
} catch (IOException e) {
e.printStackTrace();
}
When I include below line in the loop its working
arrayOutputStream.write(line.getBytes(), 0, line.getBytes().length);
What is wrong while using BufferedWriter?
Nothing's wrong - it's just buffering! :D
The BufferedWriter works by filtering everything you send into it into a buffer - when the buffer is full, or when the writer is closed, or flushed, (It's a Closeable, so you should absolutely close it), it sends along those buffered characters to the underlying writer.
If you want to see the underlying writer update you have to either:
1) Fill up the buffer (default size is 8k in Java)
2) Call .flush()
3) Call .close()
4) As mentioned in comments, you can do a try-with-resources to make the close implicit:
try (BufferedWriter writer = new BufferedWriter(underlyingWriter)) {
// doStuff
}
For some reason, this code is changing any '\n' characters from the input and replacing it with '\n\r' in the new outputed file.
I reference a couple websites, and still haven't figured it out.. Anyone have an idea?
Thanks a lot!
Socket connectionSocket = sData.accept();
InputStream inputStream = connectionSocket.getInputStream();
BufferedInputStream inputBufferedStream = new BufferedInputStream(inputStream);
FileOutputStream outputStream = new FileOutputStream("/home/greg/1");
byte[] buffer = new byte[1024];
long count = 0;
int n = 0;
while ((n = inputBufferedStream.read(buffer))>=0) {
outputStream.write(buffer, 0, n);
count += n;
}
outputStream.close();
}
The particular code isn't doing that. Likely those \r\n were simply already in the input source.
It can only happen when you're reading it using for example BufferedReader#readLine() which eats the newlines and writing it using PrintWriter#println() which appends the platform default newlines. Probably the other side is doing that? After all, a Reader/Writer shouldn't be used for binary data. It may malform it. Use InputStream/OutputStream for it.
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));
}