首页 > 解决方案 > 有没有办法直接从一个大文件中拆分和使用字符串?

问题描述

我正在尝试解析 Huuuge JSON 文件并将其转换为 CSV。JSON 文件包含很多对象,只是用“”(空格)分隔。这些对象甚至不包括在列表中 '[{...},{...}]' 这是一个对象类型。在文件中,有成千上万的人互相关注: {"name":"cmp1","homepage_url":" http://google.fr ","number_of_employees":0.0,"founded_year":0.0,"founded_month ":0.0,"founded_day":0.0,"deadpooled_year":0.0,"total_money_raised":"5000"}

查看每个字符,并根据 '{' 和 '}' 的数量查找 JSON 中的对象。但这太慢了。

RandomAccessFile raf = new RandomAccessFile(JsonInputFilePath, "rw");
            int now = 0;
            int open =0;
            int close = 0;
            String currentNode = "";
             long length = raf.length();
            while(length > now) {
                currentNode = currentNode +  (char)raf.readByte();

            raf.seek(now);
                            now++;
            char currentChar = (char)raf.readByte();
            if( currentChar == '{') {
                open ++;
            }
            if( currentChar == '}') {
                close = close +1;
                if(close  == open) {

                    open = 0;
                    close = 0;
                    JsonReader reader = new  JsonReader(new StringReader(currentNode));
                                            //process data with the Json reader -><-

                                    }
                            }
                    }

我希望能够在每次找到完整对象时处理数据。这是一个非常大的文件(150mo)。因此,一次阅读所有内容不是一种选择。

标签: javasplitstreamstreamreaderfilesize

解决方案


  1. 此处不要使用 RandomAccess,它只是一个 seq 访问用例。
  2. 使用基本堆栈(级别)实现简单的 DFA
  3. 将文件解析与json解析分开

    public void processObject(String json) {
        System.out.println(json);
    }
    
    public void read(String file) throws IOException {
        try (FileReader r = new FileReader(file)) {
          int i;
          int level = 0;
          StringBuilder sb = new StringBuilder();
          while((i = r.read()) != -1) {
            char c = (char)i;
            switch(c) {
             case '{':
               sb.append(c);
               level++;
               break;
             case '}':
              sb.append(c);
              level--;
              if (level == 0) {
                processObject(sb.toString());
                sb = new StringBuilder();
              }
              break;
             default:
               if (level > 0) {
                 sb.append(c);
               }
               else {
                 // Ignore chars between objects
               }
            }
          }
        }
    }
    

推荐阅读