我有大量的 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/