What's the difference between using a BufferedReader and a BufferedInputStream?
A BufferedReader is used for reading character data. A BufferedOutputStream is used for writing binary data.
Any classes inheriting from Reader or Writer deal with 16-bit unicode character data, whereas classes inherting from InputStream or OutputStream are concerned with processing binary data. The classes InputStreamReader and OutputStreamWriter can be used to bridge between the two classes of data.
Bufferedreader reads data from a file as a string. BufferedOutputStream writes to a file in bytes. BufferedInputStream reads data in bytes
Sample to Bufferedreader:
try {
BufferedReader br = new BufferedReader(new FileReader(new File(your_file));
while ((thisLine = br.readLine()) != null) {
System.out.println(thisLine);
}
}
Sample to BufferedOutputStream:
//Construct the BufferedOutputStream object
bufferedOutput = new BufferedOutputStream(new FileOutputStream(filename));
//Start writing to the output stream
bufferedOutput.write("Line 1".getBytes());
bufferedOutput.write("\r\n".getBytes());
bufferedOutput.write("Line 2".getBytes());
bufferedOutput.write("\r\n".getBytes());
Bufferedinputstream reads in byte:
Sample
:
//Construct the BufferedInputStream object
bufferedInput = new BufferedInputStream(new FileInputStream(filename));
int bytesRead = 0;
while ((bytesRead = bufferedInput.read(buffer)) != -1) {
String chunk = new String(buffer, 0, bytesRead);
System.out.print(chunk);
}
As the names imply, one is for reading data, and the other is for outputting data.
Related
How to read an InputStream twice if I am using ReadableByteChannel and BufferedReader?
Here is my code:
ReadableByteChannel inputChannel = Channels.newChannel(input);
WritableByteChannel outputChannel = Channels.newChannel(output);
InputStream ind = Channels.newInputStream(inputChannel);
ReadableByteChannel inputChannel1 = Channels.newChannel(ind);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
org.apache.commons.io.IOUtils.copy(ind, baos);
ByteBuffer buffer = ByteBuffer.allocateDirect(10240);
long size = 0;
while (inputChannel1.read(buffer) != -1) {
buffer.flip();
size += outputChannel.write(buffer);
buffer.clear();
}
byte[] bytes = baos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
BufferedReader in = new BufferedReader(new InputStreamReader(bais));
String inputLine;
StringBuffer bufferResponse = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
bufferResponse.append(inputLine);
}
JSONObject jsonResponse = new JSONObject(bufferResponse.toString());
You've written a lot of code to copy input to two destinations: output and jsonResponse. As you have made an in-memory copy of input => bytes there is no need to scan input twice, and you don't need to use IOUtils for a simple copy to byte[] which you can re-use to send to the two destinations:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
input.transferTo(baos);
byte[] bytes = baos.toByteArray();
output.write(bytes);
Then do as #g00se suggests - if the char encoding is platform default:
String s = new String(bytes /*, or insert another charset here */);
JSONObject jsonResponse = new JSONObject(s);
You should also deal with closing the input/output streams, best done with try-with-resources block.
I write some file transfer application. Between client and server i send 3 type of data:
1) Some "command words" like READY_FOR_UPLOAD.
2) Some serializable data
3) Big files in byte array.
I get client connections on server socket and create new Thread for every client.
try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),true);
InputStream inputStream = clientSocket.getInputStream();
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream)) {}
I create these streams using try with resources and there is no problem.
I use:
1) "in" for read messages from client:
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
2)"out" for send messages.
3)"inputStream" for receive files:
try (FileOutputStream fileOutputStream = new
FileOutputStream("D:\\testDownload.zip");
BufferedOutputStream bufferedOutputStream = new
BufferedOutputStream(fileOutputStream)
) {
byte[] buffer = new byte[1024 * 100];
int read;
while ((read = inputStream.read(buffer)) != -1) {
bufferedOutputStream.write(buffer, 0, read);
}
}
4) "objectInputStream" for serializable data:
Object object;
if ((object = objectInputStream.readObject()) != null) {
if (object instanceof File) {
File file = (File) object;
System.out.println(file.getAbsolutePath());
System.out.println(file.length());
}
}
While i use them separately - there is no problem. But i need read "command word" first of all i.e. in start of the method run of my tread.
public void run() {
try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),true);
InputStream inputStream = clientSocket.getInputStream();
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream)) {
String line;
if ((line = in.readLine()) != null) {
System.out.println(line);
there i should try to read other types of data
}
}
And if this is no "command word" i can try read serializable data or file data. But this is a problem! I may try to read a line but it can be part of serializable data of file data and because inputsream readed "one-by-one" byte method, i can't try read it like serializable or file data, because input not whole anymore, i read some data in "readLine()". I should know what type of data i receive before i try to read it. How can it be done?
You need to create a protocol - rules how client and server exchange information between them.
When you write data you specify what data type you are sending and its size. And don't use ObjectInputStream and ObjectOutputStream on Socket - convert the data into array of bytes, so that you know what the size is when you writing and then convert them back. Send the data as bytes.
As the title suggests, is there any way to read a binary representation of a given file (.txt, .docx, .exe, etc...) in Java (or any other language)?
In java, I know how to read the content of a file as is, i.e:
String line;
BufferedReader br = new BufferedReader(new FileReader("myFile.txt"));
while ((line = br.readLine()) != null) {
System.out.println(line);
}
But I'm not sure (if it's possible) to read a binary representation of the file itself.
File file = new File(filePath);
byte[] bytes = new byte[(int)file.length()];
DataInputStream dataInputStream = new DataInputStream(new BufferedInputStream(new FileInputStream(filePath)));
dataInputStream.readFully(bytes);
dataInputStream.close();
bytes is a byte array with all of the data of the file in it
recently i had troubles working with InputStreams and OutputStreams when i was trying to implement a basic file downloader in my android application.. to elaborate things this is how i did it..
i get an InputStream object using the apache HttpClient classes then tried writing the stream to a file.. but strangely when i buffer the InputStream or the OutputStream i get an unreadable file.... this is the code..
//to make the code concise i removed exceptions and stream closing..
private void download(InputStream in,String fileName){
//if i dont use the buffered thing and read directly from in everything is ok
// same is the buffered out i had to use in/outstream
BufferedInputStream bufferedIn = new BufferedInputStream(in);
FileOutputStream fout = new FileOutputStream(new File(fileName));
BufferedOutputstream bufferedOut = new BufferedOutputstream(fout);
int read = -1;
while((read = bufferedIn.read()) != -1){
bufferedOut.write(read);
}
//close the buffers
}
You have to flush the buffered outputstream when you're done with it.
In any case you probably want to flush() your output (done implicitly by close()), but with BufferedOutputStream this is even more important than with a other OutputStreams. If you have a FileOutputStream, the only buffering performed is that of the OS. If you have a BufferedOutputStream, Java performs its own buffering on top of it.
If you use Java 7 or newer, I'd recommend to write the code like this:
try (BufferedInputStream bIn = new BufferedInputStream(in);
BufferedOutputStream bOut = new BufferedOutputStream(new FileOutputStream(fileName))) {
for (int read; ((read = bIn.read()) != -1; )
bOut.write(read);
}
In your case I suspect you were closing the FileOutputStream but not the BufferedOutputStream. Therefore the file was truncated or even empty because the data buffered in the BufferedOutputStream was not flushed.
am trying to read a JSON response using buffered reader as shown below. I'm using Apache Commons Http client. Response comes as a single line JSON and no of characters are around 1060000 and size is approximately 1 MB. Problem am facing is only part of stream is read by reader and other part is missing. How can i read the full JSON without losing any data.? Is this related to 'CharBufferSize' of BufferedReader or no of characters in the stream ?
InputStream stream = method.getResponseBodyAsStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
StringBuilder builder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
try using a json parser.
import org.codehaus.jackson.*;
JsonFactory fac = new JsonFactory();
JsonParser parser = fac .createJsonParser(stream);
If you just want to copy the complete stream into the StringBuilder, you should use the InputStreamReader and a char-array buffer.
InputStream stream = method.getResponseBodyAsStream();
InputStreamReader reader = new InputStreamReader(stream, "UTF-8");
StringBuilder builder = new StringBuilder();
char[] buffer = new char[4096];
int read;
while ((read = reader.read(buffer)) != -1) {
builder.append(buffer, 0, read);
}
Finally i was able to solve using the IOUtils in Apache Commons library. Here is the code.
BoundedInputStream boundedInputStream= new BoundedInputStream(stream);
BufferedReader reader = new BufferedReader(new InputStreamReader(boundedInputStream,"UTF-8"));
StringBuilder builder= new StringBuilder();
StringBuilderWriter writer = new StringBuilderWriter(builder);
IOUtils.copy(reader, writer);
Although it is been a while, it may be helpful for someone.
Here is the original source,
Most Robust way of reading a file or stream using Java (To prevent DoS attacks)