I am working in J2ME.
I am getting json response from server then I try to parse this json data as per my requirement.
this is my code for getting response from server:-
InputStream inputStream = null;
OutputStreamWriter out = null;
byte[] readData = new byte[50000];
String response = "no";
try {
// --- write ---
out = new OutputStreamWriter(connection.openOutputStream(), "UTF-8");
out.write(data.toString());
out.close();
// --- read ---
int responseCode = connection.getResponseCode();
if (responseCode != HttpConnection.HTTP_OK) {
throw new IOException("HTTP response code: " + responseCode);
}
inputStream = connection.openInputStream();
int actual = inputStream.read(readData);
response = new String(readData, 0, actual, "UTF-8");
return response;
}
when response from server is small then it works fine, but if response is large then it get half of response and return to my another method. Please suggest me what should I do to get large amount of data into my readData and response variable.
Thank you in advance.
You will need to read all data before (there can be more data in the stream).
As you have noticed the call to InputStream.read doesn't guarantee you to fill your buffer (readData) it return the number of bytes it could read at the time. It just doesn't matter how big your buffer is on your side.
You will need to read re-call the InputStream.read method to check that you have all the data available in the stream. The read method will return -1 when no more data is available.
This is an example how you can do it:
....
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int read;
byte[] tmp = new byte[1024];
while ((read = inputStream.read(tmp)) != -1)
bos.write(tmp, 0, read);
return new String(bos.toByteArray(), "UTF-8");
Also, when you are done with the connection you should call close on it so that the system knows that you don't need it anymore.
You nead to flush and close your input stream after reading!!!
inputStream.close();
Related
How to read HTTP request using InputStream? I used to read it like this:
InputStream in = address.openStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder result = new StringBuilder();
String line;
while((line = reader.readLine()) != null) {
result.append(line);
}
System.out.println(result.toString());
But reader.readLine() could be blocked, because there is no guarantee that null line will be reached. Of course I can read Content-Length header and then read request in a loop:
for (int i = 0; i < contentLength; i++) {
int a = br.read();
body.append((char) a);
}
But if Content-Length is set too big (I guess it could be set manually for purpose), br.read() will be blocked.
I try to read bytes directly from InputStream like this:
byte[] bytes = getBytes(is);
public static byte[] getBytes(InputStream is) throws IOException {
int len;
int size = 1024;
byte[] buf;
if (is instanceof ByteArrayInputStream) {
size = is.available();
buf = new byte[size];
len = is.read(buf, 0, size);
} else {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
buf = new byte[size];
while ((len = is.read(buf, 0, size)) != -1)
bos.write(buf, 0, len);
buf = bos.toByteArray();
}
return buf;
}
But it waits forever. What do?
If you are implementing HTTP server you should detect the end of the request according to HTTP specification. Wiki - https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol
First of all, you should read a request line, it is always a single line.
Then read all request headers. You read them until you have an empty line (i.e. two line endings - <CR><LF>).
After you have a status line and headers you should decide do you need to read body or no because not all requests might have a body - summary table
Then, if you need a body, you should parse your headers (which you already got) and get Content-Length. If it is - just read as many bytes from the stream as it is specified.
When Content-Length is missing the length is determined in other ways. Chunked transfer encoding uses a chunk size of 0 to mark the end of the content. Identity encoding without Content-Length reads content until the socket is closed.
Create a request wrapper which extends HttpServletRequestWrapper, which will override the getInputStream() which in turn return ServletInputStream , which has the safe read method. try that
I have the below piece of code that works fine when run from eclipse
String str = "testing";
InputStream is = new ByteArrayInputStream(str.getBytes());
int length = is.available();
byte[] data = new byte[length];
is.read(data, 0, length);
System.out.println("output "+new String(data));
When I break this code to post the data over network using Jerser client API and try read it back on the server using Jersey I don't get the value that I posted. The client code looks like this
public static void main(String s[]) throws IOException {
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
String str = "testingthi";
InputStream is = new ByteArrayInputStream(str.getBytes());
WebResource webResource = client.resource("http://192.168.1.15:8090/JersySample/resources/stream/upload");
ClientResponse response = webResource.type(MediaType.APPLICATION_OCTET_STREAM).post(ClientResponse.class,is);
is.close();
}
The code on the server looks like this
#Consumes(MediaType.APPLICATION_OCTET_STREAM)
public Response upload( InputStream is) {
try{
int size = is.available();
byte data[] = new byte[size];
is.read(data,0,size);
System.out.println(" Posted data is "+ new String(data)+" length is "+size+" stream size "+is.available());
is.close();
}catch (Exception e) {
e.printStackTrace();
}
return Response.ok().entity("Done").build();
}
When I read the string using apache-commons-io API I do get the string value that I posted. Can someone explain why it doesn't work using the java.io API which was working in non-network situation?
You're making the usual mistake of assuming that read() fills the buffer. It isn't obliged to do that. See the Javadoc. It's only obliged to read at least one byte and return. The byte count, return -1, or throw an IOException.
You're also misusing available(). It doesn't return the total number of bytes in the stream, and the way you're using it is specifically warned against in the Javadoc.
I am calling a wcf web service in android. All appear to work fine until I call a method that is returning quite a bit of data. It appears the result is being cut off and throwing not a valid json object. I check the result, and it return about 9089 characters. The bufferedreader and inputstreamreader have both return the same count with the same result. I try calling a different method that is returning about 2000 records, and it work without problems.
Here is the sample code where I am reading the result:
StringEntity entity = new StringEntity(jsonObject.toString());
httpPost.setEntity(entity);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity responseEntity = httpResponse.getEntity();
char[] buffer = new char[(int)responseEntity.getContentLength()];
InputStream stream1 =responseEntity.getContent();
InputStreamReader reader = new InputStreamReader(stream1);
reader.read(buffer);
stream1.close();
String sInvokeReturnValue = new String(buffer);
Any kind of help would be greatly appreciated.
All appear to work fine until I call a method that is returning quite a bit of data. It appears the result is being cut off and throwing not a valid json object.
I suspect that your read is hitting a buffer limit and returning not as many bytes as you are expecting. You should put your read in a loop to make sure you get all of the input.
What I would recommend is to use a StringWriter to read in your data. For example:
// not much point on allocating a huge buffer here
char[] buffer = new char[4096];
InputStreamReader reader = new InputStreamReader(responseEntity.getContent());
try {
StringWriter writer = new StringWriter();
while (true) {
int numRead = reader.read(buffer);
if (numRead < 0) {
break;
}
writer.write(buffer, 0, numRead);
}
} finally {
reader.close();
}
stream1.close();
String sInvokeReturnValue = writer.toString();
I am creating httpServer and I have done writing file server part.
But I am having problems when I download images.
FileInputStream fis = new FileInputStream(file_path);
output = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int n = 0;
while (-1 != (n = fis.read(buffer))) {
output.write(buffer, 0, n);
}
data = output.toByteArray();
body = new String(data);
return body
I return the body of response to my original method.
// body is return value from above code, header is also another String return value from
// makeHeader method
String response = header + body;
byte[] Response = null;
try{
Response = response.getBytes("US-ASCII");
}catch (UnsupportedEncodingException e) {}
return Response
My server is working when it comes to text files, .html, .css but not with images.
Can you please point me out what did I do wrong
If you mix text and binary you are sure to corrupt the data. For example US-ASCII is only 7 bit and any byte with the top bit set will be corrupted.
You should attempt to send the image without using String or text to avoid corruption.
I am sending a file to the browser in a servlet. The highest JDK I can use is 1.4.2, and I also have to retrieve the file via a URL. I am also trying to use "guessContentTypeFromStream", but I keep getting null which raises an exception when used in the code sample below. I currently have to hard code or work out the content-type myself.
What I would like to know is, how I can re-factor this code so the file transmission is as fast as possible and also use guessContentTypeFromStream ? (Note "res" is HttpServletResponse).
URL servletUrl = new URL(sFileURL);
URLConnection conn = servletUrl.openConnection();
int read;
BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
String sContentType =conn.guessContentTypeFromStream(conn.getInputStream());
res.setContentType(sContentType);
//res.setContentType("image/jpeg");
PrintWriter os = res.getWriter();
while((read = bis.read()) != -1){
os.write(read);
}
//Clean resources
os.flush();
This is how you normally read/writes data.
in = new BufferedInputStream(socket.getInputStream(), BUFFER_SIZE);
byte[] dataBuffer = new byte[1024 * 16];
int size = 0;
while ((size = in.read(dataBuffer)) != -1) {
out.write(dataBuffer, 0, size);
}