Linux(SUSE) NFS mount挂载

被mount的机器(服务机)10.10.10.209

1 创建共享文件夹/data/attachment

2 修改/etc/exports,加入

/data/attachments 10.10.10.207(rw,no_root_squash,sync,insecure)

多个服务器如下:

/data/attachments 10.10.10.207(rw,no_root_squash,sync,insecure) 10.10.10.208(rw,no_root_squash,sync,insecure)

3 重启相关服务(顺序按下面的进行)

1
2
3
4
service rpcbind stop
service nfsserver stop
service rpcbind start
service nfsserver start

mount的机器(客户机)10.10.10.207

  • 1 创建文件夹/data/attachment

  • 2 修改/etc/fstab,加入
    10.10.103.209:/data/attachments /data/attachments nfs defaults 0 0

  • 3 输入mount -a 使其生效

  • 4 测试–>输入:showmount -e 10.10.103.209,查看本机的共享目录
    如果输出:
    Export list for 10.10.103.209:
    /data/attachments *
    则测试成功

整体测试

在服务机/data/attachment下创建文件,如果在客户机下同样目录下出现次文件,说明成功

参考资料

Sencha实现国际化,JS动态加载js、css文件

  1. 新建文件messages_en.js和messages_zh_CN.js文件;
  2. 文件中定义js全局变量 var Messages = {};
    例:messages_zh_CN.js文件 Messages = {“title”:“标题”};
    message_en.js文件 Messages = {“title”:“title”};
  3. 在Sencha应用入口launch : function(){}中,先获取用户的语言,然后通过不同的语言去加载不同的JS文件;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    /**  
    * 动态加载文件
    * @param fileName 文件名(包含后缀名)
    * .js:放在js文件夹下;.css:放在css文件夹下
    * @param 回调
    */
    loadJSCSSFile : function(fileName, callback){
    var fileref = null;
    var arr = fileName.split('.');
    switch(arr[arr.length - 1]) {
    case 'js':
    fileref = document.createElement('script');
    fileref.setAttribute('type', 'text/javascript');
    fileref.setAttribute('src', 'js/' + fileName);
    break;
    case 'css':
    fileref = document.createElement('link');
    fileref.setAttribute('rel', 'stylesheet');
    fileref.setAttribute('type', 'text/css');
    fileref.setAttribute('herf', 'css/' + fileName);
    break;
    }
    if(fileref != null) {
    if (fileref.readyState) { // IE
    fileref.onreadystatechange = function() {
    if (fileref.readyState == 'loaded' || fileref.readyState == 'complete') {
    fileref.onreadystatechange = null;
    callback();
    }
    };
    } else { // Others: Firefox, Safari, Chrome, and Opera
    fileref.onload = function() {
    callback();
    };
    }
    document.getElementsByTagName('head')[0].appendChild(fileref);
    }
    },
  4. 需要国际化的文字都在文件中以(key, value)的形式保存,用的时候,直接Messages.title

JAVA调用https, JS跨域请求,客户端解决JS跨域问题, SOP

同源协议 (SOP,Same-Origin-Policy) 可防止从一个来源加载的脚本获取或操纵来自另一来源的文档的属性或方法。术语来源 是域名、应用程序协议和运行脚本文档的端口的结合。可能存在关于 SOP 概念的一些误解;SOP 指只能从站点 A、不能从站点 B 获取信息。您需要知道在 SOP 限制下可以做什么,不可以做什么。

1.JAVA https请求

在做微信服务号的时候出现的问题,解决方法:自定义证书管理器。证书管理器的作用就是让它信任我们指定的证书,意味着信任所有证书,不管是否权威机构颁发,证书有了,通用的https请求方法就不难实现了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package com.qq.weixin.util;  
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

/**
* 公众平台通用接口工具类
* from==>
* shttp://blog.csdn.net/lyq8479/article/details/9841371
* @author liuyq
* @date 2013-08-09
*/
public class WXHttpUtil {

/**
* 发起https请求并获取结果
*
* @param requestUrl 请求地址
* @param requestMethod 请求方式(GET、POST)
* @param outputStr 提交的数据
* @return String
*/
public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) throws Exception {
StringBuffer buffer = new StringBuffer();
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();

URL url = new URL(requestUrl);
HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
httpUrlConn.setSSLSocketFactory(ssf);

httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod);

if ("GET".equalsIgnoreCase(requestMethod))
httpUrlConn.connect();

// 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}

// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
String result = buffer.toString();
System.out.println("请求结果==>" + result);
return result;
}

/**
* 证书信任管理器(用于https请求)
*
* @author liufeng
* @date 2013-08-08
*/
public static class MyX509TrustManager implements X509TrustManager {

public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}

public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}

public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
}

2. JS跨域请求

在网上看了好多方法:

  • 1)iframe
  • 2)document.domain
  • 3)window.name
  • 4)script
  • 5)XDomainRequest (IE8+)
  • 6)XMLHTTPRequest (Firefox3.5+)
  • 7)postMessage (HTML5)
  • 8)后台代理

本文此处讲解一下JsonP的处理注意事项

JSONP的实现思路很简单

  • 1)前端创建script标记,设置src,添加到head中(你可以往body中添加);
  • 2)后台返回一个js变量jsonp,这个jsonp就是请求后的JSON数据;
  • 3)回调完成后删除script标记(还有一些清理工作如避免部分浏览器内存泄露等)。

客户端直接使用JsonP请求:

1
2
3
4
5
6
7
8
9
10
11
12
$.ajax({    
url:"http://crossdomain.com/services.php",
dataType:'jsonp',
data:'',
jsonp:'callback',
success:function(result) {
for(var i in result) {
alert(i+":"+result[i]);//循环输出a:1,b:2,etc.
}
},
timeout:3000
});

服务器端处理:(Play Framework写的服务器)

1
2
3
String callback = request.params.get("callback");  
String result = callback + "(" + JSON.toJSONString(dataMap) + ")";
renderText(result);

返回时数据用callback+()包上。

3. 利用客户端解决方案改进跨域通信

http://www.ibm.com/developerworks/cn/web/wa-crossdomaincomm/

ScrollView内嵌ViewPager导致ViewPager滑动困难问题

解决方式:重写ScrollView,然后在xml中定义布局的时候,使用自定义的PagerScrollView而不是系统的ScrollView即可。

重点在于重写父类的onInterceptTouchEvent方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import android.content.Context;  
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.widget.ScrollView;

public class PagerScrollView extends ScrollView {

private GestureDetector mGestureDetector;

public PagerScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}

public PagerScrollView(Context context) {
super(context);
init();
}

public PagerScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}

private void init() {
mGestureDetector = new GestureDetector(getContext(),
new YScrollDetector());
setFadingEdgeLength(0);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return super.onInterceptTouchEvent(ev)
&& mGestureDetector.onTouchEvent(ev);
}

private class YScrollDetector extends SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {

if (Math.abs(distanceY) >= Math.abs(distanceX)) {
return true;
}
return false;
}
}
}

Android自己管理Activity和Service

在一些特殊情况下,我们需要对Activity Task进行管理。

当然,我们最好还是不要自己去控制,以免发生一些不必要的麻烦。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package com.anjoyo.musicplayer.util;  

import java.util.List;

import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;

public class ContextManagerUtil {

/**
* @param context 上下文
* @param className 服务类的名称
* @return 返回服务是否还在后台运行
*/
public static boolean isServiceRunning(Context context,Class<?> obj) {

boolean isRunning = false;
ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> serviceList = activityManager.getRunningServices(30);

if (!(serviceList.size()>0)) {
return false;
}

for (int i=0; i<serviceList.size(); i++) {
if (serviceList.get(i).service.getClassName().equals(obj.getName()) == true) {
isRunning = true;
break;
}
}
return isRunning;
}

/**
* 返回本程序中Task中顶端的Activity
* @param context
* @return
*/
public static ComponentName getTopActivity(Context context) {
//需要android.permission.GET_TASKS权限
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
int maxNum = 10;//获取的正在运行的activity的最大数量
List<ActivityManager.RunningTaskInfo> runningTasks = activityManager.getRunningTasks(maxNum);
for (ActivityManager.RunningTaskInfo runningTaskInfo : runningTasks) {
ComponentName componentName = runningTaskInfo.topActivity;
if (componentName != null && componentName.getClassName().startsWith("com.anjoyo.musicplayer")) {
return componentName;
}
}

return null;
}


}

Bitmap too large to be uploaded into a texture,Hardware accelerated

Android的硬件加速及可能导致的问题

问题

在Android 4.0的某些设备上,在View刷新时会出现花屏和屏幕上的某些View错位的现象。 经过调查后发现adb logcat中出现很多OpenGLRenderer: 0x501的错位:

1
2
3
09-18 14:34:39.090: DEBUG/OpenGLRenderer(3104): GL error from OpenGLRenderer: 0x501
09-18 14:34:39.386: DEBUG/OpenGLRenderer(3104): GL error from OpenGLRenderer: 0x501
09-18 14:34:39.656: DEBUG/OpenGLRenderer(3104): GL error from OpenGLRenderer: 0x501

从这个日志,初步怀疑是硬件加速导致的问题。 经过分析发现使用了比较复杂的自定义View,可能会导致硬件加速渲染出错。

硬件加速的优点与缺点

硬件加速能使用GPU来加速2D图像的渲染速度,但是硬件加速并不能完全支持所有的渲染操作, 针对自定义的View,硬件加速可能导致渲染出现错误。 如果有自定义的View,需要在硬件加速的设备上进行测试,如果出现渲染的问题,需要关闭硬件加速。

开启和关闭硬件加速

对硬件加速的开关可以在不同的级别进行控制:

  • Application
  • Activity
  • Windows
  • View

1. Application级别

在Applciation级别控制硬件加速的开关

1
<application android:hardwareAccelerated="true" ...>

2. Activity级别

可以对单个的Activity控制是否启用硬件加速:

1
2
3
4
<application android:hardwareAccelerated="true">
<activity ... />
<activity android:hardwareAccelerated="false" />
</application>

3. Window级别

在指定的View上关闭硬件加速:

1
myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

或者使用android:layerType="software"来关闭硬件加速:

1
2
3
4
5
6
7
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:paddingLeft="2dp"
android:layerType="software"
android:paddingRight="2dp" />

如何判断一个View是否启用了硬件加速

View.isHardwareAccelerated() returns true if the View is attached to a hardware accelerated window.

Canvas.isHardwareAccelerated() returns true if the Canvas is hardware accelerated

参考:http://developer.android.com/guide/topics/graphics/hardware-accel.html

fastjson使用public修饰 private转化Object有问题 注意事项

版本:fastjson.jar 1.1.33

字段为非StringObject时,若不是使用public修饰,则必须有对应的get、set方法,

字段类选为boolean时,必须使用public;

综合各种考虑,应当直接全部使用public修饰!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import java.util.ArrayList;  
import java.util.List;

import com.alibaba.fastjson.JSON;

class User {
public Long id;
public String name;
int age;
public String adress;
List<String> teachers;
public void setTeachers(List<String> teachers) {
this.teachers = teachers;
}
public List<String> getTeachers(){
return this.teachers;
}
}

public class Test {
public static void main(String[] args) {
List<String> teachers = new ArrayList<>();
for (int i = 0; i < 5; i++) {
teachers.add(i+"");
}
User rootUser = new User();
rootUser.id = 3L;
rootUser.name = "root";
rootUser.teachers = teachers;
// rootUser.setTeachers(teachers);

String jsonString = JSON.toJSONString(rootUser);

System.out.println(jsonString);

User user = JSON.parseObject(jsonString, User.class);

System.out.println(user.id);
// System.out.println(user.getTeachers());
System.out.println(user.teachers);

}
}

MQTT mosquitto的初步学习

mosquitto简介

MQTT(MQ Telemetry Transport),消息队列遥测传输协议,轻量级的发布/订阅协议,适用于一些条件比较苛刻的环境,进行低带宽、不可靠或间歇性的通信。
Mosquitto是一个开源(BSD许可证)的消息代理,实现MQTT(消息队列遥测传输)协议版本3.1。

为每个MQTT消息头命令消息包含一个固定头,头只有两个字节,格式如下:

消息头

参考:http://public.dhe.ibm.com/software/dw/webservices/ws-mqtt/mqtt-v3r1.html#msg-format

一、安装mosquitto服务

本文仅介绍mosquitto在Windows上的安装,Linux系统与之类似

在mosquitto官网下载安装包http://mosquitto.org/files/binary/win32/mosquitto-1.2.3-install-win32.exe
下载之后直接安装即可

二、配置和运行

可参照http://www.cnblogs.com/li-baibo/archive/2013/01/21/2869225.html

三、在客户端的使用(Java)

pc 端客户端,下载地址:http://download.csdn.net/detail/kuailebeihun/7312947
解压,运行\ia92\J2SE\wmqttSample.jar即可

1. 客户端使用的库

下载地址:http://download.csdn.net/detail/kuailebeihun/7312731(JDK环境1.6及以上,若以下请下载源码开发)

2. 客户端 库 的源码

下载地址:http://download.csdn.net/detail/kuailebeihun/7312743

3. 具体使用

(1)消息质量

0: “至多一次”,消息发布完全依赖底层 TCP/IP 网络。会发生消息丢失或重复。这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送;
1 :“至少一次”,确保消息到达,但消息重复可能会发生;
2:“只有一次”,确保消息到达一次。这一级别可用于如下情况,在计费系统中,消息重复或丢失会导致不正确的结果。

(2)消息主题

构建一个应用程序时,主题树的设计应考虑以下主题名称的语法和语义的原则:
主题必须至少一个字符长;  
主题名称是区分大小写的,例如,A和a是两个不同的主题;
“/”创造了一个独特的主题,例如,/a与a是不同的主题。/a匹配“+/+”和“/+”,但不匹配“+”; 
任何主题不包含空字符(Unicode \ x0000)。  

以下原则适用于主题树的结构和内容:     
64 k的长度是有限的,但在没有限制水平主题树的数量。  
可以有任意数量的根节点,也就是说,可以有任意数量的主题树。

(3) subscribe订阅

使用正斜杠(/)分隔主题树中的每个级别,并提供一个主题空间的层次结构。主题层面分离器的使用中遇到两个通配符时重要的主题由用户指定。

数字符号(#)是一个通配符匹配任意数量的水平在一个主题,只能用在最后,如a/#/c是不合法的
例如,如果你订阅a/b/c/#,你在这些主题接收消息:
a/b/c
a/b/c/d
a/b/c/e

加号(+)是一个通配符匹配的主题只有一个水平
例如,如果你订阅a/+/c/#,你在这些主题:接收消息:
a/a/c/
a/b/c/d
a/c/c/e

若订阅”+/#”,此主题可接受所有类型主题的消息

(4) publish发布

发布的时候主题时,+或者#不能通配,是且仅是一个明确的主题。

贴上一段简单代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import org.eclipse.paho.client.mqttv3.MqttCallback;  
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttSecurityException;
import org.eclipse.paho.client.mqttv3.MqttTopic;
import org.eclipse.paho.client.mqttv3.internal.MemoryPersistence;

/**
*
* @author LP by 2014-04-24
*
*/
public class MqttServiceClient implements MqttCallback {

private static final String MQTT_HOST = "tcp://192.168.12.38:1883";
private static final String MQTT_CLIENT = "Test_";

public static MqttServiceClient mqttServiceClient = null;

private MqttClient client = null;
private MqttConnectOptions options = null;

/**
* 单例模式构造类
*/
public static MqttServiceClient getInstance() {
if (mqttServiceClient == null) {
mqttServiceClient = new MqttServiceClient();
}
return mqttServiceClient;
}

private MqttServiceClient() {
System.out.println("init MQTTClientService");
init();
}
// The major API implementation follows :-

/**
* 初始化
*/
private void init() {
try {

// host为主机名,test为clientid即连接MQTT的客户端ID,一般以客户端唯一标识符表示,MemoryPersistence设置clientid的保存形式,默认为以内存保存
client = new MqttClient(MQTT_HOST, MQTT_CLIENT, new MemoryPersistence());
// MQTT的连接设置
options = new MqttConnectOptions();
// 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,这里设置为true表示每次连接到服务器都以新的身份连接
options.setCleanSession(true);
// 设置连接的用户名
// options.setUserName(userName);
// 设置连接的密码
// options.setPassword(passWord.toCharArray());
// 设置超时时间 单位为秒
options.setConnectionTimeout(50);
// 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
options.setKeepAliveInterval(30);
// 设置回调
client.setCallback(this);

} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 连接到MQTT
*/
void connect() {
System.out.println("Start connect----------");
try {
client.connect(options);
//订阅主题的方法,2为消息的质量
client.subscribe("+/#", 2);
//发送消息
publish("test", "撒打发水电费水电费");
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 断开连接到MQTT
*/
public void disconnect() {
System.out.println("Start disconnect----------");
try {
client.disconnect();
} catch (MqttSecurityException e) {
e.printStackTrace();
} catch (MqttException e) {
e.printStackTrace();
}
}

/**
* 发布消息
* @param topic 主题
* @param msg 消息
*/
public void publish(String topic, String msg) {
System.out.println("Start publish----------");
try {
MqttTopic mqttTopic = client.getTopic(topic);
//2为消息的质量
MqttDeliveryToken messageToken = mqttTopic.publish(msg.getBytes(), 2, true);
System.out.println("publish success==>"+messageToken.getMessage());
// client.publish(topic, 2, msg);
} catch (Exception e) {
e.printStackTrace();
}
}


// -------------------------------------------------回调方法------------------------------------------------------------//

/**
* 连接断开触发此方法
*/
@Override
public void connectionLost(Throwable cause) {
System.out.println("Connection Lost---------->" + cause.getMessage());
}

/**
* 消息达到触发此方法
*/
@Override
public void messageArrived(MqttTopic topic, MqttMessage message)
throws Exception {
System.out.println(topic + ":" + message.toString());
}

/**
* 消息发送成功触发此方法
*/
@Override
public void deliveryComplete(MqttDeliveryToken token) {
try {
System.out.println("deliveryComplete---------" + token.getMessage());
} catch (MqttException e) {
e.printStackTrace();
}
}


public static void main(String[] args)throws Exception {

MqttServiceClient.getInstance().disconnect();
MqttServiceClient.getInstance().connect();

new Thread() {
public void run() {
int count = 0;
while(true) {
try {
Thread.sleep(1000*3);
} catch (InterruptedException e) {
e.printStackTrace();
}
MqttServiceClient.getInstance().publish("AAA", "hello world ! count=" + count);
count ++;
}
};
}.start();
}

}

Java先序序列构造二叉树

BinaryTree.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package com.anjoyo.data_structures.tree;  

import java.util.Scanner;

/**
* 先序序列构造二叉树
* @author HLP
*
*/
public class BinaryTree {
static String[] arr = new String[100];
static int index = 0;

static {
@SuppressWarnings("resource")
Scanner scanner = new Scanner(System.in);
String str;
do {
str = scanner.next();
if ("over".equals(str)) {
break;
}
arr[index++] = str;
} while (true);
index = 0;
}

public static TNode create() {
TNode node = null;
String data = arr[index++];
if (! "null".equals(data)) {
node = new TNode(data);
node.lChild = create();
node.rChild = create();
}
return node;
}

public static void print(TNode node) {
if (node == null) {
return;
}else {
System.out.print(node.data + " --> ");
print(node.lChild);
print(node.rChild);
}
}

public static void main(String[] args) {
TNode biTree = null;
biTree = create();

print(biTree);
}
}

TNode.java

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.anjoyo.data_structures.tree;  

public class TNode {
String data;//值
TNode lChild;//左孩子
TNode rChild;//右孩子

public TNode(String data) {
this.data = data;
this.lChild = null;
this.rChild = null;
}
}

测试Test.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.anjoyo.data_structures.tree;  

class T {
int data;

public T(){}
public T(int data) {
this.data = data;
}
}

public class Test {

static T createT(){
T t2 = new T(32);
// t.data = 34;
// t = t2;
return t2;
}

public static void main(String[] args) {
T t = new T();
// createT(t);
System.out.println(t);
System.out.println(t.data);

T t2 = null;
t2 = createT();
System.out.println(t2);
System.out.println(t2.data);
}
}

Java实现表达式的运算-Android简易计算器

计算一个正确的字符串形式运算式(若要实现计算器,还需对表达式的合法性进行判断)

效果图

计算器效果图

运算代码CalculatorMathUtil.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import java.math.BigDecimal;  
import java.math.MathContext;
import java.util.Stack;

/**
* 计算一个正确的字符串形式运算式
* @author HLP
*
*/
public class CalculatorMathUtil {
/**
* 数据栈
*/
Stack<BigDecimal> number;
/**
* 符号栈
*/
Stack<Character> operator;
/**
* 计算除法时,设置的结果标度
*/
int length;

public CalculatorMathUtil(int length) {
this.length = length;
}

/**
* 获得计算结果的字符串表示形式
* @param exp
* @return
*/
public String getResult(String exp) {
this.number = new Stack<BigDecimal>();
this.operator = new Stack<Character>();
calculate(exp);
return this.number.peek().toString();
}

/**
* 对运算式exp进行解析,并计算
* @param exp
*/
public void calculate(String exp) {
int index = 0;
int sign = 0;
while (index < exp.length()) {
char op = exp.charAt(index);
if ((op <= '9' && op >= '0') || op == '.') {
index++;
} else {
if (index > 0) {
char opp = exp.charAt(index-1);
if (op == '-' && !((opp <= '9' && opp >= '0') || opp == '.')) {
index++;
continue;
}
}
if (sign != index) {
String numStr = exp.substring(sign, index);
BigDecimal num = new BigDecimal(numStr);
number.push(num);
}
analysis(op);
sign = ++index;
}
}
}

/**
* 对得到的数据和符号进行分析处理
* @param op
* @param num
*/
public void analysis(char op) {
if (operator.empty() || comparePriority(op, operator.peek())) {
operator.push(op);
} else {
makeNum(op);
}
}

/**
* 计算
* @param op
* @param num
*/
private void makeNum(char op) {
BigDecimal result = null;
while (!operator.empty() && !comparePriority(op, operator.peek())) {
char op2 = operator.pop();
if (op == ')' && op2 == '(') {
return;
}
BigDecimal num1 = null;
BigDecimal num2 = number.pop();
if (number.empty()) {
num1 = new BigDecimal(0);
} else {
num1 = number.pop();
}
switch (op2) {
case '+':
result = num1.add(num2);
break;
case '-':
result = num1.subtract(num2);
break;
case '*':
result = num1.multiply(num2);
break;
case '/':
result = num1.divide(num2, new MathContext(length));
break;
default:
operator.pop();
break;
}
number.push(result);
}
if (op != ')') {
operator.push(op);
}
}

/**
* 判断优先级:true(c1优先级高于c2)、false(c1优先级低于c2)
* @param c1
* @param c2
* @return
*/
public boolean comparePriority(char c1, char c2) {
if (c1 == '=') {
return false;
} else if (c1 == ')') {
return false;
} else if (c1 == '(') {
return true;
} else if (c2 == '(') {
return true;
} else if ((c1 == '*' || c1 == '/') && (c2 == '-' || c2 == '+')) {
return true;
} else {
return false;
}

}

}

CalculatorMainActivity.java

在输入的同时来保证表达式的合法性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
import com.anjoyo.lifelittlehelper.R;  

import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class CalculatorMainActivity extends Activity {

private TextView mShowTextView = null;
private StringBuffer mExpressBuffer = new StringBuffer();
private String mResult = "";
private static CalculatorMathUtil mCalculatorMathUtil = new CalculatorMathUtil(20);

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_calculator_main);

mShowTextView = (TextView) findViewById(R.id.tv_calculator_result);

}

public void clickMe(View v) {
if (mResult.length() > 0 && mExpressBuffer.toString().contains("=")) {
mExpressBuffer = new StringBuffer();
}
Button btn = (Button) v;
switch (btn.getId()) {
case R.id.btn_calculator_num_0:
if (mExpressBuffer.length() != 0 && mExpressBuffer.charAt(mExpressBuffer.length() - 1) == ')') {
break;
}
mExpressBuffer.append(0);
break;
case R.id.btn_calculator_num_1:
if (mExpressBuffer.length() != 0 && mExpressBuffer.charAt(mExpressBuffer.length() - 1) == ')') {
break;
}
mExpressBuffer.append(1);
break;
case R.id.btn_calculator_num_2:
if (mExpressBuffer.length() != 0 && mExpressBuffer.charAt(mExpressBuffer.length() - 1) == ')') {
break;
}
mExpressBuffer.append(2);
break;
case R.id.btn_calculator_num_3:
if (mExpressBuffer.length() != 0 && mExpressBuffer.charAt(mExpressBuffer.length() - 1) == ')') {
break;
}
mExpressBuffer.append(3);
break;
case R.id.btn_calculator_num_4:
if (mExpressBuffer.length() != 0 && mExpressBuffer.charAt(mExpressBuffer.length() - 1) == ')') {
break;
}
mExpressBuffer.append(4);
break;
case R.id.btn_calculator_num_5:
if (mExpressBuffer.length() != 0 && mExpressBuffer.charAt(mExpressBuffer.length() - 1) == ')') {
break;
}
mExpressBuffer.append(5);
break;
case R.id.btn_calculator_num_6:
if (mExpressBuffer.length() != 0 && mExpressBuffer.charAt(mExpressBuffer.length() - 1) == ')') {
break;
}
mExpressBuffer.append(6);
break;
case R.id.btn_calculator_num_7:
if (mExpressBuffer.length() != 0 && mExpressBuffer.charAt(mExpressBuffer.length() - 1) == ')') {
break;
}
mExpressBuffer.append(7);
break;
case R.id.btn_calculator_num_8:
if (mExpressBuffer.length() != 0 && mExpressBuffer.charAt(mExpressBuffer.length() - 1) == ')') {
break;
}
mExpressBuffer.append(8);
break;
case R.id.btn_calculator_num_9:
if (mExpressBuffer.length() != 0 && mExpressBuffer.charAt(mExpressBuffer.length() - 1) == ')') {
break;
}
mExpressBuffer.append(9);
break;
case R.id.btn_calculator_num_point:
if (mExpressBuffer.length() != 0) {
char c = mExpressBuffer.charAt(mExpressBuffer.length() - 1);
if (c >= '0' && c <= '9') {
mExpressBuffer.append(".");
}
}
break;
case R.id.btn_calculator_brackets_left:
if (mExpressBuffer.length() == 0) {
mExpressBuffer.append("(");
} else {
char c = mExpressBuffer.charAt(mExpressBuffer.length() - 1);
if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(') {
mExpressBuffer.append("(");
}
}
break;
case R.id.btn_calculator_brackets_right:
if (mExpressBuffer.length() != 0) {
char c = '\0';
int n1 = 0;// '('的个数
int n2 = 0;// ')'的个数
for (int i = 0; i < mExpressBuffer.length(); i++) {
c = mExpressBuffer.charAt(i);
if (c == '(') {
n1++;
} else if (c == ')') {
n2++;
}
}
if (n2 < n1 && (c >= '0' && c <= '9' || c == ')')) {
mExpressBuffer.append(")");
}
}
break;
case R.id.btn_calculator_back_space:
if (mExpressBuffer.length() != 0) {
mExpressBuffer.deleteCharAt(mExpressBuffer.length() - 1);
}
break;
case R.id.btn_calculator_operator_0:
mExpressBuffer = new StringBuffer();
mResult = "";
break;
case R.id.btn_calculator_operator_1:
if (mResult.length() != 0) {
mExpressBuffer.append(mResult);
mResult = "";
}
if (mExpressBuffer.length() == 0) {
mExpressBuffer.append("+");
} else {
char c = mExpressBuffer.charAt(mExpressBuffer.length() - 1);
if (c >= '0' && c <= '9' || c == ')') {
mExpressBuffer.append("+");
}
}
break;
case R.id.btn_calculator_operator_2:
if (mResult.length() != 0) {
mExpressBuffer.append(mResult);
mResult = "";
}
if (mExpressBuffer.length() == 0) {
mExpressBuffer.append("-");
} else {
int len = mExpressBuffer.length();
char c = mExpressBuffer.charAt(len - 1);
if (c >= '0' && c <= '9' || c == '(' || c == ')') {
mExpressBuffer.append("-");
} else if (len >= 2) {
c = mExpressBuffer.charAt(len - 2);
if (c >= '0' && c <= '9' || c == '(' || c == ')') {
mExpressBuffer.append("-");
}
}
}
break;
case R.id.btn_calculator_operator_3:
if (mResult.length() != 0) {
mExpressBuffer.append(mResult);
mResult = "";
}
if (mExpressBuffer.length() != 0) {
char c = mExpressBuffer.charAt(mExpressBuffer.length() - 1);
if (c >= '0' && c <= '9' || c == ')') {
mExpressBuffer.append("*");
}
}
break;
case R.id.btn_calculator_operator_4:
if (mResult.length() != 0) {
mExpressBuffer.append(mResult);
mResult = "";
}
if (mExpressBuffer.length() != 0) {
char c = mExpressBuffer.charAt(mExpressBuffer.length() - 1);
if (c >= '0' && c <= '9' || c == ')') {
mExpressBuffer.append("/");
}
}
break;
case R.id.btn_calculator_operator_5:
if (mExpressBuffer.length() != 0) {
char c = '\0';
int n1 = 0;// '('的个数
int n2 = 0;// ')'的个数
for (int i = 0; i < mExpressBuffer.length(); i++) {
c = mExpressBuffer.charAt(i);
if (c == '(') {
n1++;
} else if (c == ')') {
n2++;
}
}
if (n1 == n2 && (c >= '0' && c <= '9' || c == ')')) {
mExpressBuffer.append("=");
try {
mResult = mCalculatorMathUtil.getResult(mExpressBuffer.toString());
mExpressBuffer.append(mResult);
} catch (Exception e1) {
// mExpressBuffer.append(" IS ERROR");
mExpressBuffer.deleteCharAt(mExpressBuffer.length() - 1);
Toast.makeText(this, "表达式错误", Toast.LENGTH_LONG).show();
}

}
}
break;
default:
break;
}
mShowTextView.setText(mExpressBuffer.toString());
}

}

布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ff000000"
android:orientation="vertical" >

<TextView
android:id="@+id/tv_calculator_result"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#cccccccc"
android:textSize="26sp"
android:gravity="bottom|right"
android:layout_margin="10dp"
android:paddingBottom="10dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
/>
<TableLayout
android:id="@+id/tl_calculator_keys_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stretchColumns="0,1,2,3"
android:layout_marginTop="10dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
>
<TableRow >
<Button
android:id="@+id/btn_calculator_brackets_left"
style="@style/calculator_button_style"
android:layout_margin="1dp"
android:layout_weight="0.25"
android:text="@string/brackets0"
android:onClick="clickMe"
/>
<Button
android:id="@+id/btn_calculator_brackets_right"
style="@style/calculator_button_style"
android:layout_margin="1dp"
android:layout_weight="0.25"
android:text="@string/brackets1"
android:onClick="clickMe"
/>
<Button
android:id="@+id/btn_calculator_operator_0"
style="@style/calculator_button_style"
android:layout_margin="1dp"
android:layout_weight="0.25"
android:text="@string/operator0"
android:background="@drawable/calculator_button_background_2"
android:onClick="clickMe"
/>
<Button
android:id="@+id/btn_calculator_back_space"
style="@style/calculator_button_style"
android:layout_margin="1dp"
android:layout_weight="0.25"
android:text="@string/operatorC"
android:background="@drawable/calculator_button_background_2"
android:onClick="clickMe"
/>
</TableRow>

<TableRow >
<Button
android:id="@+id/btn_calculator_operator_1"
style="@style/calculator_button_style"
android:layout_margin="1dp"
android:layout_weight="0.25"
android:text="@string/operator1"
android:onClick="clickMe"
/>
<Button
android:id="@+id/btn_calculator_num_7"
style="@style/calculator_button_style"
android:layout_margin="1dp"
android:layout_weight="0.25"
android:text="@string/num7"
android:onClick="clickMe"
/>
<Button
android:id="@+id/btn_calculator_num_8"
style="@style/calculator_button_style"
android:layout_margin="1dp"
android:layout_weight="0.25"
android:text="@string/num8"
android:onClick="clickMe"
/>
<Button
android:id="@+id/btn_calculator_num_9"
style="@style/calculator_button_style"
android:layout_margin="1dp"
android:layout_weight="0.25"
android:text="@string/num9"
android:onClick="clickMe"
/>
</TableRow>

<TableRow >
<Button
android:id="@+id/btn_calculator_operator_2"
style="@style/calculator_button_style"
android:layout_margin="1dp"
android:layout_weight="0.25"
android:text="@string/operator2"
android:onClick="clickMe"
/>
<Button
android:id="@+id/btn_calculator_num_4"
style="@style/calculator_button_style"
android:layout_margin="1dp"
android:layout_weight="0.25"
android:text="@string/num4"
android:onClick="clickMe"
/>
<Button
android:id="@+id/btn_calculator_num_5"
style="@style/calculator_button_style"
android:layout_margin="1dp"
android:layout_weight="0.25"
android:text="@string/num5"
android:onClick="clickMe"
/>
<Button
android:id="@+id/btn_calculator_num_6"
style="@style/calculator_button_style"
android:layout_margin="1dp"
android:layout_weight="0.25"
android:text="@string/num6"
android:onClick="clickMe"
/>
</TableRow>

<TableRow >
<Button
android:id="@+id/btn_calculator_operator_3"
style="@style/calculator_button_style"
android:layout_margin="1dp"
android:layout_weight="0.25"
android:text="@string/operator3"
android:onClick="clickMe"
/>
<Button
android:id="@+id/btn_calculator_num_1"
style="@style/calculator_button_style"
android:layout_margin="1dp"
android:layout_weight="0.25"
android:text="@string/num1"
android:onClick="clickMe"
/>
<Button
android:id="@+id/btn_calculator_num_2"
style="@style/calculator_button_style"
android:layout_margin="1dp"
android:layout_weight="0.25"
android:text="@string/num2"
android:onClick="clickMe"
/>
<Button
android:id="@+id/btn_calculator_num_3"
style="@style/calculator_button_style"
android:layout_margin="1dp"
android:layout_weight="0.25"
android:text="@string/num3"
android:onClick="clickMe"
/>
</TableRow>

<TableRow >
<Button
android:id="@+id/btn_calculator_operator_4"
style="@style/calculator_button_style"
android:layout_margin="1dp"
android:layout_weight="0.25"
android:text="@string/operator4"
android:onClick="clickMe"
/>
<Button
android:id="@+id/btn_calculator_num_point"
style="@style/calculator_button_style"
android:layout_margin="1dp"
android:layout_weight="0.25"
android:text="@string/point"
android:onClick="clickMe"
/>
<Button
android:id="@+id/btn_calculator_num_0"
style="@style/calculator_button_style"
android:layout_margin="1dp"
android:layout_weight="0.25"
android:text="@string/num0"
android:onClick="clickMe"
/>
<Button
android:id="@+id/btn_calculator_operator_5"
style="@style/calculator_button_style"
android:layout_margin="1dp"
android:layout_weight="0.25"
android:text="@string/operator5"
android:background="@drawable/calculator_button_background_2"
android:onClick="clickMe"
/>
</TableRow>

</TableLayout>

</LinearLayout>

样式

1
2
3
4
5
6
7
8
9
<style name="calculator_button_style">  
<item name="android:layout_width">68dp</item>
<item name="android:layout_height">50dp</item>
<item name="android:gravity">center</item>
<item name="android:textSize">18sp</item>
<item name="android:textColor">#ffffffff</item>
<item name="android:textStyle">bold</item>
<item name="android:background">@drawable/calculator_button_background</item>
</style>

有个可查看的Android项目,请点击查看源码