1. 我们在之前的笔记中LoginServlet.java中,我们Tomcat服务器回复给客户端的数据是英文的"Login Success","Login Failed".

现在我们改成如下的汉字:

 package com.himi.web;

 import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; /**
* Servlet implementation class LoginServlet
*/
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L; /**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String qq = request.getParameter("qq");
String password = request.getParameter("password");
System.out.println("qq:"+qq);
System.out.println("password:"+password); //模拟服务器操作,查询数据库,看qq和密码是否正确. response.getOutputStream()获得一个输出流,向浏览器写入数据(提示数据)
if("10086".equals(qq) && "123456".equals(password)) {
response.getOutputStream().write("登录成功".getBytes());
}else {
response.getOutputStream().write("登录失败".getBytes());
} } }

这时候,我们布署之前的Android手机端http程序到模拟器上,运行产生如下效果:

2.常见的乱码处理

(1)菱形里面有问号 : gbk的中文数据用utf-8表示的

Tomcat默认的编码是iso-8859-1的码表,没有中文,如果遇到了不认识的字符串就使用本地默认编码gbk;

当我们把这些gbk编码数据通过http协议传递给手机Android客户端的时候,Android客户端的默认编码是utf-8.所以会出现这样的问题。

这个乱码解决问题的方式:在客户端或者服务器端任意一端(不能同时修改两端).比如服务器端把回复数据编码改成utf-8,要么就是客户端把接收到数据指定以gb2312。

(2)中文用户名输入出现乱码

• 手机客户端

还是之前的qq登录的案例,这里输入中文:

点击登录之后,服务器端接收到数据,显示乱码,效果如下:出现?乱码

• PC端浏览器

这里也是输入中文用户名,如下:

结果出现乱码如下:出现的?乱码

(3)PC端到服务器端的乱码问题解决:

PC端到服务器端的乱码是由于之前客户端是以utf-8流的方式把中文用户名,传递给服务器端,服务端默认编码是ios-8859-1,它是不能识别中文的。

所以服务器端以ios-8859-1的方式显示数据,就会上面的问号乱码。

解决办法:修改服务器端代码,如下:

qq.getBytes("iso-8859-1"),这里必须指定iso-8859-1的方式,不然会默认是系统本地编码gb2312;

此时再次在浏览器提交数据,服务器端就不会出现乱码,如下:

(4)GET客户端到服务器端的乱码问题解决:

上面只是解决PC端到服务器端的乱码出现的问题,但是客户端到服务器端的乱码还是没有解决,如下:

这里我们知道get方式是组拼url路径的,提交的数据包含在这个路径下,提交的数据要是包含中文或者其他不合法字符就会转化,就如下:

解决方法:拼接url的路径时候,对中文进行转化:

(5)POST客户端到服务器端的乱码问题解决:

之前POST方式编写的QQ登录案例,直接布署程序到模拟器上会出现如下错误:

解决办法:

 package com.himi.post;

 import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL; import android.app.Activity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast; public class MainActivity extends Activity {
private static final String Tag = "MainActivity";
private EditText et_qq;
private EditText et_pwd;
private CheckBox cb_remember; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//查询关心的控件
et_qq = (EditText) findViewById(R.id.et_qq);
et_pwd = (EditText) findViewById(R.id.et_pwd);
cb_remember = (CheckBox) findViewById(R.id.cb_remember);
Log.i(Tag,"oncreate 被调用");
//完成数据的回显。
readSavedData();
}
//读取保存的数据
private void readSavedData() {
// getFilesDir() == /data/data/包名/files/ 获取文件的路径 一般系统是不会清理的。 用户手工清理,系统会有提示。
// getCacheDir()== /data/data/包名/cache/ 缓存文件的路径 当系统内存严重不足的时候 系统会自动的清除缓存 用户手工清理系统没有提示
File file = new File(getFilesDir(),"info.txt");
if(file.exists()&&file.length()>0){
try {
//FileInputStream fis = new FileInputStream(file);
FileInputStream fis =this.openFileInput("info.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
//214342###abcdef
String info = br.readLine();
String qq = info.split("###")[0];
String pwd = info.split("###")[1];
et_qq.setText(qq);
et_pwd.setText(pwd);
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 登陆按钮的点击事件,在点击事件里面获取数据
* @param view
*/
public void login(View view){
final String qq = et_qq.getText().toString().trim();
final String pwd = et_pwd.getText().toString().trim();
if(TextUtils.isEmpty(qq)||TextUtils.isEmpty(pwd)){
Toast.makeText(this, "qq号码或者密码不能为空", 0).show();
return;
}
//判断用户是否勾选记住密码。
if(cb_remember.isChecked()){
//保存密码
Log.i(Tag,"保存密码");
try {
// File file = new File(getFilesDir(),"info.txt");
// FileOutputStream fos = new FileOutputStream(file);
FileOutputStream fos = this.openFileOutput("info.txt", 0);
//214342###abcdef
fos.write((qq+"###"+pwd).getBytes());
fos.close();
Toast.makeText(this, "保存成功", 0).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, "保存失败", 0).show();
}
}else{
//无需保存密码
Log.i(Tag,"无需保存密码");
} //登录的操作,网络的请求
new Thread() {
public void run() {
//post请求提交数据
//String path = "http://localhost:8080/web/LoginServlet";这里不能写成localhost
try {
String path = getString(R.string.serverip);
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//重要,记得设置请求方式post
conn.setRequestMethod("POST");
//重要,记得设置数据的类型
conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
String data = "qq="+URLEncoder.encode(qq,"utf-8")+"&password="+URLEncoder.encode(pwd,"utf-8");
//重要,记得设置数据的长度
conn.setRequestProperty("Content-Length", String.valueOf(data.length())); //重要,记得给服务器写数据
conn.setDoOutput(true);//声明要给服务器写数据
//重要,把数据写给服务器
conn.getOutputStream().write(data.getBytes()); int code = conn.getResponseCode();
if(code == 200) {
InputStream is = conn.getInputStream();
String result = StreamTools.readStream(is);
showToastInAnyThread(result);
}else {
showToastInAnyThread("请求失败");
}
} catch (Exception e) {
e.printStackTrace();
showToastInAnyThread("请求失败");
}
};
}.start(); } /**
* 显示土司 在主线程更新UI
* @param text
*/
public void showToastInAnyThread(final String text) {
runOnUiThread(new Runnable() { public void run() {
Toast.makeText(MainActivity.this, text, 0).show(); }
});
}
}

这时候我们输入提交数据给服务器就不会出现乱码,如下:

(6)HttpClient-Get客户端到服务器端的乱码问题解决:

  1 package com.himi.post;
2 import java.io.BufferedReader;
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.FileOutputStream;
6 import java.io.InputStream;
7 import java.io.InputStreamReader;
8 import org.apache.http.HttpResponse;
9 import org.apache.http.client.HttpClient;
10 import org.apache.http.client.methods.HttpGet;
11 import org.apache.http.impl.client.DefaultHttpClient;
12 import android.app.Activity;
13 import android.os.Bundle;
14 import android.text.TextUtils;
15 import android.util.Log;
16 import android.view.View;
17 import android.widget.CheckBox;
18 import android.widget.EditText;
19 import android.widget.Toast;
20 public class MainActivity extends Activity {
21 private static final String Tag = "MainActivity";
22 private EditText et_qq;
23 private EditText et_pwd;
24 private CheckBox cb_remember;
25 @Override
26 protected void onCreate(Bundle savedInstanceState) {
27 super.onCreate(savedInstanceState);
28 setContentView(R.layout.activity_main);
29 //查询关心的控件
30 et_qq = (EditText) findViewById(R.id.et_qq);
31 et_pwd = (EditText) findViewById(R.id.et_pwd);
32 cb_remember = (CheckBox) findViewById(R.id.cb_remember);
33 Log.i(Tag,"oncreate 被调用");
34 //完成数据的回显。
35 readSavedData();
36 }
37 //读取保存的数据
38 private void readSavedData() {
39 // getFilesDir() == /data/data/包名/files/ 获取文件的路径 一般系统是不会清理的。 用户手工清理,系统会有提示。
40 // getCacheDir()== /data/data/包名/cache/ 缓存文件的路径 当系统内存严重不足的时候 系统会自动的清除缓存 用户手工清理系统没有提示
41 File file = new File(getFilesDir(),"info.txt");
42 if(file.exists()&&file.length()>0){
43 try {
44 //FileInputStream fis = new FileInputStream(file);
45 FileInputStream fis =this.openFileInput("info.txt");
46 BufferedReader br = new BufferedReader(new InputStreamReader(fis));
47 //214342###abcdef
48 String info = br.readLine();
49 String qq = info.split("###")[0];
50 String pwd = info.split("###")[1];
51 et_qq.setText(qq);
52 et_pwd.setText(pwd);
53 fis.close();
54 } catch (Exception e) {
55 e.printStackTrace();
56 }
57 }
58 }
59 /**
60 * 登陆按钮的点击事件,在点击事件里面获取数据
61 * @param view
62 */
63 public void login(View view){
64 final String qq = et_qq.getText().toString().trim();
65 final String pwd = et_pwd.getText().toString().trim();
66 if(TextUtils.isEmpty(qq)||TextUtils.isEmpty(pwd)){
67 Toast.makeText(this, "qq号码或者密码不能为空", 0).show();
68 return;
69 }
70 //判断用户是否勾选记住密码。
71 if(cb_remember.isChecked()){
72 //保存密码
73 Log.i(Tag,"保存密码");
74 try {
75 // File file = new File(getFilesDir(),"info.txt");
76 // FileOutputStream fos = new FileOutputStream(file);
77 FileOutputStream fos = this.openFileOutput("info.txt", 0);
78 //214342###abcdef
79 fos.write((qq+"###"+pwd).getBytes());
80 fos.close();
81 Toast.makeText(this, "保存成功", 0).show();
82 } catch (Exception e) {
83 e.printStackTrace();
84 Toast.makeText(this, "保存失败", 0).show();
85 }
86 }else{
87 //无需保存密码
88 Log.i(Tag,"无需保存密码");
89 }
90
91 //登录的操作,网络的请求
92 new Thread() {
93 public void run() {
94 //String path = "http://localhost:8080/web/LoginServlet";这里不能写成localhost
95 try {
96 //httpclient get请求提交数据
97 String path = getString(R.string.serverip)+"?qq="+URLEncoder.encode(qq)+"&password="+URLEncoder.encoder(pwd);
98 //1.打开浏览器
99 HttpClient client = new DefaultHttpClient();
100 //2.输入地址
101 HttpGet httpGet = new HttpGet(path);
102 //3.敲回车
103 HttpResponse response = client.execute(httpGet);
104 int code = response.getStatusLine().getStatusCode();
105 if(code == 200) {
106 InputStream is = response.getEntity().getContent();
107 String result = StreamTools.readStream(is);
108 showToastInAnyThread(result);
109 }else {
110 showToastInAnyThread("请求失败,返回码是:"+code);
111 }
112
113
114 } catch (Exception e) {
115 e.printStackTrace();
116 showToastInAnyThread("请求失败");
117 }
118 };
119 }.start();
120
121 }
122
123 /**
124 * 显示土司 在主线程更新UI
125 * @param text
126 */
127 public void showToastInAnyThread(final String text) {
128 runOnUiThread(new Runnable() {
129
130 public void run() {
131 Toast.makeText(MainActivity.this, text, 0).show();
132
133 }
134 });
135 }
136
}

(7)HttpClient-Post客户端到服务器端的乱码问题解决:

  1 package com.himi.post;
2 import java.io.BufferedReader;
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.FileOutputStream;
6 import java.io.InputStream;
7 import java.io.InputStreamReader;
8 import java.util.ArrayList;
9 import java.util.List;
10 import org.apache.http.HttpResponse;
11 import org.apache.http.NameValuePair;
12 import org.apache.http.client.HttpClient;
13 import org.apache.http.client.entity.UrlEncodedFormEntity;
14 import org.apache.http.client.methods.HttpPost;
15 import org.apache.http.impl.client.DefaultHttpClient;
16 import org.apache.http.message.BasicNameValuePair;
17 import android.app.Activity;
18 import android.os.Bundle;
19 import android.text.TextUtils;
20 import android.util.Log;
21 import android.view.View;
22 import android.widget.CheckBox;
23 import android.widget.EditText;
24 import android.widget.Toast;
25 public class MainActivity extends Activity {
26 private static final String Tag = "MainActivity";
27 private EditText et_qq;
28 private EditText et_pwd;
29 private CheckBox cb_remember;
30 @Override
31 protected void onCreate(Bundle savedInstanceState) {
32 super.onCreate(savedInstanceState);
33 setContentView(R.layout.activity_main);
34 //查询关心的控件
35 et_qq = (EditText) findViewById(R.id.et_qq);
36 et_pwd = (EditText) findViewById(R.id.et_pwd);
37 cb_remember = (CheckBox) findViewById(R.id.cb_remember);
38 Log.i(Tag,"oncreate 被调用");
39 //完成数据的回显。
40 readSavedData();
41 }
42 //读取保存的数据
43 private void readSavedData() {
44 // getFilesDir() == /data/data/包名/files/ 获取文件的路径 一般系统是不会清理的。 用户手工清理,系统会有提示。
45 // getCacheDir()== /data/data/包名/cache/ 缓存文件的路径 当系统内存严重不足的时候 系统会自动的清除缓存 用户手工清理系统没有提示
46 File file = new File(getFilesDir(),"info.txt");
47 if(file.exists()&&file.length()>0){
48 try {
49 //FileInputStream fis = new FileInputStream(file);
50 FileInputStream fis =this.openFileInput("info.txt");
51 BufferedReader br = new BufferedReader(new InputStreamReader(fis));
52 //214342###abcdef
53 String info = br.readLine();
54 String qq = info.split("###")[0];
55 String pwd = info.split("###")[1];
56 et_qq.setText(qq);
57 et_pwd.setText(pwd);
58 fis.close();
59 } catch (Exception e) {
60 e.printStackTrace();
61 }
62 }
63 }
64 /**
65 * 登陆按钮的点击事件,在点击事件里面获取数据
66 * @param view
67 */
68 public void login(View view){
69 final String qq = et_qq.getText().toString().trim();
70 final String pwd = et_pwd.getText().toString().trim();
71 if(TextUtils.isEmpty(qq)||TextUtils.isEmpty(pwd)){
72 Toast.makeText(this, "qq号码或者密码不能为空", 0).show();
73 return;
74 }
75 //判断用户是否勾选记住密码。
76 if(cb_remember.isChecked()){
77 //保存密码
78 Log.i(Tag,"保存密码");
79 try {
80 // File file = new File(getFilesDir(),"info.txt");
81 // FileOutputStream fos = new FileOutputStream(file);
82 FileOutputStream fos = this.openFileOutput("info.txt", 0);
83 //214342###abcdef
84 fos.write((qq+"###"+pwd).getBytes());
85 fos.close();
86 Toast.makeText(this, "保存成功", 0).show();
87 } catch (Exception e) {
88 e.printStackTrace();
89 Toast.makeText(this, "保存失败", 0).show();
90 }
91 }else{
92 //无需保存密码
93 Log.i(Tag,"无需保存密码");
94 }
95
96 //登录的操作,网络的请求
97 new Thread() {
98 public void run() {
99 //post请求提交数据
100 //String path = "http://localhost:8080/web/LoginServlet";这里不能写成localhost
101 try {
102 String path = getString(R.string.serverip);
103 //1.打开浏览器
104 HttpClient client = new DefaultHttpClient();
105 //2.输入地址
106 HttpPost httpPost = new HttpPost(path);
107 //设置一个url的表单的数据
108 List<NameValuePair> paramters = new ArrayList<NameValuePair>();
109 paramters.add(new BasicNameValuePair("qq", qq));
110 paramters.add(new BasicNameValuePair("password", pwd));
111 httpPost.setEntity(new UrlEncodedFormEntity(paramters,"utf-8"));
112 //3.敲回车
113 HttpResponse response = client.execute(httpPost);
114 int code = response.getStatusLine().getStatusCode();
115 if(code == 200) {
116 InputStream is = response.getEntity().getContent();
117 String result = StreamTools.readStream(is);
118 showToastInAnyThread(result);
119 }else {
120 showToastInAnyThread("请求失败,返回码是:"+code);
121 }
122
123 } catch (Exception e) {
124 e.printStackTrace();
125 showToastInAnyThread("请求失败");
126 }
127 };
128 }.start();
129
130 }
131
132 /**
133 * 显示土司 在主线程更新UI
134 * @param text
135 */
136 public void showToastInAnyThread(final String text) {
137 runOnUiThread(new Runnable() {
138
139 public void run() {
140 Toast.makeText(MainActivity.this, text, 0).show();
141
142 }
143 });
144 }
145 }

Android(java)学习笔记212:中文乱码的问题处理(qq登录案例)的更多相关文章

  1. Android(java)学习笔记155:中文乱码的问题处理(qq登录案例)

    1. 我们在之前的笔记中LoginServlet.java中,我们Tomcat服务器回复给客户端的数据是英文的"Login Success","Login Failed& ...

  2. Android(java)学习笔记213:开源框架post和get方式提交数据(qq登录案例)

    1.前面提到Http的get/post方式  . HttpClient方式,实际工作的时候不常用到,因为这些方式编写代码是很麻烦的 2.Android应用会经常使用http协议进行传输,网上会有很完善 ...

  3. Android(java)学习笔记156:开源框架post和get方式提交数据(qq登录案例)

    1. 前面提到Http的get/post方式  . HttpClient方式,实际工作的时候不常用到,因为这些方式编写代码是很麻烦的 2. Android应用会经常使用http协议进行传输,网上会有很 ...

  4. 《Java学习笔记(第8版)》学习指导

    <Java学习笔记(第8版)>学习指导 目录 图书简况 学习指导 第一章 Java平台概论 第二章 从JDK到IDE 第三章 基础语法 第四章 认识对象 第五章 对象封装 第六章 继承与多 ...

  5. java学习笔记12--国际化

    java学习笔记12--国际化 国际化的操作就是指一个程序可以同时适应多门语言,即:如果现在程序者是中国人,则会以中文为显示文字,如果现在程序的使用者是英国人,则会以英语为显示的文字,也就是说可以通过 ...

  6. 0028 Java学习笔记-面向对象-Lambda表达式

    匿名内部类与Lambda表达式示例 下面代码来源于:0027 Java学习笔记-面向对象-(非静态.静态.局部.匿名)内部类 package testpack; public class Test1{ ...

  7. Android自动化学习笔记之MonkeyRunner:官方介绍和简单实例

    ---------------------------------------------------------------------------------------------------- ...

  8. Android动画学习笔记-Android Animation

    Android动画学习笔记-Android Animation   3.0以前,android支持两种动画模式,tween animation,frame animation,在android3.0中 ...

  9. Java学习笔记:语言基础

    Java学习笔记:语言基础 2014-1-31   最近开始学习Java,目的倒不在于想深入的掌握Java开发,而是想了解Java的基本语法,可以阅读Java源代码,从而拓展一些知识面.同时为学习An ...

随机推荐

  1. 过滤器(Filter)

    day21 过滤器概述 1 什么是过滤器 过滤器JavaWeb三大组件之一,它与Servlet很相似!不它过滤器是用来拦截请求的,而不是处理请求的. 当用户请求某个Servlet时,会先执行部署在这个 ...

  2. Java面试题相关内容

    选择题(共5题,每题1.5分,共75分.多选题选不全或选错都不得分.)1. 以下属于面向对象的特征的是(C,D).(两项)A) 重载B) 重写C) 封装D) 继承 2. 以下代码运行输出是(C)pub ...

  3. Android 模拟HTTP协议的编码问题 Android默认编码UTF-8

    Android通过GET和POST方法请求服务器和浏览器请求的过程是不一样的. 浏览器请求服务器的时候会先将中文进行UTF-8编码,然后再发送到服务器端. Android编程下我们需要通过URLEnc ...

  4. windows驱动开发推荐书籍

    [作者] 猪头三 个人网站 :http://www.x86asm.com/ [序言] 很多人都对驱动开发有兴趣,但往往找不到正确的学习方式.当然这跟驱动开发的本土化资料少有关系.大多学的驱动开发资料都 ...

  5. 【HDOJ】1422 重温世界杯

    简单题. #include <stdio.h> #define MAXN 100005 int wi[MAXN], li[MAXN]; ]; int main() { int n, tot ...

  6. Linux Shell编程(22)——时间/日期 命令

    date直接调用, date 就会打印日期和时间到 stdout 上. 这个命令有趣的地方在于它的格式化和分析选项上.time输出统计出来的命令执行的时间.touch这是一个用来更新文件被存取或修改的 ...

  7. c#后台验证

    #region 后台验证 panda /// 验证电话号码的主要代码如下: public bool IsTelephone(string str_telephone) { return System. ...

  8. 博弈论(男人八题):POJ 1740 A New Stone Game

    A New Stone Game Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 5694   Accepted: 3119 ...

  9. [转]33 useful Keyboard Shortcuts for Run commond

    原文: http://www.shortcutworld.com/en/win/Run-command.html 1. Calling Run CommandWin + r               ...

  10. 苹果Think Different广告

    电视广告版: Here’s to the crazy ones. The misfits. The rebels. The troublemakers. The round pegs in the s ...