I'm trying to parse some JSON data that I'm receiving as response from a web url.
I'm getting the complete response, but when I read the response using BufferedReader, I get only partial data, I'm not able to read the entire contents of the response.
I've also tried writing the contents into a .txt file and again reading the contents from that file, but still it reads only partial dat, not the entire file contents.
Anyone has any solutions to this...
here is my code,
package com.example.asynctest;
/*I have excluded the imports*/
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new MyAsyncTask().execute();
}
class MyAsyncTask extends AsyncTask<String, String, Void>{
public String readBugzilla() {
StringBuilder builder = new StringBuilder();
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet("https://bugzilla.mozilla.org/rest/bug?assigned_to=lhenry#mozilla.com");
try {
HttpResponse response = client.execute(httpGet);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode == 200) {
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
/*I tried to Read the InputStream here, but it was incomplete, so I decided to write the contents of the inputstream into a text file, and then read the contents later on*/
String fileName = "category.txt";
File destinationFile = new File(getExternalFilesDir(null), fileName);
BufferedOutputStream buffer = new BufferedOutputStream(new FileOutputStream(destinationFile));
byte byt[] = new byte[100000];
int i;
for (long l = 0L; (i = content.read(byt)) != -1; l += i ) {
buffer.write(byt, 0, i);
}
buffer.close();
//Read text from file
File file = new File(getExternalFilesDir(null),"category.txt");
StringBuilder text = new StringBuilder();
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while ((line = br.readLine()) != null) {
text.append(line);
Log.d("Law", "line is "+line);
}
br.close();
Log.d("Law","Text is "+text.toString());
}
catch (IOException e) {
//You'll need to add proper error handling here
Log.d("Law IO", e.toString());
}
} else {
Log.e("Law", "Failed to download file");
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return builder.toString();
}
#Override
protected Void doInBackground(String... arg0) {
// TODO Auto-generated method stub
String response = readBugzilla();
Log.d("Law", "Response "+response);
return null;
}
I really tried all that I can, but can't find a solution to this problem, perhaps someone has used a better technique to solve this.
Related
I am trying to upload a audio file to my webserver. But don't know how to read the the response. Here is the very simplified test.php:
<?php
echo 'I want to see this in the Toast';
?>
fff And here is my onClick that must send the file to the webserver and get a response:
public void send(View v){
Uri uri = new Uri.Builder().scheme("http").authority("sub.domain.nl").path("test.php")
.appendQueryParameter("action", "sendMessage")
.appendQueryParameter("idto", "18")
.appendQueryParameter("idfrom", "36")
.appendQueryParameter("type", "audio")
.build();
String urlString = uri.toString();
new SendAudioTask().execute(urlString);
}
private class SendAudioTask extends AsyncTask<String, Integer, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
String url = params[0];
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath(),
"/audio.3gpp");
HttpResponse response = null;
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
InputStreamEntity reqEntity = new InputStreamEntity(
new FileInputStream(file), -1);
reqEntity.setContentType("binary/octet-stream");
reqEntity.setChunked(true);
httppost.setEntity(reqEntity);
response = httpclient.execute(httppost);
} catch (Exception e) {
publishProgress(1);
}
return response.toString();
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
Toast.makeText(MainActivity.this, "Dev message: = " + values[0], Toast.LENGTH_SHORT).show();
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
}
}
Result.toString() in the onPostExecute() is
org.apache.http.message.basicHttpRespons#43b4cc68
If toString() is the right way to read the response. What is wrong with my code? My code doesn't execute the publishProgress.
HttpEntity entity = httpResponse.getEntity();
InputStream is = entity.getContent();
String result = convertStreamToString(is);
private static String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append((line + "\n"));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
change
return response.toString();
to
return EntityUtils.toString(response.getEntity());
So what getEntity() does,
getEntity()
Obtains the message entity of this response, if any.
Thanks in advance..
First, I'm asking this for android.
I have to send a http post request with a zip file containing an xml file having list of names in it.
now, according to the list of name I sent, the server will send me the binary data of a zip file and I have to save that binary data (response) as a zip file.
the problem is, when I'm saving this binary data as a zip file, it is not able to extract the zip then.
I think this could be some character set problem too.. that i need to convert the received binary data to some character set and then save it as a zip..
please Help me in this, I'm new to android. and any ASYNC task example for doing the same will be great Help.
This is my code..
private class sendMissingImagesToServer extends
AsyncTask<String, Integer, byte[]> {
#Override
protected byte[] doInBackground(String... params) {
String uri = params[0];
try {
MultipartEntityBuilder entity;
File f;
FileBody fb;
entity = MultipartEntityBuilder.create();
entity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
f = new File(zipImageFile);
fb = new FileBody(f);
entity.addPart("orderFile", fb);
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(uri);
Log.e("Uploload Missing Image URL", "" + uri);
httppost.setEntity(entity.build());
HttpResponse response = httpclient.execute(httppost);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer stringBuffer = new StringBuffer();
// byte[] fileBites=null;
String line = "";
while ((line = bufferedReader.readLine()) != null) {
stringBuffer.append(line);
}
bufferedReader.close();
// fileBites=stringBuffer.toString().getBytes();
// Log.e("FILE BITES", fileBites+"=>"+fileBites.length);
ByteArrayOutputStream bObj = new ByteArrayOutputStream();
bObj.reset();
bObj.write(stringBuffer.toString().getBytes());
return bObj.toByteArray();
// return stringBuffer.toString();
} catch (Exception e) {
return e.toString().getBytes();
}
}
#Override
protected void onPostExecute(byte[] result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
Log.e("Response From Server", "" + result);
writeToFile(result);
}
}
#SuppressWarnings("resource")
private void writeToFile(byte[] data) {
try {
FileOutputStream fop = null;
File file;
file = new File(AppConstants.DataPath+"/products.zip");
fop = new FileOutputStream(file);
// if file doesnt exists, then create it
if (!file.exists()) {
file.createNewFile();
}
try {
fop.write(data);
} catch (IOException e) {
Log.e("Exception", "File write failed: " + e.toString());
}
unzipImage(AppConstants.DataPath + "/products.zip",
AppConstants.DataPath);
}catch (Exception E)
{
}
}
Readers are not meant to read octet streams.
Reads text from a character-input stream, buffering characters so as to provide for the efficient reading of characters, arrays, and lines.
You're looking for a BufferedInputStream.
The getContent() method on the HttpEntity returns an InputStream. Wrap this around a BufferedInputStream and write it to a file or a ByteArrayOutputStream.
byte[] buffer = new byte[5 * 1024];
int numRead = -1;
while( (numRead = bufferedInputStream.read(buffer))!= -1)
{
byteArrayOutputStream.write(buffer, 0, numRead);
}
byteArrayOutputStream.flush();
byteArrayOutputStream.close();
byte[] result = byteArrayOutputStream.toByteArray();
To save on memory I'd advise you to write to a BufferedOutputStream instead of trying to get the bytes from the stream into a data structure. The android device is likely to run out of memory for large zip files.
Maybe you can try this:
private class sendMissingImagesToServer extends
AsyncTask<String, Integer, byte[]> {
#Override
protected byte[] doInBackground(String... params) {
String uri = params[0];
byte[] data;
try {
MultipartEntityBuilder entity;
File f;
FileBody fb;
entity = MultipartEntityBuilder.create();
entity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
f = new File(zipImageFile);
fb = new FileBody(f);
entity.addPart("orderFile", fb);
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(uri);
Log.e("Uploload Missing Image URL", "" + uri);
httppost.setEntity(entity.build());
HttpResponse response = httpclient.execute(httppost);
InputStream input = response.getEntity().getContent();
data = new byte[input.available()];
input.read(data);
return data;
} catch (Exception e) {
return e.toString().getBytes();
}
}
#Override
protected void onPostExecute(byte[] result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
Log.e("Response From Server", "" + result);
writeToFile(result);
}
}
#SuppressWarnings("resource")
private void writeToFile(byte[] data) {
try {
FileOutputStream fop = null;
File file;
file = new File(AppConstants.DataPath+"/products.zip");
fop = new FileOutputStream(file);
// if file doesnt exists, then create it
if (!file.exists()) {
file.createNewFile();
}
try {
fop.write(data);
} catch (IOException e) {
Log.e("Exception", "File write failed: " + e.toString());
}
unzipImage(AppConstants.DataPath + "/products.zip",
AppConstants.DataPath);
}catch (Exception E)
{
}
}
If you covert the bytes to a String and then get bytes by String.getBytes() ,you need to assume that the encoding must be single-byte like iso-8859-1(not utf-8 nor others).
Change your code from
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
to
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(),"ISO-8859-1"));
And then bObj.write(stringBuffer.toString().getBytes());
to
bObj.write(stringBuffer.toString().getBytes("ISO-8859-1"));
Android 4.2.2
I'm parsing a JSON string sent from PHP server. Parsing the same string gives this exception on random character number each time. Sometimes it's loaded successfully. The size of the input is 202858 bytes. I can't post it here as it's private data but I guess it's correctly formatted. If I run my app in debug/step-by-step mode it loads all the time! Also if the size of the response is smaller (fewer lines but not sure how many exactly) it also loads all the time.
Here is how I load the stream:
String JSONResp = "";
try {
URL u = new URL(params[1]);
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
conn.setRequestMethod(params[0]);
conn.connect();
/* Here is the new code. This works! */
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"), 4096);
StringBuilder sb = new StringBuilder();
String line = null;
while( (line = br.readLine()) != null ) {
sb.append(line + "\n");
}
JSONResp = sb.toString();
/* Old code starts here. This is not working!
// Read the stream
InputStream is = conn.getInputStream();
byte[] b = new byte[4096];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ( is.read(b) != -1) {
baos.write(b);
}
JSONResp = new String(baos.toByteArray());
*/
JSONArray arr = new JSONArray(JSONResp);
//TODO read result form the input stream
_HTTP_code = 200;
return arr;
}
catch(Throwable t) {
_HTTP_code = ERROR_Throwable;
_HTTP_text = "Error";
_HTTP_body = "Could not parse response!";
Log.e("JSON", "JSONResp.length() = " + JSONResp.length() + ".");
t.printStackTrace();
}
The code is executed from a separate thread and this is what I found in the Android documentation:
Instances of this class are not thread safe. Although this class is nonfinal, it was not designed for inheritance and should not be subclassed. In particular, self-use by overridable methods is not specified. See Effective Java Item 17, "Design and Document or inheritance or else prohibit it" for further information.
I'm not sure if I understand that text correctly but I don't have more than one thread querying the server at the same time.
Any help would be appreciated.
public class GetResultTask extends AsyncTask<String, Void, String> {
Activity act;
private ProgressDialog pd;
private boolean isInternetConnected = true;
public GetResultTask(Activity _act){
this.act = _act;
pd = ProgressDialog.show(act, null, "Loading...", true );
}
#Override
protected void onPreExecute() {
}
protected void onPostExecute(String result) {
pd.dismiss();
if(!isInternetConnected){
//Toast.makeText(getApplicationContext(), "Check your Network Connection", Toast.LENGTH_LONG).show();
}
}
#Override
protected String doInBackground(String... params) {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("option", "getPeople"));
nameValuePairs.add(new BasicNameValuePair("val", params[0]));
String downloadedString = null;
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://example.com/filename.php");
try {
// Execute HTTP Post Request
UrlEncodedFormEntity ent = new UrlEncodedFormEntity(nameValuePairs,HTTP.UTF_8);
httppost.setEntity(ent);
//new
//HttpResponse response = httpClient.execute(httppost);
//System.out.println("Response");
HttpResponse response = httpclient.execute(httppost);
//System.out.println("Response is :-\n"+response);
InputStream in = response.getEntity().getContent();
StringBuilder stringbuilder = new StringBuilder();
BufferedReader bfrd = new BufferedReader(new InputStreamReader(in));
String line;
while((line = bfrd.readLine()) != null)
stringbuilder.append(line);
//string returned as JSON
downloadedString = stringbuilder.toString();
}
catch (ClientProtocolException e) {
e.printStackTrace();
} catch(UnknownHostException e){
isInternetConnected = false;
}
catch (IOException e) {
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
}
//System.out.println(downloadedString);
return downloadedString;
}
}
I get Data from Json in android,date get and save in String Variable.but when use DecodeUrl its error:
Error: java.lang.IllegalArgumentException: Invalid % sequence at 40:
my code:
#SuppressLint("NewApi")
public String JsonReguest(String url) {
String json = "";
String result = "";
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
HttpClient httpclient = new DefaultHttpClient();
// Prepare a request object
HttpGet httpget = new HttpGet(url);
httpget.setHeader("Accept", "application/json");
httpget.setHeader("Content-Type", "application/json");
HttpResponse response;
try {
response = httpclient.execute(httpget);
response.setHeader("Content-Type","UTF-8");
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
result = convertStreamToString(instream);
InputStream stream = new ByteArrayInputStream(result.getBytes("UTF-8"));
result = convertStreamToString(stream);
// String encode_url=URLEncoder.encode(result,"UTF-8");
// String decode_url=URLDecoder.decode(encode_url,"UTF-8");
//result=decode_url;
//String decodedUrl = URLDecoder.decode(result, "UTF-8");
result=URLDecoder.decode(result);
}
} catch (Exception e) {
Log.e("Error", e.toString());
}
return result;
}
public static String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
simple text of json :
{"CategoryID":11,"ParentID":0,"Title":"%u062E%u0648%u062F%u0631%u0648","PicAddress":""},{"CategoryID":16,"ParentID":0,"Title":"%u0627%u0645%u0644%u0627%u0643%20","PicAddress":""}
this line crashed : result=URLDecoder.decode(result);
how to Resolve Problems.
first decode specifing your encoding
String result = URLDecoder.decode(url, "UTF-8");
and then go to http://json.org/, scroll down and choose one of the supported json parsing Java libraries
As Selvin commented %uxxxx is not a standard Url encoded string , so it's obvious to get an error
you have 2 options:
Contact the service provider to fix her url encoded strings and use URLDecoder.decode in your code
write a custom decoder for such strings
P.S. ask your questions more clear to avoid getting negative points
I'm aiming to make a very basic application which reads the HTML and stores it into a string. I'm only interested in one line from the website's source. I found a topic which suggested this:
String bodyHtml = "null";
try {
String myUri = "http://www.spring8.or.jp/ext/ja/status/text.html";
HttpClient httpClient = new DefaultHttpClient();
HttpGet get = new HttpGet(myUri);
HttpResponse response = httpClient.execute(get);
// Build up result
bodyHtml = EntityUtils.toString(response.getEntity());
} catch (Exception e) {
}
url.setText(bodyHtml);
With url being my textview. I have set the permissions in the manifest correctly as far as I'm aware.
However when I run this code on my phone and the emulator, it doesn't seem to work at all. I get nothing. Am I missing something?
Thank you
Try this instead of the EntityUtils
BufferedReader rd = new BufferedReader(new InputStreamReader(
response.getEntity().getContent()));
String line = "";
String newLine = "";
while ((line = rd.readLine()) != null) {
newLine = newLine.concat(line);
}
System.out.println(newLine);
Try this,
Call the below method to download the HTml Content and pass the Url in the parameter,
private void downloadText(String urlStr) {
progressDialog = ProgressDialog.show(this, "",
"Download Text from " + urlStr);
final String url = urlStr;
new Thread () {
public void run() {
int BUFFER_SIZE = 2000;
InputStream in = null;
Message msg = Message.obtain();
msg.what=1;
try {
in = openHttpConnection(url);
InputStreamReader isr = new InputStreamReader(in);
int charRead;
text = "";
char[] inputBuffer = new char[BUFFER_SIZE];
while ((charRead = isr.read(inputBuffer))>0)
{
String readString =
String.copyValueOf(inputBuffer, 0, charRead);
text += readString;
inputBuffer = new char[BUFFER_SIZE];
}
Bundle b = new Bundle();
b.putString("text", text);
msg.setData(b);
in.close();
}catch (IOException e2) {
e2.printStackTrace();
}
messageHandler.sendMessage(msg);
}
}.start();
}
This the helper method which returns InputStream Object,
private InputStream openHttpConnection(String urlStr) {
InputStream in = null;
int resCode = -1;
try {
URL url = new URL(urlStr);
URLConnection urlConn = url.openConnection();
if (!(urlConn instanceof HttpURLConnection)) {
throw new IOException ("URL is not an Http URL");
}
HttpURLConnection httpConn = (HttpURLConnection)urlConn;
httpConn.setAllowUserInteraction(false);
httpConn.setInstanceFollowRedirects(true);
httpConn.setRequestMethod("GET");
httpConn.connect();
resCode = httpConn.getResponseCode();
if (resCode == HttpURLConnection.HTTP_OK) {
in = httpConn.getInputStream();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return in;
}
And now display the String in a textView using Handler,
private Handler messageHandler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
TextView text = (TextView) findViewById(R.id.textview01);
text.setText(msg.getData().getString("text"));
break;
}
progressDialog.dismiss();
}
};
Provide the INTERNET permission in the manifest.
In the execute method of the HttpClient, also put a HttpContext as you see below:
HttpContext localContext = new BasicHttpContext();
HttpResponse response = httpClient.execute(get, localContext);
And also use a BufferedReader:
final BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
If it doesn't work, you'll probably have a problem with you Internet connection.
BTW, don't forget about the android.permission.INTERNET permission!