java - Java中处理unicode字符并将结果写入mysql和HBase

标签 java mysql json unicode

我有大量的 Twitter 数据集,其中每条推文都存储为 JSON 对象,其中一个字段是推文文本,它是一系列 unicode 字符。我需要做的是将这条推文文本存储在 MySql 和 HBase 中。当然,MySql 和 HBase 默认情况下不存储 unicode 字符,我尝试了多种方法,包括更改 MySql 中数据存储的格式。然而,为了处理这个 1TB 数据集,我使用 MapReduce 从每个 JSON 对象中提取相关字段,并将输出写入字符串序列,例如:

1000000069:2014-04-20+09:23:41,457811834188607488%3A1%3ART+%40followback_707%3A+Retweet+this+%3F+ALL+%3F+WHO+%3F+RETWEETS+%3F+WANT+%3F+NEW+FOLLOWERS+FAST+%3F+%3F+%23FollowPyramid+%3F+%23TeamFollowBack%

(键值对在第一个逗号之后分隔,因此上面的文本中 1000000069:2014-04-20+09:23:41 是键,后面的所有内容都是文本信息. 开头的数字是推文 ID,然后是推文的情感分数。)

现在,在上面的文本中,我们可以看到一些字符已正确编码,但有些文本完全难以辨认,因为它们的存储处理不当。这里更大的挑战是处理 MapReduce 作业中的文本并正确写入该 MapReduce 作业的输出,以便其适合存储在所需的存储中,即 MySql 和 HBase。

1000001353:2014-04-28+13:20:59,460770655601164288%3A0%3A%22%40FuckinFather_%3A+%3F%3F%3F%3F%3F%3F%3F+%3F+%3F%3F%3F%3F%3F%3F%3F%3F.%22+%3F+%3F%3F%3F%3F%3F%3F+%3F%3F%3F%3F%3F+%3F+%3F%3F%3F%3F%3F%3F+%3F%3F%3F%3F%3F%3F.

实际上我们看到的%3F序列都被解码为问号,导致推文文本信息完全丢失。我一直在使用 URLEncoder.encode(string, "UTF-8) 函数对推文文本进行编码,但显然它只适用于某些字符串集,但不适用于其他类型的字符。有吗我可以使用某种方式正确地正确编码所有类型的推文文本,以便存储到 MySql 数据库和 HBase 中。

下面给出了我用来从化简器写下数据的代码片段:

我的映射器功能:

public class TweetParsingMapper {
    public static void main(String[] args){     
        List<HashMap<String, Integer>> wordSentimentScoringList = createAffinDataSet();
        HashSet<String> censorList = createCensorList();
        try{
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
            String jsonString;
            while((jsonString = bufferedReader.readLine()) != null){
                JSONObject tweetInfo = new org.json.JSONObject(jsonString);
                String tweetText = tweetInfo.get("tweetText").toString();
                String tweetId = tweetInfo.get("tweetId").toString();
                String userId = tweetInfo.get("userId").toString();
                String timeStamp = tweetInfo.get("timeStamp").toString();
                Integer sentimentScore = calculateSentimentScore(wordSentimentScoringList, tweetText);
                String censoredTweet = censorTweet(censorList, tweetText);
                censoredTweet = censoredTweet.replace("\n", "+delimiterfornewline+");
                censoredTweet = censoredTweet.replace("\r", "+delimiterforcarriagereturn+");
                censoredTweet = censoredTweet.replace(",", "+delimiterforcomma+");
                censoredTweet = tweetId + ":" + sentimentScore.toString() + ":"+ censoredTweet;
                String requestKey = userId + ":" + timeStamp;
                System.out.println(requestKey + "\t" + censoredTweet);
            }
            bufferedReader.close();
        }catch(IOException e){
            System.err.println(e.getMessage());
        }

    }

我的 reducer 功能:

{
        try{
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
            String input = null;
            String requestKey = null;
            String currentRequestKey = null;
            List<String> responseString = new ArrayList<String>();
            while((input = bufferedReader.readLine()) != null){
                String[] mapperResposeSet = input.split("\t", 2);
                requestKey = mapperResposeSet[0];
                if(requestKey.equals(currentRequestKey) && currentRequestKey != null){
                    if(!responseString.contains(mapperResposeSet[1]))
                        responseString.add(mapperResposeSet[1]);
                }
                else{
                    if(currentRequestKey != null){
                        StringBuilder finalResponse = new StringBuilder();

                        for(String str : responseString){
                            finalResponse.append(str);
                            finalResponse.append("+delimiter+");
                        }
                        System.out.println(currentRequestKey + "," + URLEncoder.encode(finalResponse.toString(), "UTF-8"));
                        responseString.clear();
                    }
                    currentRequestKey = requestKey;
                    responseString.add(mapperResposeSet[1]);
                }
            }
        }catch(IOException e){
            System.err.println(e.getMessage());
        }
    }

示例推文对象之一是:

{"timeStamp": "2014-06-25+08:54:16", "tweetText": "\uff62\u30c9\u30e9\u30b4\u30f3\u30b3\u30a4\u30f3\u30ba\uff63\u3092\u59cb\u3081\u305f\u3088\uff01\u30b8\u30e3\u30e9\u30b8\u30e3\u30e9\u30b3\u30a4\u30f3\u304c\u8d85\u723d\u5feb\uff01\u4e00\u7dd2\u306b\u3042\u305d\u307c\uff01 http://t.co/An4nuiswy1 #\u30c9\u30e9\u30b3\u30a4", "uId": "1669549520", "ht": ["\u30c9\u30e9\u30b3\u30a4"], "tweetId": "481722030383828994"}

最佳答案

您可以按原样存储它,即每个“字符”6 个字节 (\uxxxx)。如果你能把它变成utf8,那么就可以节省一半的空间。例如6个字符\u30c9代表片假名DO; utf8 中的十六进制 e38389 也是如此,它将存储为 3 个字节。

在 PHP(版本 >= 5.4)中,这将给出 utf8 而不是\uxxxx: $t = json_encode($s, JSON_UNESCAPED_UNICODE);

我不知道 Java 中的等效项。

关于java - Java中处理unicode字符并将结果写入mysql和HBase,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29290992/

相关文章:

php - 返回给定时间/日期的可用性

php - 为什么在 User::first() 上调用方法有效,但 User::where(...) 无效?

php - 无法从数据库检索数据

java - 为什么我需要 : "org.apache.derby.jdbc.ClientDriver"

java - 如何在 log4j2 文件名中使用当前日期模式?

java - 线程中出现异常 "main"java.lang.UnsatisfiedLinkError : no libz3java in java. library.path

json:无法将数组解码为 main.Posts 类型的 Go 值

java - 使用 Java FlowLayout

javascript - 使用我们自己的键将两个数组作为 json 对象推送

C# - Json 反序列化具有子属性的对象