I am new to ADK. Recently I wrote a program to get strings from
other devices. It's OK except for Chinese string. Can anyone
help to fix this problem?
my codes look like this
mFileDescriptor = mUsbManager.openAccessory(mAccessory);
FileDescriptor fd = mFileDescriptor.getFileDescriptor();
mInputStream = new FileInputStream(fd);
byte[] b = new byte[512];
int n;
String str;
while ((n = mInputStream.read(b)) != -1)
{
......
str = (new String(b, 0, n, Charset.forName("UTF-8")));
......
}
Chinese language is represented in Unicode as multi-byte characters. So, to read it properly, you need to use specific reader objects which can understand and interpret the multi-byte character encoding concept.
Essentially, you need to do something like this:
try {
BufferedReader bufReader = new BufferedReader(
new InputStreamReader(inputstream,Charset.forName("UTF-8")));
String line = null;
while ((line= bufReader.readLine())!= null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
Related
I am trying to download the json file which contains slovenian characters,While downloading json file as a string I am getting special character as specified below in json data
"send_mail": "Po�lji elektronsko sporocilo.",
"str_comments_likes": "Komentarji, v�ecki in mejniki",
Code which I am using
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.connect();
try {
InputStream input1 = new BufferedInputStream(url.openStream(), 300);
String myData = "";
BufferedReader r = new BufferedReader(new InputStreamReader(input1));
StringBuilder totalValue = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
totalValue.append(line).append('\n');
}
input1.close();
String value = totalValue.toString();
Log.v("To Check Problem from http paramers", value);
} catch (Exception e) {
Log.v("Exception Character Isssue", "" + e.getMessage());
}
I want to know how to get characters downloaded properly.
You need to encode string bytes to UTF-8. Please check following code :
String slovenianJSON = new String(value.getBytes([Original Code]),"utf-8");
JSONObject newJSON = new JSONObject(reconstitutedJSONString);
String javaStringValue = newJSON.getString("content");
I hope it will help you!
Decoding line in while loop can work. Also you should add your connection in try catch block in case of IOException
URL url = new URL(f_url[0]);
try {
URLConnection conection = url.openConnection();
conection.connect();
InputStream input1 = new BufferedInputStream(url.openStream(), 300);
String myData = "";
BufferedReader r = new BufferedReader(new InputStreamReader(input1));
StringBuilder totalValue = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
line = URLEncoder.encode(line, "UTF8");
totalValue.append(line).append('\n');
}
input1.close();
String value = totalValue.toString();
Log.v("To Check Problem from http paramers", value);
} catch (Exception e) {
Log.v("Exception Character Isssue", "" + e.getMessage());
}
It's not entirely clear why you're not using Android's JSONObject class (and related classes). You can try this, however:
String str = new String(value.getBytes("ISO-8859-1"), "UTF-8");
But you really should use the JSON libraries rather than parsing yourself
When creating the InputStreamReader at this line:
BufferedReader r = new BufferedReader(new InputStreamReader(input1));
send the charset to the constructor like this:
BufferedReader r = new BufferedReader(new InputStreamReader(input1), Charset.forName("UTF_8"));
problem is in character set
as per Wikipedia Slovene alphabet supported by UTF-8,UTF-16, ISO/IEC 8859-2 (Latin-2). find which character set used in server, and use the same character set for encoding.
if it is UTF-8 encode like this
BufferedReader bufferedReader= new BufferedReader(new InputStreamReader(inputStream), Charset.forName("UTF_8"));
if you had deffrent character set use that.
I have faced same issue because of the swedish characters.
So i have used BufferedReader to resolved this issue. I have converted the Response using StandardCharsets.ISO_8859_1 and use that response. Please find my answer as below.
BufferedReader r = new BufferedReader(new InputStreamReader(response.body().byteStream(), StandardCharsets.ISO_8859_1));
StringBuilder total = new StringBuilder();
String line;
while ((line = r.readLine()) != null)
{
total.append(line).append('\n');
}
and use this total.toString() and assigned this response to my class.
I have used Retrofit for calling web service.
I finally found this way which worked for me
InputStream input1 = new BufferedInputStream(conection.getInputStream(), 300);
BufferedReader r = new BufferedReader(new InputStreamReader(input1, "Windows-1252"));
I figured out by this windows-1252, by putting json file in asset folder of the android application folder, where it showed same special characters like specified above,there it showed auto suggestion options to change encoding to UTF-8,ISO-8859-1,ASCII and Windows-1252, So I changed to windows-1252, which worked in android studio which i replicated the same in our code, which worked.
This question already has answers here:
Java multiple file transfer over socket
(3 answers)
Closed 5 years ago.
I have been spending forever on this and can not seem to work it out. I am self taught and not very familiar with this so forgive me if it is a remedial question. I am sending data from Android to .Net server. Data is getting corrupt on encoding, I know this I am just not sure how to fix. I am using the .Net Async server sample code found here: Microsoft Async Sample
My Android client code is:
try {
final Socket sock = new Socket();
final int timeOut = (int) TimeUnit.SECONDS.toMillis(5); // 5 sec wait period
sock.connect(new InetSocketAddress("localhost", 11000), timeOut);
if (sock.isConnected()==true){
BufferedReader in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
String FileName = "myfile.jpg";
StringBuilder hd = new StringBuilder();
try {
String FilePath= Environment.getExternalStorageDirectory() + "/mydir/" + FileName;
File file = new File(FilePath);
FileInputStream is = new FileInputStream(file);
byte[] chunk = new byte[40960];
int chunkLen = 0;
while ((chunkLen = is.read(chunk)) != -1) {
//String str = new String(Base64.encodeToString(chunk, Base64.NO_WRAP));
//String str = new String(chunk, "ASCII");
String str = new String(chunk, "UTF-8");
out.write(str);
}
//out.write(hd.toString());
} catch (FileNotFoundException fnfE) {
// file not found, handle case
} catch (IOException ioE) {
// problem reading, handle case
}
out.write("<EOF>");
out.flush();
StringBuilder returnString = new StringBuilder();
String line;
while ((line = in.readLine()) != null) {
returnString.append(line).append('\n');
}
out.close();
in.close();
sock.close();
}else{
sock.close();
}
} catch (IOException e) {
e.printStackTrace();
}
As you can see in my comments, I have tried base64 and UTF-8. I get all kinds of errors on the server when I do that. If I use Base64 I get not part of Base64 error (extra padding etc.). UTF8 writes the file but it is corrupt. When I send it all as one Base64 string it works fine as I use 'Dim data As Byte() = Convert.FromBase64String(FileData)' but as expected it throws memory errors in Android for large files hence the chunking. I am sending some plain ASCII text along with it so I parse out the non-ASCII stuff to write the file. I am super stuck, any help would be much appreciated. Thanks in advance.
You don't have to encode it at all. Just write it directly as bytes using an OutputStream. Simpler, quicker, better.
I found the answer. It was so weird but makes sense now.
byte[] chunk = new byte[30000];
int chunkLen = 0;
while ((chunkLen = is.read(chunk)) != -1) {
String str = new String(Base64.encodeToString(chunk, Base64.NO_WRAP));
out.write(str);
}
I had to change the chunk size to a multiple of 3 then my base64 encoding worked great. Found it here and gave an up vote. Thank you 'mjv'. Link to the answer
This is related to a situation I find myself in working with saving text files in Unity on Android, then reading them in native Android.
One of the files we read is a HMACMD5 signature, created with the code,
byte[] bData = System.Text.Encoding.UTF8.GetBytes (data);
byte[] bKey = System.Text.Encoding.UTF8.GetBytes (key);
using (HMACMD5 hmac = new HMACMD5(bKey)) {
byte[] signature = hmac.ComputeHash (bData);
return System.Convert.ToBase64String (signature);
}
And then written to the phone with,
public static void SaveText (string path, string data) {
using (FileStream fs = new FileStream(path, FileMode.Create)) {
using (StreamWriter sw = new StreamWriter(fs)) {
sw.Write (data);
}
}
}
The other string we're saving is a JSON string dump. The signature has a newline character at the end of the string, but the JSON string doesn't. I know I can manually add one, but this question is about reading the accurate file contents.
On Android, based on previous SO answers, I read the file with,
String readFile(File file) {
StringBuilder text = new StringBuilder();
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while ((line = br.readLine()) != null) {
text.append(line);
text.append("\n");
}
br.close();
}
catch (IOException e) {
MyLogger.e(LOG_TAG, "Error opening file " + file.getPath(), e);
}
return text.toString();
}
I'm manually adding the newline character after every line, but if I do this, I don't accurately read the JSON file, which doesn't have a newline character at the end. If I don't add the newline, I don't accurately read the signature file, which does.
You better then do not use readLine() but read().
I want to send an XML message to a server from my Android Mobile app via HTTP post.
I tried it with HttpUrlConnection, following these steps:
URL url = new URL(vURL);
HttpUrlConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
// Adding headers (code removed)
conn.setRequestProperty("Content-Type", "text/xml; charset=utf-16");
OutputStream out = new BufferedOutputStream(conn.getOutputStream());
// Adding XML message to the connection output stream
// I have removed exception handling to improve readability for posting it here
out.write(pReq.getBytes()); // here pReq is the XML message in String
out.close();
conn.connect();
Once I get the response, the stream reading part is in done this manner:
BufferedReader in = null;
StringBuffer sb;
String result = null;
try {
InputStreamReader isr = new InputStreamReader(is);
// Just in case, I've also tried:
// new InputStreamReader(is, "UTF-16");
// new InputStreamReader(is, "UTF-16LE");
// new InputStreamReader(is, "UTF-16BE");
// new InputStreamReader(is, "UTF-8");
in = new BufferedReader(isr);
sb = new StringBuffer("");
String line = "";
while ((line = in.readLine()) != null)
sb.append(line);
in.close();
result = sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
Now the result string I get is in some unreadable format/encoding.
When I try the same thing with HttpClient it works correctly. Here is the streaming reading part once I get an HttpResponse after the HttpClient.execute call:
BufferedReader in = null;
InputStream is;
StringBuffer sb;
String decompbuff = null;
try {
is = pResponse.getEntity().getContent();
InputStreamReader isr = new InputStreamReader(is);
in = new BufferedReader(isr);
// Prepare the String buffer
sb = new StringBuffer("");
String line = "";
while ((line = in.readLine()) != null)
sb.append(line);
in.close();
// gZip decompression of response. Note: message was compressed before
// posting it via HttpClient (Posting code is not mentioned here)
decompbuff = Decompress(sb.toString());
} catch (Exception e) {
e.printStackTrace();
}
return decompbuff;
Some help is appreciated in understanding the problem.
One (severe) problem could be that you're ignoring the encoding of input and output.
Input
conn.setRequestProperty("Content-Type", "text/xml; charset=utf-16");
OutputStream out = new BufferedOutputStream(conn.getOutputStream());
// Adding XML message to the connection output stream
// I have removed exception handling to improve readability for posting it here
out.write(pReq.getBytes()); // <-- you use standard platform encoding
out.close();
better:
out.write(pReq.getBytes("UTF-16"));
Output
You probably ignored compression, which would better look like this (taken from DavidWebb):
static InputStream wrapStream(String contentEncoding, InputStream inputStream)
throws IOException {
if (contentEncoding == null || "identity".equalsIgnoreCase(contentEncoding)) {
return inputStream;
}
if ("gzip".equalsIgnoreCase(contentEncoding)) {
return new GZIPInputStream(inputStream);
}
if ("deflate".equalsIgnoreCase(contentEncoding)) {
return new InflaterInputStream(inputStream, new Inflater(false), 512);
}
throw new RuntimeException("unsupported content-encoding: " + contentEncoding);
}
// ...
InputStream is = wrapStream(conn.getContentEncoding(), is);
InputStreamReader isr = new InputStreamReader(is, "UTF-16");
in = new BufferedReader(isr);
sb = new StringBuffer("");
String line = "";
while ((line = in.readLine()) != null)
sb.append(line); // <-- you're swallowing linefeeds!
in.close();
result = sb.toString();
It would be better to let the XML-Parser consume your InputStream directly. Don't create a JAVA string, but let the parser scan the bytes. It will automatically detect the encoding of the XML.
Generally there might be still an issue, because we don't know what type of UTF-16 you use. Can be BigEndian or LittleEndian. That's why I asked, if you really need UTF-16. If you don't have to treat with some asian languages, UTF-8 should be more efficient and easier to use.
So the "solution" I gave you is not guaranteed to work - you have to fiddle with UTF-16 BE/LE a bit and I wish you good luck and patience.
Another remark: in your example above you first construct the String and then Decompress it. That is the wrong order. The stream comes compressed (gzip, deflate) and must be decompressed first. Then you get the String.
I am receiving huge JSON and and while I am reading the lines OutOfMemoryError appears.
Here is my first method that I am trying to parse the JSON.
InputStream in = response.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"), 8);
String result = "";
while (true) {
String ss = reader.readLine();
if (ss == null) {
break;
}
result += ss;
}
And I've also tried this method.
InputStream in = response.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ( (line = reader.readLine()) != null)
{
sb.append(line);
}
In the both of the cases the OutOfMemoryErorr is appearing.
Mostly the error will occur due to heap size. You need to increase the size of the heap
To increase the heap size
For additional info on heap size in java visit here
The best solution I found was to raise the Heap of the Application.
I placed android:largeHeap="true" under the <application/> in the AndroidManifest.xml.
When you instantiate your BufferedReader, you pass in an int size of 8, meaning your buffer is 8 characters (I assume that's not what you want). If you pass no size, the default is 8192 characters.
Try this:
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
Or this (same effect):
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"), 8192);
http://developer.android.com/reference/java/io/BufferedReader.html
I'm not completely sure that will fix the error you are seeing, but worth trying if you can't get it working.
My JSON code was waiting for status, which comes towards the end. So I modified the code to return earlier.
// try to get formattedAddress without reading the entire JSON
String formattedAddress;
while ((read = in.read(buff)) != -1) {
jsonResults.append(buff, 0, read);
formattedAddress = ((String) ((JSONObject) new JSONObject(
jsonResults.toString()).getJSONArray("results").get(0))
.get("formatted_address"));
if (formattedAddress != null) {
Log.i("Taxeeta", "Saved memory, returned early from json") ;
return formattedAddress;
}
}
JSONObject statusObj = new JSONObject(jsonResults.toString());
String status = (String) (statusObj.optString("status"));
if (status.toLowerCase().equals("ok")) {
formattedAddress = ((String) ((JSONObject) new JSONObject(
jsonResults.toString()).getJSONArray("results").get(0))
.get("formatted_address"));
if (formattedAddress != null) {
Log.w("Taxeeta", "Did not saved memory, returned late from json") ;
return formattedAddress;
}
}