2014-06-09 1 views
0

얼랭으로 PostgreSQL에서 데이터를 가져 오려고합니다. 다음은 DB에서 데이터를 가져 오는 내 코드입니다. 그러나 나는 '상태'열에서 cyrrilic 데이터 있습니다. 이 부정한 데이터가 올바르게 가져 오지 않습니다. UserInfo = io_lib:format("~tp ~n",[UserInfoQuery]),을 사용해 보았지만 앱이 작동하지 않아 작동하지 않는 것 같습니다.PostgreSQL에서 유니 코드 데이터 가져 오기 Erlang

UserInfoQuery = odbc_queries:get_user_info(LServer,LUser), 
UserInfo = io_lib:format("~p",[UserInfoQuery]), 
?DEBUG("UserInfo: ~p",[UserInfo]), 
StringForUserInfo = lists:flatten(UserInfo), 

get_user_info(LServer, Id) -> 
ejabberd_odbc:sql_query(
    LServer, 
    [<<"select * from users " 
    "where email_hash='">>, Id, "';"]). 

다음은 DB

에서 가져올 수있는 데이터입니다
{selected,[<<"username">>,<<"password">>,<<"created_at">>, 
      <<"id">>,<<"email_hash">>,<<"status">>], 
      [{<<"admin">>,<<"admin">>,<<"2014-05-13 12:40:30.757433">>, 
      <<"1">>,<<"adminhash">>, 
      <<209,139,209,132,208,178,208,176,209,139,209,132,208, 
       178,208,176>>}]} 

질문 :

  1. 어떻게 내가 열에서 데이터를 추출 할 수 있습니까? 예를 들어 '상태'열의 데이터 만 표시 할 수 있습니까?
  2. DB에서 유니 코드로 데이터를 추출하려면 어떻게해야합니까? DB에서 데이터를 가져와야합니까? io_lib : format ("~ tp ~ n")? 더 좋은 방법이 있습니까?

추가 질문 : 문자열을 사람이 읽을 수있는 형식으로 가져 오는 방법이 있습니까? RowUnicode의 StringForUserInfo = 'ыфваыфва'?

{selected, _, [Row]} = UserInfoQuery, 
RowUnicode = io_lib:format("~tp~n", [Row]), 
?DEBUG("RowUnicode: ~p",[RowUnicode]), 
StringForUserInfo = lists:flatten(RowUnicode), 

오류 : io:format("~tp")이 작동하지 않는 이유

bad argument in call to erlang:iolist_size([123,60,60,34,97,100,109,105,110,34, 
62,62,44,60,60,34,97,100,109,105,110,34,62,62,44,60,60,34,50,...]) 

답변

2

Erlang ODBC 드라이버는 데이터베이스에서 상태 열을 완벽하게 가져 왔습니다. 사실, PostgreSQL은 여러분의 데이터를 UTF-8로 인코딩하고, 여러분이 얻는 가치는 UTF-8로 인코딩됩니다.

Status = <<209,139,209,132,208,178,208,176,209,139,209,132,208,178,208,176>>. 

이것은 ыфваыфва을 UTF-8로 나타내는 이진수입니다. 코드에서 UTF-8로 인코딩 된 바이너리를 직접 사용할 수 있습니다. UTF-8 바이트 대신 유니 코드 문자 포인트를 사용하려면이 값을 정수 목록 (Erlang 구문의 문자열)으로 변환 할 수 있습니다. 귀하의 경우 [1099,1092,1074,1072,1099,1092,1074,1072] 목록을 얻을 것입니다 unicode:characters_to_list/1, 그냥 사용하십시오. 이것은 동일한 문자열의 목록 표현입니다. 유니 코드 문자 1099 (16 진수 16 # 044B)는 ы입니다 (CYRILLIC SMALL LETTER YERU, Cyrillic excerpt unicode chart 참조).

Erlang은 위의 두 표현에서 유니 코드 텍스트를 처리 할 수 ​​있습니다. 유니 코드 문자 목록은 UTF-8 인코딩 문자의 정수 및 바이너리로 나타납니다.

더 작은 예제 인 문자열 "ы"을 살펴 보겠습니다. 이 문자열은 유니 코드 문자 044B CYRILLIC SMALL LETTER YERU로 구성되며 <<209,139>> 또는 [16#044B] (= [1099])의 목록으로 이진 형식으로 인코딩 할 수 있습니다.

역사적으로 바이너리뿐만 아니라 정수 목록도 Latin-1 (ISO-8859-1)로 인코딩되었습니다. 유니 코드와 ISO-8859-1은 0에서 255까지 동일한 값을 갖지만 UTF-8 변환은 0-127 범위의 문자에 대해서만 ISO-8859-1과 일치합니다. 이러한 이유로 Erlang의 ~s 형식 인수의 유니 코드 변환 한정자는 ~ts입니다.다음 줄은 예상대로 작동하지 않습니다

io:format("~s", [<<209,139>>]). 

출력됩니다 두 개의 문자, 00D1 (물결표 라틴 대문자 N) 및 008B (부분 LINE FORWARD). < < 209,139 >>는 Latin-1 문자열로 해석되고 UTF-8 인코딩 된 문자열로 해석되지 않기 때문입니다.

다음 줄에 실패합니다 : [1099] 유효한 라틴어 1 문자열이 아니기 때문에

io:format("~s", [[1099]]). 

이다.

대신 작성해야 :

io:format("~ts", [<<209,139>>]), 
io:format("~ts", [[1099]]). 

얼랑의 ~p 형식 인수는 또한, ~tp을 유니 코드 변환 수정이 있습니다. 그러나 ~tp만을 찾고 있습니다.. 당신은 기본적으로 ~p 또는 ~tp를 사용하든, io_lib:format/2은 위의 상태 UTF-8로 인코딩 된 바이너리 포맷합니다 :

<<209,139,209,132,208,178,208,176,209,139,209,132,208,178,208,176>> 

사실, t 수정은 유니 코드 입력을 수용한다 인수를 의미한다. ~p을 사용하면 문자열이나 바이너리를 포맷 할 때 Erlang이 입력을 Latin-1로 인코딩 할 수 있기 때문에이를 라틴어 -1 문자열로 나타낼 수 있는지 여부를 결정합니다. 이 경험적 방법은 Erlang이 대부분의 시간에 정수와 문자열 목록을 적절하게 구분할 수있게합니다. [1,2,3,4,5,6]는 정수의 목록이 아니라, 단지 반면,

io:format("~p\n~p\n", [[69,114,108,97,110,103], [1,2,3,4,5,6]]). 

휴리스틱은 [69,114,108,97,110,103] 실제로 "Erlang" 것을 감지 : 직장에서 휴리스틱을 확인하려면, 당신은 뭔가를 시도 할 수 있습니다.

~tp을 사용하는 경우 Erlang은 문자열이나 바이너리가 유니 코드로 인코딩 될 것으로 예상하고 기본값 식별 추론을 적용합니다. 그리고 기본 발견 적 방식은 현재 (R17) 라틴 -1이기도합니다. 문자열은 Latin-1로 표현 될 수 없기 때문에 Erlang은 이것을 정수 목록으로 표시합니다. 다행스럽게도 명령 행에서 +pc unicode을 Erlang으로 전달하면 유니 코드 휴리스틱 스로 전환 할 수 있으며 원하는 결과를 얻을 수 있습니다.

$ erl +pc unicode 

그래서 문제에 대한 해결책은 +pc unicode을 통과하고 ~tp을 사용하는 것입니다.

+0

데이터를 사람이 읽을 수있는 UTF-8로 처리하고 Erlang 문자열에 넣을 수있는 방법이 있습니까? – max

+0

이 데이터는 이미 UTF-8 형식이며 "사람이 읽을 수있는 UTF-8"을 이해하지 못합니다. 소스 코드에서 UTF-8 문자열을 입력 하시겠습니까? –

+0

더 나은 설명을 위해 질문을 편집했습니다. – max

1

내가 이해하지 않지만, 당신이 필요로하는 행과 열을 추출하고 인쇄 할 수 io:format("~ts")과 :

이 시도
> {selected, _, [Row]} = UserInfoQuery. 
> io:format("~ts~n", [element(6, Row)]). 
ыфваыфва 
ok