题目如下:

1. 300G xml 文件,3000w 数据量, 每条数据写入20ms,要求 24小时内跑完。

2. 示例内容格式如下:

<page>

    <title>Q12926095</title>

    <ns>0</ns>

    <id>14386122</id>

    <revision>

      <id>37251228</id>

     <timestamp>2013-05-07T16:35:15Z</timestamp>

      <contributor>

       <username>Sk!dbot</username>

        <id>4341</id>

      </contributor>

      <comment>/* wbeditentity-create:0|*/</comment>

      <model>wikibase-item</model>

     <format>application/json</format>

      <textxml:space="preserve">{&quot;type&quot;:&quot;item&quot;,&quot;id&quot;:&quot;Q12926095&quot;,&quot;labels&quot;:{&quot;new&quot;:{&quot;language&quot;:&quot;new&quot;,&quot;value&quot;:&quot;\u0921\u093f\u0921\u0938\u093e\u0930\u0940,\u092d\u091f\u0935\u093e\u0921\u0940\u0924\u0939\u0938\u0940\u0932&quot;}},&quot;descriptions&quot;:[],&quot;aliases&quot;:[],&quot;claims&quot;:[],&quot;sitelinks&quot;:{&quot;newwiki&quot;:{&quot;site&quot;:&quot;newwiki&quot;,&quot;title&quot;:&quot;\u0921\u093f\u0921\u0938\u093e\u0930\u0940,\u092d\u091f\u0935\u093e\u0921\u0940\u0924\u0939\u0938\u0940\u0932&quot;,&quot;badges&quot;:[]}}}</text>

     <sha1>hvpmqlzhqk6ysjzqledwm9txz4i4d0f</sha1>

    </revision>

  </page>

3. <page> 后跟着新的<page>内容体。

4. 设计一个最快的将内容解析并写入到mysql数据库的方法。

5. 编码,并预估 所有数据导入的时间。





解决方案之一:



package com.test.bigFile;


import java.util.concurrent.Executors;

import java.util.concurrent.ScheduledExecutorService;

import java.util.concurrent.TimeUnit;


/**

 * 入口函数

 * 

 * @author felly

 *

 */

public class Main {


    /// 20个线程*24小时*3600秒*50条记录

    public static void main(String args[]) throws Exception {

        String file = "F:/娱乐/游戏/动作/古墓丽影/cpy-rottr20yc.iso";

        int pix = 1024 * 10;/// 每次读取1M

        int threadNum = 20;

        long fileLength = 300*1024*1024*1024L ;


        long pos = 0;//// 位置

        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(20);

        

        while (true) {

          

            for (int i = 0; i < threadNum; i++) {

                pos = pos + i * pix;

                 

                scheduledThreadPool.schedule(new SplitFileThread(file, pos, pix), 1, TimeUnit.SECONDS);


            }


            if (pos >= fileLength) {

                System.out.println("调度完毕,等待执行完成!");

                break;

            }

        }

        scheduledThreadPool.shutdown();

    }

}



package com.test.bigFile;


import java.io.RandomAccessFile;

import java.util.ArrayList;

import java.util.Iterator;

import java.util.List;


///按设计的块为单位读取文件内容

public class SplitFileThread extends Thread {

    private String filePath;/// 文件路径

    private long startPos;/// 开始位置

    private int readLength;// 读取长度

    private RandomAccessFile bigFile = null;


    public SplitFileThread(String filePath, long startPos, int readLength) throws java.io.IOException {

        this.filePath = filePath;

        this.startPos = startPos;

        this.readLength = readLength;

        bigFile = new RandomAccessFile(filePath, "r");

    }


    private final int BLOCK = 1024;


    public void run() {

        try {

            bigFile.seek(startPos);// 移动文件指针位置


            byte[] buff = new byte[BLOCK]; ////

            // 用于保存实际读取的字节数

            int hasRead = 0;

            // 循环读取

            List<String> tokens = new ArrayList<String>((int) (readLength / 0.75));

            int sum = 0;///// 计算读取的长度

            while ((hasRead = bigFile.read(buff)) > 0) {

                // 打印读取的内容,并将字节转为字符串输入

                sum += hasRead;

                tokens.add(new String(buff, 0, hasRead));


                if (sum >= readLength) {

                    break;

                }


            }


            new ParseAndInsertThread(tokens).start();


        } catch (Exception e) {

            ///

            e.printStackTrace();

        } finally {

            try {

                bigFile.close();

            } catch (Exception e) {

                e.printStackTrace();

            }

        }


    }


    /**

     * 解析并写入数据库,这里要求内容完整<page>开始,</page>结束

     * 

     * @author felly

     *

     */

    class ParseAndInsertThread extends Thread {

        private List<String> data;


        ParseAndInsertThread(List<String> data) {

            this.data = data;

        }


        public void run() {

            int len = data.size();

            List<List<String>> insertData = new ArrayList<List<String>>(len);

            Iterator<String> its = data.iterator();

            try {

                while (its.hasNext()) {

                    insertData.add(parseData(its.next()));

                }

                batchInsertDB(insertData);


            } catch (Exception e) {

                ////

                e.printStackTrace();


            } finally {

                System.out.println("当前执行完成进度:" + (startPos + readLength));

            }


        }


    }


    //// 批量插入数据库方法


    public void batchInsertDB(List<List<String>> insertData) {


        ///// 批量写入mysql并一次提交,这里就不实现了


    }


    public List<String> parseData(String data) {

        List<String> item = new ArrayList<String>();


        /// 解析字符传,并将得到的值按顺序写入item

        /// todo item.add。。。

        //// 速度最快的话应该是用字符解析最快,不考虑用第三方框架


        return item;

    }

}



本文版权归作者,欢迎转载,但未经作者同意必须在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。