存档

2018年8月 的存档

C语言中p[j]和j[p]

2018年8月30日 没有评论

首页我们来看一段有关C语言指针相关的代码,代码不是很规范,但是可以表明问题。

#include <stdio.h>

int main() {
    char *p;
    int i=1;
    p = &i;
    *(p+1) = 2;
    p[2] = 3;
    for (int j = 0; j < 3; ++j) {
        printf("p[%d]: %d \n", j, p[j]);
        printf("%d[p]: %d \n", j, j[p]);
    }
    return 0;
}

那么这里”p[j]”和”j[p]”数据结果会一样吗?

是的,他们的结果完全一样,下面是上面代码的运行结果。

p[0]: 1 
0[p]: 1 
p[1]: 2 
1[p]: 2 
p[2]: 3 
2[p]: 3 

大多数的C语言书籍里面,都会把p[j]说成数组p中的第j个元素,虽然这种说法也没有错,其实p[j]等价于*(p+j)的。这也是我上面示例中赋值时使用2中方法的原因。“加法运算可以交换顺序,所以将*(p + i)写成*(i + p) 也是可以的。同理,将p[i]写成i[p]也是可以的(可能你会不相信,但这样写既不会出错,也能正常运行)。摘录来自: 川合秀实. “30天自制操作系统”。

分类: C/C++ 标签:

elasticsearch自定义ik词库

2018年8月7日 没有评论

最近一直在研究使用elasticsearch,es默认的分析器对中文只能提供一个一个汉字的分词,这对搜索有些要求的应用或项目来说有些差强人意的。所以很多人选择国人开发的分词插件ik来选择中文默认的分词器,插件在github上面的地址是medcl/elasticsearch-analysis-ik

安装ik

官方提供了2中方式来安装ik,下载稳定的发布包,或者通过”elasticsearch-plugin”来安装。elasticsearch-plugin安装是很方便,不过可能会有一些问题要解决“java.security.AccessControlException: access denied”问题,在最新版的6.3版本中,加入了”plugin-security.policy”来解决这个文。如果有AccessControlException问题的,查看《elasticsearch ik socket access denied》来解决你的问题。

plugin安装命令

./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.3.0/elasticsearch-analysis-ik-6.3.0.zip

 发布包方式

cd {your-es-root}/plugins/ && mkdir ik
cp -r elasticsearch-analysis-ik-* {your-es-root}/plugins/ik

这里的”{your-es-root}”是你es的根目录,”elasticsearch-analysis-ik-*”表示你解压以后的ik插件目录。

可以通过访问”http://localhost:9200/_cat/plugins?pretty”来查看你的ik是否安装成功。

自定义分词

ik的配置文件IKAnalyzer.cfg.xml可以在 ” {conf}/analysis-ik/config/IKAnalyzer.cfg.xml" 或者 “{plugins}/elasticsearch-analysis-ik-*/config/IKAnalyzer.cfg.xml"。如果你没有找到试试用find命令来查找。

<properties>
	<comment>IK Analyzer 扩展配置</comment>
	<!--用户可以在这里配置自己的扩展字典 -->
	<!-- <entry key="ext_dict">custom/custom.dic</entry> -->
	 <!--用户可以在这里配置自己的扩展停止词字典-->
	<entry key="ext_stopwords"></entry>
	<!--用户可以在这里配置远程扩展字典 -->
	<entry key="remote_ext_dict">http://xxxxx/ik/custom.dic</entry>
	<!--用户可以在这里配置远程扩展停止词字典-->
	<!-- <entry key="remote_ext_stopwords">http://xxxxxx/ik/stopwords.dic</entry> -->
</properties>

这是IKAnalyzer.cfg.xml的文件格式,我们要自定义分词,把”ext_dict”设置成我们分词文件所在的目录就可以。分词文件的格式是一行一个分词,也就是用”\n”分隔,和下面要介绍的热加载分词格式一样。然后重启es,如果没有错误发生,那么自定义分词就生效了。但是这种方式如果我们想要修改添加分词每次必须要重启es。

热加载自定义分词

通过”remote_ext_dict”我们可以配置热加载的分词词库,这是一个url地址,它大概会每隔60秒来检查一下地址,如果有变化就加载新的词库。

1、该 http 请求需要返回两个头部(header),一个是 Last-Modified,一个是 ETag,这两者都是字符串类型,只要有一个发生变化,该插件就会去抓取新的分词进而更新词库。

2、该 http 请求返回的内容格式是一行一个分词,换行符用 \n 即可。

把词库生成到nginx服务器指定路径下面即可。注意修改完配置文件以后要生效也需要重启。

elasticsearch ik socket access denied

2018年8月7日 没有评论

最近在使用elasticsearch,然后中分词选择使用ik,ik支持热加载分词,但是配置的时候总是失败。没有撸过java代码,所有对java在socket连接时居然还需要权限验证还是蛮吃惊的。我当初是用elasticsearch-plugin安装的,如果使用ik github上面提供的稳定版的发布包来手动安装就不会有这个问题,里面的”plugin-security.policy”已经包含了解决方案。

在启动es时,日志文件里面有如下错误信息。

[2018-08-07T14:52:26,004][WARN ][o.e.g.Gateway            ] [75Cwi4-] recovering index [index/Tmk_kfl-SqqeSSPx7vjXQw] failed - recovering as closed
java.security.AccessControlException: access denied ("java.net.SocketPermission" "120.77.217.214:80" "connect,resolve")
	at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472) ~[?:1.8.0_65]
	at java.security.AccessController.checkPermission(AccessController.java:884) ~[?:1.8.0_65]
	at java.lang.SecurityManager.checkPermission(SecurityManager.java:549) ~[?:1.8.0_65]
	at java.lang.SecurityManager.checkConnect(SecurityManager.java:1051) ~[?:1.8.0_65]
	at java.net.Socket.connect(Socket.java:584) ~[?:1.8.0_65]
	at org.apache.http.conn.socket.PlainConnectionSocketFactory.connectSocket(PlainConnectionSocketFactory.java:74) ~[?:?]
	at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:141) ~[?:?]
	at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353) ~[?:?]
	at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380) ~[?:?]
	at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236) ~[?:?]
	at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184) ~[?:?]
	at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88) ~[?:?]
	at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) ~[?:?]
	at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184) ~[?:?]
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) ~[?:?]
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107) ~[?:?]
	at org.wltea.analyzer.dic.Dictionary.getRemoteWords(Dictionary.java:470) ~[?:?]
	at org.wltea.analyzer.dic.Dictionary.loadRemoteExtDict(Dictionary.java:439) ~[?:?]
	at org.wltea.analyzer.dic.Dictionary.loadMainDict(Dictionary.java:380) ~[?:?]
	

这个错误是由java安全管理器SecurityManager引起的,相关的信息可以查看一下这篇《java安全管理器SecurityManager入门》。由于我对这方面的知识了解不多,就不再展开了。解决这个问题的思路是我们在SecurityManager配置文件里面允许这些socket连接。找到”java.policy”文件,我在mac上面的位置在”/Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home/jre/lib/security/java.policy”,当然如果你是windows或者linux系统,可以搜索java.policy文件,注意不要修改成其他软件自带的jre中的配置文件。

grant {
    ...
    //默认配置省略
    permission java.net.SocketPermission "*", "connect,resolve";
}

在配置文件最后增加上面的权限相关的最后2行内容,然后重启es,一切就ok了!