海量日志数据提取某日访问百度次数最多的那个IP的Java实现

前几天在网上看到july的一篇文章《教你如何迅速秒杀掉:99%的海量数据处理面试题》,里面说到百度的一个面试题目,题目如下:

海量日志数据,提取出某日访问百度次数最多的那个IP。

july里面的分析如下。

1、  分而治之/hash映射:针对数据太大,内存受限,只能是:把大文件化成(取模映射)小文件,即16字方针:大而化小,各个击破,缩小规模,逐个解决

2、  hash统计:当大文件转化了小文件,那么我们便可以采用常规的hash_map(ip,value)来进行频率统计。

3、  堆/快速排序:统计完了之后,便进行排序(可采取堆排序),得到次数最多的IP。

我的分析:

1、  见july的1st.

2、  见july的2nd.

3、  不用排序,直接在统计的时候,计算出次数最多的IP:在第2步的时候,求出ip的次数,实际上呢,次数最大的那个只可能是一个值,因此在计算每个IP次数的时候,与这个最大值作比较,计算完即可知道最大值的IP是….

1      机器配置:

CPU:I3-2330M  2.20GHZ

MEM:4G(3.16G可用)

OS:win7  32位

2      生成海量数据的大文件:

2.1     总数据为1亿个IP数据,生成规则:以10.开头,其他是0-255的随机数。

  1. /**
  2. * 生成大文件
  3. * @param ipFile
  4. * @param numberOfLine
  5. */
  6. public void gernBigFile(File ipFile,long numberOfLine){
  7. BufferedWriter bw = null;
  8. FileWriter fw = null;
  9. long startTime = System.currentTimeMillis();
  10. try{
  11. fw = new FileWriter(ipFile,true);
  12. bw = new BufferedWriter(fw);
  13.  
  14. SecureRandom random = new SecureRandom();
  15. for (int i = 0; i < numberOfLine; i++) {
  16. bw.write("10."+random.nextInt(255)+"."+random.nextInt(255)+"."+random.nextInt(255)+"\n");
  17. if((i+1) % 1000 == 0){
  18. bw.flush();
  19. }
  20. }
  21. bw.flush();
  22.  
  23. long endTime = System.currentTimeMillis();
  24. System.err.println(DateUtil.convertMillsToTime(endTime - startTime));
  25. }catch (Exception e) {
  26. e.printStackTrace();
  27. }finally{
  28. try{
  29. if(fw != null){
  30. fw.close();
  31. }
  32. }catch (Exception e) {
  33. e.printStackTrace();
  34. }
  35. try{
  36. if(bw != null){
  37. bw.close();
  38. }
  39. }catch (Exception e) {
  40. e.printStackTrace();
  41. }
  42. }
  43. }
  1. /*
  2. * 1、第一次生成1亿(实际上最多为16581375)的ip地址,需要时间为3分多钟不到4分钟。
  3. */
  4. TooMuchIpFile tooMuchIpFile = new TooMuchIpFile();
  5. File ipFile = new File("e:/ipAddr.txt");
  6. try {
  7. ipFile.createNewFile();
  8. } catch (IOException e) {
  9. e.printStackTrace();
  10. }
  11. tooMuchIpFile.gernBigFile(ipFile, 100000000);

2.2     运行结果:

生成1亿行的Ip地址,大约耗时:3分多钟,大小1.27 GB (1,370,587,382字节)

3      分割大文件,

根据july的分析,取每个IP的hashCode,与1000取模,把IP散列到不同的文件中去。

3.1     第一种方法:

一边取每个IP的散列值,再模1000,得到一个值,然后写到此值对应的文件中去。大约耗时超过2个多小时,实在是太慢了,没跑完就直接断掉了。

  1. /**
  2. * 大文件分割为小文件
  3. * @param ipFile
  4. * @param numberOfFile
  5. */
  6. public void splitFile(File ipFile,int numberOfFile){
  7. BufferedReader br = null;
  8. FileReader fr = null;
  9. BufferedWriter bw = null;
  10. FileWriter fw = null;
  11. long startTime = System.currentTimeMillis();
  12. try{
  13. fr = new FileReader(ipFile);
  14. br = new BufferedReader(fr);
  15. String ipLine = br.readLine();
  16. while(ipLine != null){
  17. int hashCode = ipLine.hashCode();
  18. hashCode = hashCode < 0 ? -hashCode : hashCode;
  19. int fileNum = hashCode % numberOfFile;
  20. File file = new File("e:/tmp/ip/"+ fileNum + ".txt");
  21. if(!file.exists()){
  22. file.createNewFile();
  23. }
  24. fw = new FileWriter(file,true);
  25. bw = new BufferedWriter(fw);
  26. bw.write(ipLine + "\n");
  27. bw.flush();
  28. fw.close();
  29. bw.close();
  30. ipLine = br.readLine();
  31. }
  32.  
  33. long endTime = System.currentTimeMillis();
  34. System.err.println(DateUtil.convertMillsToTime(endTime - startTime));
  35. }catch (Exception e) {
  36. e.printStackTrace();
  37. }finally{
  38. try{
  39. if(fr != null){
  40. fr.close();
  41. }
  42. }catch (Exception e) {
  43. e.printStackTrace();
  44. }
  45. try{
  46. if(br != null){
  47. br.close();
  48. }
  49. }catch (Exception e) {
  50. e.printStackTrace();
  51. }
  52. try{
  53. if(fw != null){
  54. fw.close();
  55. }
  56. }catch (Exception e) {
  57. e.printStackTrace();
  58. }
  59. try{
  60. if(bw != null){
  61. bw.close();
  62. }
  63. }catch (Exception e) {
  64. e.printStackTrace();
  65. }
  66. }
  67. }

3.2     第二种方法:

与第一次方法基本相同,不同的是减少流对象的创建,只是创建文件时,创建流对象,但还是需要每次都要判断文件存在与否。大约耗时超过1个多小时,也实在是慢呀,没等它运行完就断了。

  1. /**
  2. * 大文件分割为小文件
  3. * @param ipFile
  4. * @param numberOfFile
  5. */
  6. public void splitFile2(File ipFile,int numberOfFile){
  7. BufferedReader br = null;
  8. FileReader fr = null;
  9. BufferedWriter bw = null;
  10. FileWriter fw = null;
  11. long startTime = System.currentTimeMillis();
  12. try{
  13. fr = new FileReader(ipFile);
  14. br = new BufferedReader(fr);
  15. String ipLine = br.readLine();
  16. while(ipLine != null){
  17. int hashCode = ipLine.hashCode();
  18. hashCode = hashCode < 0 ? -hashCode : hashCode;
  19. int fileNum = hashCode % numberOfFile;
  20. File file = new File("e:/tmp/ip/"+ fileNum + ".txt");
  21. if(!file.exists()){
  22. file.createNewFile();
  23. fw = new FileWriter(file,true);
  24. bw = new BufferedWriter(fw);
  25. bwMap.put(fileNum, bw);
  26. }else{
  27. bw = bwMap.get(fileNum);
  28. }
  29. bw.write(ipLine + "\n");
  30. bw.flush();
  31. ipLine = br.readLine();
  32. }
  33. for(int fn : bwMap.keySet()){
  34. bwMap.get(fn).close();
  35. }
  36. bwMap.clear();
  37. long endTime = System.currentTimeMillis();
  38. System.err.println(DateUtil.convertMillsToTime(endTime - startTime));
  39. }catch (Exception e) {
  40. e.printStackTrace();
  41. }finally{
  42. try{
  43. if(fr != null){
  44. fr.close();
  45. }
  46. }catch (Exception e) {
  47. e.printStackTrace();
  48. }
  49. try{
  50. if(br != null){
  51. br.close();
  52. }
  53. }catch (Exception e) {
  54. e.printStackTrace();
  55. }
  56. try{
  57. if(fw != null){
  58. fw.close();
  59. }
  60. }catch (Exception e) {
  61. e.printStackTrace();
  62. }
  63. try{
  64. if(bw != null){
  65. bw.close();
  66. }
  67. }catch (Exception e) {
  68. e.printStackTrace();
  69. }
  70. }
  71. }

3.3     第三种方法:

与第二种方法基本相同,在此基础上,优化一边取值,一边写文件的过程,而是先写到内存中,当达到1000后,再一起写入文件中。大约耗时52多分钟,这个是实际运行完的,在中午去吃饭的时候让它自己跑完的。

  1. /**
  2. * 大文件分割为小文件
  3. * @param ipFile
  4. * @param numberOfFile
  5. */
  6. public void splitFile3(File ipFile,int numberOfFile){
  7. BufferedReader br = null;
  8. FileReader fr = null;
  9. BufferedWriter bw = null;
  10. FileWriter fw = null;
  11. long startTime = System.currentTimeMillis();
  12. try{
  13. fr = new FileReader(ipFile);
  14. br = new BufferedReader(fr);
  15. String ipLine = br.readLine();
  16. while(ipLine != null){
  17. int hashCode = ipLine.hashCode();
  18. hashCode = hashCode < 0 ? -hashCode : hashCode;
  19. int fileNum = hashCode % numberOfFile;
  20. File file = new File("e:/tmp/ip/"+ fileNum + ".txt");
  21. if(!file.exists()){
  22. file.createNewFile();
  23. fw = new FileWriter(file,true);
  24. bw = new BufferedWriter(fw);
  25. bwMap.put(fileNum, bw);
  26. dataMap.put(fileNum, new LinkedList<String>());
  27. }else{
  28. List<String> list = dataMap.get(fileNum);
  29. list.add(ipLine + "\n");
  30. if(list.size() % 1000 == 0){
  31. BufferedWriter writer = bwMap.get(fileNum);
  32. for(String line : list){
  33. writer.write(line);
  34. }
  35. writer.flush();
  36. list.clear();
  37. }
  38. }
  39. ipLine = br.readLine();
  40. }
  41. for(int fn : bwMap.keySet()){
  42. List<String> list = dataMap.get(fn);
  43. BufferedWriter writer = bwMap.get(fn);
  44. for(String line : list){
  45. writer.write(line);
  46. }
  47. list.clear();
  48. writer.flush();
  49. writer.close();
  50. }
  51. bwMap.clear();
  52. long endTime = System.currentTimeMillis();
  53. System.err.println(DateUtil.convertMillsToTime(endTime - startTime));
  54. }catch (Exception e) {
  55. e.printStackTrace();
  56. }finally{
  57. try{
  58. if(fr != null){
  59. fr.close();
  60. }
  61. }catch (Exception e) {
  62. e.printStackTrace();
  63. }
  64. try{
  65. if(br != null){
  66. br.close();
  67. }
  68. }catch (Exception e) {
  69. e.printStackTrace();
  70. }
  71. try{
  72. if(fw != null){
  73. fw.close();
  74. }
  75. }catch (Exception e) {
  76. e.printStackTrace();
  77. }
  78. try{
  79. if(bw != null){
  80. bw.close();
  81. }
  82. }catch (Exception e) {
  83. e.printStackTrace();
  84. }
  85. }
  86. }

3.4     第四种方法:

在第三种方法基础上作进一步优化,不同的是,把创建1000个流对象放到循环外面。大约耗时13分钟35秒。这个方法实在比第三种方法快了4倍左右,但在我觉得,这时间还是有点说不过去呀。

  1. /**
  2. * 大文件分割为小文件
  3. * @param ipFile
  4. * @param numberOfFile
  5. */
  6. public void splitFile4(File ipFile,int numberOfFile){
  7. BufferedReader br = null;
  8. FileReader fr = null;
  9. BufferedWriter bw = null;
  10. FileWriter fw = null;
  11. long startTime = System.currentTimeMillis();
  12. try{
  13. fr = new FileReader(ipFile);
  14. br = new BufferedReader(fr);
  15. String ipLine = br.readLine();
  16. //先创建文件及流对象方便使用
  17. for(int i=0;i<numberOfFile;i++){
  18. File file = new File("e:/tmp/ip1/"+ i + ".txt");
  19. bwMap.put(i, new BufferedWriter(new FileWriter(file,true)));
  20. dataMap.put(i, new LinkedList<String>());
  21. }
  22. while(ipLine != null){
  23. int hashCode = ipLine.hashCode();
  24. hashCode = hashCode < 0 ? -hashCode : hashCode;
  25. int fileNum = hashCode % numberOfFile;
  26. List<String> list = dataMap.get(fileNum);
  27. list.add(ipLine + "\n");
  28. if(list.size() % 1000 == 0){
  29. BufferedWriter writer = bwMap.get(fileNum);
  30. for(String line : list){
  31. writer.write(line);
  32. }
  33. writer.flush();
  34. list.clear();
  35. }
  36. ipLine = br.readLine();
  37. }
  38. for(int fn : bwMap.keySet()){
  39. List<String> list = dataMap.get(fn);
  40. BufferedWriter writer = bwMap.get(fn);
  41. for(String line : list){
  42. writer.write(line);
  43. }
  44. list.clear();
  45. writer.flush();
  46. writer.close();
  47. }
  48. bwMap.clear();
  49. long endTime = System.currentTimeMillis();
  50. System.err.println(DateUtil.convertMillsToTime(endTime - startTime));
  51. }catch (Exception e) {
  52. e.printStackTrace();
  53. }finally{
  54. try{
  55. if(fr != null){
  56. fr.close();
  57. }
  58. }catch (Exception e) {
  59. e.printStackTrace();
  60. }
  61. try{
  62. if(br != null){
  63. br.close();
  64. }
  65. }catch (Exception e) {
  66. e.printStackTrace();
  67. }
  68. try{
  69. if(fw != null){
  70. fw.close();
  71. }
  72. }catch (Exception e) {
  73. e.printStackTrace();
  74. }
  75. try{
  76. if(bw != null){
  77. bw.close();
  78. }
  79. }catch (Exception e) {
  80. e.printStackTrace();
  81. }
  82. }
  83. }

3.5     第五种方法:

使用多线程,未成功实现优化。只是给出思路如下:读取1亿数据的文件,循环读取每个IP,计算其散列值,取模1000,之后把其放到对应的队列中,当其队列超过1000时,启动一个服务线程把数据写入文件中。(也即主线程只负责计算,由其他线程负责写)

3.6     运行结果:

1、第一次分割1亿数据的大文件,实在是太慢,运行差不多一小时,才分割出300W数据,耗时超过2个钟头

2、第二次分割1亿数据的大文件,经过优化后,虽然比第一次有提升,但是还是很慢,耗时超过1个钟头.

3、第三次分割1亿数据的大文件,经过优化后,虽然比第二次有提升,但是还是很慢,需耗时52.0分3.6秒

4、第四次分割1亿数据的大文件,经过优化后,耗时13.0分35.10400000000004秒

4      统计

各个文件中出现次数最多的IP(可能有多个):

采用的方法是一边统计各个IP出现的次数,一边算次数出现最大那个IP。

  1. /**
  2. * 统计,找出次数最多的IP
  3. * @param ipFile
  4. */
  5. public void read(File ipFile){
  6. BufferedReader br = null;
  7. FileReader fr = null;
  8. long startTime = System.currentTimeMillis();
  9. try{
  10. fr = new FileReader(ipFile);
  11. br = new BufferedReader(fr);
  12. String ipLine = br.readLine();
  13. while(ipLine != null){
  14. ipLine = ipLine.trim();
  15. Integer count = ipNumMap.get(ipLine);
  16. if(count == null){
  17. count = 0;
  18. }
  19. count ++;
  20. ipNumMap.put(ipLine, count);
  21.  
  22. if(count >= ipMaxNum){
  23. if(count > ipMaxNum){
  24. keyList.clear();
  25. }
  26. keyList.add(ipLine);
  27. ipMaxNum = count;
  28. }
  29. ipLine = br.readLine();
  30. }
  31. long endTime = System.currentTimeMillis();
  32. System.err.println(ipFile.getName()+":"+DateUtil.convertMillsToTime(endTime - startTime));
  33. totalTime += (endTime - startTime);
  34. }catch (Exception e) {
  35. e.printStackTrace();
  36. }finally{
  37. try{
  38. if(fr != null){
  39. fr.close();
  40. }
  41. }catch (Exception e) {
  42. e.printStackTrace();
  43. }
  44. try{
  45. if(br != null){
  46. br.close();
  47. }
  48. }catch (Exception e) {
  49. e.printStackTrace();
  50. }
  51. }
  52. }

4.1     运行结果:

1、从1000个文件中查询Ip次数最多的Ip,10.164.143.57:24,3.0分18.748999999999995秒

2、从1000个文件中查询Ip次数最多的Ip,10.164.143.57:24,3.0分27.366000000000014秒

3、从1000个文件中查询Ip次数最多的Ip,10.164.143.57:24,2.0分42.781000000000006秒

5      以上代码的公共变量

  1. public final Map<Integer,BufferedWriter> bwMap = new HashMap<Integer,BufferedWriter>();//保存每个文件的流对象
  2. public final Map<Integer,List<String>> dataMap = new HashMap<Integer,List<String>>();//分隔文件用
  3. private Map<String,Integer> ipNumMap = new HashMap<String, Integer>();//保存每个文件中的每个IP出现的次数
  4. private List<String> keyList = new LinkedList<String>();//保存次数出现最多的IP
  5. private int ipMaxNum = 0;//次数出现最多的值
  6. private long totalTime = 0;//计算统计所耗的时间

6      Main

  1. public static void main(String[] args) {
  2. /*
  3. * 1、第一次生成1亿(实际上最多为16581375)的ip地址,需要时间为3分多钟不到4分钟。
  4. */
  5. /*TooMuchIpFile tooMuchIpFile = new TooMuchIpFile();
  6. File ipFile = new File("e:/ipAddr.txt");
  7. try {
  8. ipFile.createNewFile();
  9. } catch (IOException e) {
  10. e.printStackTrace();
  11. }
  12. tooMuchIpFile.gernBigFile(ipFile, 100000000);*/
  13.  
  14. // System.err.println("128.128.80.226".hashCode()%1000);
  15. // System.err.println("128.128.80.227".hashCode());
  16. // System.err.println("10.128.80.227".hashCode());
  17. // System.err.println("10.0.80.227".hashCode());
  18.  
  19. /*
  20. * 1、第一次分割1亿数据的大文件,实在是太慢,运行差不多一小时,才分割出300W数据,耗时超过2个钟头
  21. * 2、第二次分割1亿数据的大文件,经过优化后,虽然比第一次有提升,但是还是很慢,耗时超过1个钟头.
  22. * 3、第三次分割1亿数据的大文件,经过优化后,虽然比第二次有提升,但是还是很慢,需耗时52.0分3.6秒
  23. * 4、第四次分割1亿数据的大文件,经过优化后,耗时13.0分35.10400000000004秒
  24. */
  25. TooMuchIpFile tooMuchIpFile = new TooMuchIpFile();
  26. File ipFile = new File("e:/ipAddr.txt");
  27. tooMuchIpFile.splitFile4(ipFile, 1000);
  28.  
  29. /*
  30. * 1、从1000个文件中查询Ip次数最多的Ip,10.164.143.57:24,3.0分18.748999999999995秒
  31. * 2、从1000个文件中查询Ip次数最多的Ip,10.164.143.57:24,3.0分27.366000000000014秒
  32. * 3、从1000个文件中查询Ip次数最多的Ip,10.164.143.57:24,2.0分42.781000000000006秒
  33. */
  34. // TooMuchIpFile tooMuchIpFile = new TooMuchIpFile();
  35. // File ipFiles = new File("e:/tmp/ip1/");
  36. // for (File ipFile : ipFiles.listFiles()) {
  37. // tooMuchIpFile.read(ipFile);
  38. // tooMuchIpFile.ipNumMap.clear();
  39. // }
  40. // System.err.println("======================出现次数最多的IP==================");
  41. // for(String key: tooMuchIpFile.keyList){
  42. // System.err.println(key + ":" + tooMuchIpFile.ipMaxNum);
  43. // }
  44. // System.err.println(DateUtil.convertMillsToTime(tooMuchIpFile.totalTime));
  45. }

海量日志数据提取某日访问百度次数最多的那个IP的Java实现的更多相关文章

  1. 14海量日志提取出现次数最多的IP

    问题描述:现有某网站海量日志数据,提取出某日访问该网站次数最多的那个IP. 分析:IP地址是32位的二进制数,所以共有N=2^32=4G个不同的IP地址, 如果将每个IP地址看做是数组的索引的话,那么 ...

  2. 一次flume exec source采集日志到kafka因为单条日志数据非常大同步失败的踩坑带来的思考

    本次遇到的问题描述,日志采集同步时,当单条日志(日志文件中一行日志)超过2M大小,数据无法采集同步到kafka,分析后,共踩到如下几个坑.1.flume采集时,通过shell+EXEC(tail -F ...

  3. 海量日志收集利器 —— Flume

    Flume 是什么? Flume是一个分布式.可靠.和高可用的海量日志聚合的系统,支持在系统中定制各类数据发送方,用于收集数据:同时,Flume提供对数据进行简单处理,并写到各种数据接受方(可定制)的 ...

  4. 面试笔试-脚本-1:使用shell脚本输出登录次数最多的用户

    原题目: 一个文本类型的文件,里面每行存放一个登陆者的IP(某些行是反复的),写一个shell脚本输出登陆次数最多的用户. 之前刚看到这个题目时,立即没有想到一行直接解决的办法,尽管知道能够先进行排序 ...

  5. Java面试基础--(出现次数最多的字符串)

    题目:给定字符串,求出现次数最多的那个字母及次数,如有多个 重复则都输出. eg,String data ="aaavzadfsdfsdhshdWashfasdf": 思路: 1. ...

  6. 使用python找出nginx访问日志中访问次数最多的10个ip排序生成网页

    使用python找出nginx访问日志中访问次数最多的10个ip排序生成网页 方法1:linux下使用awk命令 # cat access1.log | awk '{print $1" &q ...

  7. Python习题-统计日志中访问次数超过限制的IP

    #1.1分钟之内ip访问次数超过200次的,就给他的ip加入黑名单#需求分析: #1.读日志,1分钟读一次 #2.获取这1分钟之内所有访问的ip #3.判断ip出现的次数,如果出现200次,那么就加入 ...

  8. 大数据学习——有两个海量日志文件存储在hdfs

    有两个海量日志文件存储在hdfs上, 其中登陆日志格式:user,ip,time,oper(枚举值:1为上线,2为下线):访问之日格式为:ip,time,url,假设登陆日志中上下线信息完整,切同一上 ...

  9. MongoDB应用案例:使用 MongoDB 存储日志数据

    线上运行的服务会产生大量的运行及访问日志,日志里会包含一些错误.警告.及用户行为等信息,通常服务会以文本的形式记录日志信息,这样可读性强,方便于日常定位问题,但当产生大量的日志之后,要想从大量日志里挖 ...

随机推荐

  1. 泰晓科技 +兰大开源社区 +程序动态分析---LINUX内核网站

    http://www.tinylab.org/ http://linux-talents.tinylab.org/lzuoss/ http://www.tinylab.org/source-code- ...

  2. Oracle修改被占用的临时表结构

    这两天在修改临时表的类型时,提示”attempt to create,alter or drop an index on temporary table already in use“的错误,由于临时 ...

  3. C# Socket通信 小案例

    本文将编写2个控制台应用程序,一个是服务器端(server),一个是客户端(client), 通过server的监听,有新的client连接后,接收client发出的信息. server代码如下: u ...

  4. Java使用poi对Execl简单_写_操作

    public class WriteExecl { @Test public void writeExeclTest() throws Exception{ OutputStream os = new ...

  5. (转)HTML表格边框的设置小技巧

    对于很多初学HTML的人来说,表格<table>是最常用的标签了,但对于表格边框的控制,很多初学者却不甚其解. 对于很多初学HTML的人来说,表格<table>是最常用的标签了 ...

  6. tomcat的webapp下的root文件夹的作用是什么

    1.基本一样..只是表示不同的tomcat的http路径而已. root目录默认放的是tomcat自己的一个项目,如:http://localhost:8080/默认访问root项目 对于webapp ...

  7. 解决UITableView中Cell重用机制导致内容出错的方法总结

    UITableView继承自UIScrollview,是苹果为我们封装好的一个基于scroll的控件.上面主要是一个个的 UITableViewCell,可以让UITableViewCell响应一些点 ...

  8. iOS菜鸟之苹果开发者账号的注册

    大家一起来讨论讨论苹果开发者账号的注册(主要是以公司的开发者账号为例),前段时间公司要求注册开发者账号,于是我就特地看了看相关的帖子.这里简单给大家总结一下具体的流程. 首先你要登陆这个网址,进去之后 ...

  9. Java操作hbase总结

    用过以后,总得写个总结,不然,就忘喽. 一.寻找操作的jar包. java操作hbase,首先要考虑到使用hbase的jar包. 因为咱装的是CDH5,比较方便,使用SecureCRT工具,远程连接到 ...

  10. java编码转化方案-备用

    import java.io.UnsupportedEncodingException; /** * 转换字符串的编码 */ public class changeCharSet { /** 7位AS ...