YAML.dumpで日本語が文字化けする

YAML.dumpでUTF8文字列をダンプする際にはバイナリと認識されてしまい、ファイルに保存した際にちょっと困ったことになります。

Psychなどを使う方法があるとのことですが、1.8だと気軽には使えません。

一つすばらしいやり方が紹介されていたのでちょっと改造してみます

http://projectzero-swb.blogspot.jp/2010/06/rubyyaml2.html

  • CentOS5.4
  • ruby1.8.7
#!/usr/bin/env ruby																																											 
# -*- encoding: utf-8 -*-

require "yaml"
require "yaml/encoding"

# String.is_binary_data?で必ずfalseを返すように書き換える
class String
	def is_binary_data?
		return false
	end
end

class Name
	attr_reader:no,:name
	def initialize(no,name)
		 @no=no
		 @name=name
	end
	def to_s
		return @no.to_s+":"+@name.to_s
	end
end

data = {"はつね"=>Name.new(1,"みく"), "はちゅね"=>Name.new(2,"みく"), "かがみね"=>Name.new(3,"りん・
れん"), "めぐりね"=>Name.new(4,"るか")}

# 通常どおり表示
#puts "Escape:"
yaml = YAML.dump(data)

# アンエスケープして表示
#puts "Unescape:"
yaml = YAML.unescape(yaml)

f=open("test3.yaml","w")
f.write(yaml)
f.close

f=YAML.load_file("test3.yaml")
f.each{|k,v|
	puts k+","+v.to_s
}

実行結果

はちゅね,2:みく
めぐりね,4:るか
かがみね,3:りん・れん
はつね,1:みく

test3.yaml

--- 
"はちゅね": !ruby/object:Name
	name: "みく"
	"no": 2
"めぐりね": !ruby/object:Name
	name: "るか"
	"no": 4
"かがみね": !ruby/object:Name
	name: "りん・れん"
	"no": 3
"はつね": !ruby/object:Name
	name: "みく"
	"no": 1

rubyのマルチスレッド

rubyはマルチスレッドのプログラムを書いても、CPUは一個しか使ってくれないらしい。

GIL というもののせいらしい。。

http://ja.wikipedia.org/wiki/グローバルインタプリタロック

そこでマルチプロセスのプログラムを作ってみる

#!/bin/env ruby
class Test
	def exec
		t1=fork{calc}
		t2=fork{calc}
		Process.waitpid t1
		Process.waitpid t2
	end
	def calc
		tim=rand(10)
p Process.pid.to_s+",start,"+tim.to_s
		sleep tim
p Process.pid.to_s+",end,"+tim.to_s
		exit
	end
end

if __FILE__ == $0 then
	Test.new.exec
end

jQuery-uiのautocompleteで遊んでみる

  • eclipse 4.2
  • MaxOS10.8.2

ajaxでjsonpをあらかじめ取得しておき、autocompleteにわたすサンプル

jspで取得する値はmemcachedに入っている

  • sample.jsp
<%@ page language="java" contentType="text/html; charset=Shift_JIS"
		pageEncoding="Shift_JIS"%>
<%@ page import="java.util.*" %> 
<%@ page import="java.net.*" %>	 
<%@ page import="net.rubyeye.xmemcached.*" %>
<%@ page import="net.rubyeye.xmemcached.utils.*" %>
<%@ page import="net.rubyeye.xmemcached.exception.*" %>
<%--
memcachedに以下のデータが入っている
key,value
1,value1
2,value2
3,value3
..

出力はJsonp
[ {"label":"1","tag":"value1"} , {"label":"2","tag":"value2"} , {"label":"3","tag":"value3"} , {"label":"4","tag":"value4"} , {"label":"5","tag":"value5"} , {"label":"6","tag":"value6"} , {"label":"7","tag":"value7"} , {"label":"8","tag":"value8"} , {"label":"9","tag":"value9"} ] 
 --%>
<%
	String callback=request.getParameter("callback");
	String callbackHeader="";
	String callbackFooter="";
	if(callback!=null){
		callbackHeader=callback+"(";
		callbackFooter=");";
	}
%>
<%=callbackHeader%>[
<%
	XMemcachedClientBuilder builder=
		new XMemcachedClientBuilder(AddrUtil.getAddresses("localhost:11211"));
	MemcachedClient client=builder.build();
	client.setPrimitiveAsString(true);
	
	boolean isFirst=true;
	for(int i=1;i<10;i++){
		String val=client.get(String.valueOf(i));
		if(val==null)continue;
		if(isFirst){
			isFirst=false;
		}else{
%>
,
<%
		}
%>
{"label":"<%=i %>","tag":"<%=val %>"}
<%
	}
%>
]<%=callbackFooter%>

<%
	client.shutdown();
%>
  • sample.html




	    

rubyで関数ポインタが使えるのか?

  • ruby 1.8.7
  • MacOS 10.8.2
#!/bin/env ruby

class Calcurator
	def initialize(a,b)
		@a=a
		@b=b
	end 
	def add 
		p @a+@b
	end 
	def subRet
		return @a-@b
	end 
	def addValue(c,d)
		p @a+@b+c+d
	end 
	def addValueRet(c)
		return @a+@b+c
	end 
	def addMethod(m)
		return @a+@b+method(m).call
		
	end 
end

class CalcTest
	def exec
		calc=Calcurator.new(2,1)
		calc.method(:add).call			 
		p calc.method(:subRet).call	
		calc.method(:addValue).call(3,4) 
		p calc.method(:addValueRet).call(4)	
		p calc.method(:addMethod).call(:subRet) 
	end 
end

if __FILE__ == $0 then
	CalcTest.new.exec
end

結果

3
1
10
7
4

jQueryのsuggestとautocompleteを使ってみる

googleなどの検索ボックスで予測したり、ぺろっと出てくるあれ、実装してみました

  • 予測で出てくるあれ

http://polarblau.github.com/suggest/

こちらからjquery.suggest.jsをゲット

  • ぺろっとでてくるあれ

http://api.jqueryui.com

こちらからjquery-1.9.0.jsとjquery-ui.jsをダウンロード





	     

Macでkakasi

KAKASIをMacにインストールしてみた

  • MaxOS10.8.2
  • kakasi-2.3.4
$ tar zxvfp kakasi-2.3.4.tar.gz
$ ./configure
$ make
make	all-recursive
Making all in src
make[2]: Nothing to be done for `all'.
Making all in lib
/bin/ksh ../libtool --mode=link gcc	-g -O2 -Wall -Wunused -Wuninitialized -Wmissing-prototypes -Wmissing-declarations -pedantic	-o libkakasi.la -rpath /usr/local/lib -version-info 3:0:1	-export-dynamic libdict.lo libkakasi.lo libkanjiio.lo liba2.lo libg2.lo libj2.lo libk2.lo libee2.lo libhh2.lo libjj2.lo libkk2.lo libitaiji.lo lib78_83.lo
rm -fr .libs/libkakasi.la .libs/libkakasi.* .libs/libkakasi.*
gcc -dynamiclib -undefined suppress -o .libs/libkakasi.2.1.0.dylib	libdict.lo libkakasi.lo libkanjiio.lo liba2.lo libg2.lo libj2.lo libk2.lo libee2.lo libhh2.lo libjj2.lo libkk2.lo libitaiji.lo lib78_83.lo	-lc -install_name	/usr/local/lib/libkakasi.2.dylib -compatibility_version 4 -current_version 4.0
ld: can't use -undefined warning or suppress with -twolevel_namespace
collect2: ld returned 1 exit status
make[2]: *** [libkakasi.la] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all-recursive-am] Error 2

エラーが出る

http://www.ki.nu/~makoto/diary/?200307b&to=200307131#200307131

こちらに対処法があったので修正

$ vi libtool
allow_undefined_flag="-undefined suppress"
↓
allow_undefined_flag=""
$make
#make install
$ echo "書かし"|kakasi.dSYM -Ja -Ka -Ha
kakashi

うまくいったようだ

GSONを使ってJson文字列をパースする

JSONの文字列を簡単にJAVAのクラスにしてくれます

  • gson-2.2.2.jar
  • java version “1.6.0_37”
  • iOS10.8.2
package jp.qri.search;

import java.util.List;

import com.google.gson.Gson;

public class GsonTest {
	public static class StockItem{
		public String string;
		public String code;
		public String toString(){
			return "("+string+":"+code+")";
		}
	}
	public static class StockList{
		public List stocks;	// 配列はListを使う
		public StockList(){}
		public String toString(){
			String ret="";
			for(StockItem item:stocks){
				ret+=item.toString()+",";
			}
			return ret;
		}
	}
	
	
	public static void main(String[] argv){
		Gson gson=new Gson();
		String jsonStr="{\"string\":\"ソニー\",\"code\":\"6758\"}";
		StockItem item=gson.fromJson(jsonStr,StockItem.class);
		System.out.println(item.toString());
		
		String jsonString="{\"stocks\":[{\"string\":\"ソニー\",\"code\":\"6758\"},{\"string\":\"ソニーフィナンシャルホールディングス\",\"code\":\"8729\"}]}";
		StockList list=gson.fromJson(jsonString, StockList.class);
		System.out.println(list.toString());
	}
}

結果

(ソニー:6758)
(ソニー:6758),(ソニーフィナンシャルホールディングス:8729),

ruby-mysqlで文字コード指定

rubyでMYSQLにつなぐ際にMySQL/Rubyを使っていたのですが、どうやら開発が止まってしまったらしくruby1.9には非対応とのこと

https://github.com/tmtm/ruby-mysql

こちらからruby-mysqlなるものをダウンロード。

ちなみにプロキシ越しのgemではうまくいきませんでした

# gem install ruby-mysql
WARNING:	Error fetching data: too many connection resets (http://rubygems.org/latest_specs.4.8.gz)
ERROR:	Could not find a valid gem 'ruby-mysql' (>= 0) in any repository
ERROR:	Possible alternatives: ruby-mysql

とりあえずインストール

# ruby setup.rb
  • 日本語

mysqlにはSjisでデータが入っており、クライアントがutf-8の場合には以下のように書く必要があります

#/bin/env ruby -w -Ku
# -*- coding=utf-8 -*-
client=Mysql.connect("localhost","root","pass","dbname")
client.charset="utf8"
res=client.query("select id,name from IdTable")
res.each{|r|
p r
}

kyototycoonをmemcachedモードで使う

kyototycoonをmemcachedモードで使ったときの不思議な現象が出たのでメモ

使用したバージョンはこれ

kyotocabinet-1.2.76

kyototycoon-0.9.56

MacOS10.8

  • まずはOKパターン
$ /usr/local/bin/ktserver -host 127.0.0.1 -th 2 -plsv /usr/local/libexec/ktplugservmemc.dylib -plex 'opts=f' ./ktserver.kch >> ./ktserver.log
$ telnet localhost 11211
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
stats
STAT pid 88068
STAT uptime 8
STAT time 1360107774
STAT version KyotoTycoon/0.9.56
STAT pointer_size 64
STAT curr_connections 1
STAT threads 16
STAT curr_items 9800
STAT bytes 6794776
STAT db_apow 3
STAT db_bnum 1048583
STAT db_chksum 188
STAT db_count 9800
STAT db_dfunit 0
STAT db_flags 1
STAT db_fmtver 5
STAT db_fpow 10
STAT db_frgcnt 0
STAT db_ktcapcnt -1
STAT db_ktcapsiz -1
STAT db_ktopts 0
STAT db_librev 13
STAT db_libver 16
STAT db_msiz 67108864
STAT db_opts 0
STAT db_path ./ktserver.kch
STAT db_realsize 6794776
STAT db_realtype 48
STAT db_recovered 0
STAT db_reorganized 0
STAT db_size 6794776
STAT db_trimmed 0
STAT db_type 48
STAT set_hits 0
STAT set_misses 0
STAT get_hits 0
STAT get_misses 0
STAT delete_hits 0
STAT delete_misses 0
STAT incr_hits 0
STAT incr_misses 0
STAT decr_hits 0
STAT decr_misses 0
STAT cmd_set 0
STAT cmd_get 0
STAT cmd_delete 0
STAT cmd_flush 0
END
  • NGパターン
$ /usr/local/bin/ktserver -host 127.0.0.1 -port 11211 -th 2 -plsv /usr/local/libexec/ktplugservmemc.dylib -plex opts=f ./ktserver.kch
$ telnet localhost 11211
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
stats
Connection closed by foreign host.

ポートを明示的に指定すると落ちてしまう

memcachedで日本語キーを扱う

memcachedの代わりにkyoto tycoonを試してみようとしています。

kyoto tycoonはmemcachedと同じインターフェースで起動できるとのことで、当然memcachedライブラリが使えます

日本語のキーが使えるかどうか確認します

  • memcachedライブラリ
$ su
# export http_proxy=proxy:port
# gem install memcached
#!/bin/env ruby -Ku 
# -*- encoding:utf-8 -*-
require "rubygems"
require "memcached"
require "nkf"

cache=Memcached.new "localhost:11211"
cache.set("sony","6758",0)
puts cache.get("sony")
key="ソニー"
cache.set(key,"ソニー",0)
puts cache.get(key)
$ ruby mem.rb 
6758
/Library/Ruby/Gems/1.8/gems/memcached-1.5.0/lib/memcached/memcached.rb:630:in `reraise': Key {"ソニー"=>nil} (Memcached::ABadKeyWasProvidedOrCharactersOutOfRange)
	from /Library/Ruby/Gems/1.8/gems/memcached-1.5.0/lib/memcached/memcached.rb:608:in `check_return_code'
	from /Library/Ruby/Gems/1.8/gems/memcached-1.5.0/lib/memcached/memcached.rb:306:in `set'
	from mem.rb:11

なんかだめ。。

ちなみにperlだと

#!/usr/bin/perl

use strict;
use warnings;
use Cache::Memcached::Fast;

my $memd=Cache::Memcached::Fast->new({
		servers => [ { address => 'localhost:11211' }], 
}); 

# 値を追加 key => value
my $key='ソニーal';
$memd->set($key=> 'そにー2');

# 値を取得
my $id = $memd->get($key);
print "$id\n";
$ perl mem.pl
そにー2

rubyのライブラリが悪いようだ

ちなみにOSはMountain Lion