Node.js-循环读取和写入成千上万的JSON文件

时间:2019-06-26 08:48:26

标签: javascript node.js fs

我需要以最有效,最快捷的方式处理大量文件。

读取->处理->写入(保存到同一位置)。

我的问题是我的执行速度很慢,至少我认为是这样。我花了半个小时左右的时间处理了600000个文件。

我故意以同步方式完成此操作,如果可以更好地异步完成-我愿意接受解决方案,我只是不认为处理很多只有1-3kb的文件会花费那么长时间。

文件具有简单的JSON数据,就像我已经说过的那样,每个文件的大小约为1-3kb。

这些文件位于单独的文件夹中,每个文件夹包含300个文件。我将它们分开以使其更有效和可用。

因此,我们有〜2000个文件夹,每个文件夹包含300个文件(1-3kb大小)。

看看我的代码,给我个想法。谢谢!

function test() {

    /**
     * Get list of folders and loop through
     */
    const folderList = fs.readdirSync(`../db`)

    for (const folder of folderList) {

        /**
         * Get list of files for each folder and loop through
         */
        const fileList = fs.readdirSync(`../db/${ folder }`)

        for (const filePath of fileList) {

            /**
             * try/catch block to handle JSON.parse errors
             */
            try {

                /**
                 * Read file
                 */
                const file = JSON.parse(fs.readFileSync(`../db/${ folder }/${ filePath }`))

                /**
                 * Process file
                 */
                processFile(file)

                /**
                 * Write file
                 */
                fs.writeFileSync(`../db/${ folder }/${ filePath }`, JSON.stringify(file), 'utf8')

            } catch (err) {

                console.log(err)

            }
        }
    }
}

我希望它运行得很快,实际上这需要一段时间。

2 个答案:

答案 0 :(得分:0)

伙计们,所以我想出了这个解决方案作为测试,您能否检查一下并让我知道它是否是一个好的实现?处理600k文件所需的时间约为10-15分钟,而不是数小时。每个“文件夹”中都有300个文件,因此我们始终等待300个承诺完成。我这样做是因为文件很小(1-3kb,一个对象,没什么花哨的)。可以做得更好吗,例如可以在一分钟内完成吗? :)

async function test() {

    const folderList = fs.readdirSync(`../db`)

    for (const folder of folderList) {

        console.log(folder)

        const fileList = fs.readdirSync(`../db/${ folder }`)

        let promises = []

        for (const fileName of fileList) {
            promises.push(processFile(site, folder, fileName))
        }

        await Promise.all(promises)

    }
}

async function processFile(folder, fileName) {

    const path = `../db/${ folder }/${ fileName }`

    const file = await readFile(path)

    if (file){
        //do something and write
        await writeFile(path)
    }

}

function readFile(path) {
    return new Promise(function (resolve) {

        fs.readFile(path, function (err, raw) {

            if (err) {
                console.log(err)
                resolve()
                return
            }

            try {
                const file = JSON.parse(raw)
                resolve(file)
            } catch (err) {
                console.log(err)
                resolve()
            }

        })

    })
}

function writeFile(path, object) {
    return new Promise(function (resolve) {

        fs.writeFile(path, JSON.stringify(object), function (err) {
            if (err)
                console.log(err)

            resolve()
        })

    })
}

答案 1 :(得分:0)

所以,在玩了一些东西之后,我想到了这样的东西:

const PromisePool = require('es6-promise-pool')

const list = require('./list.json')

let n = 0

let pool = new PromisePool(promiseProducer, 11)

pool.start()
    .then(function () {
        console.log('Complete')
    })

function promiseProducer(){

    console.log(n)

    if (n < list.length)
        return processFile(list[++n])
    else
        return null
}

运行速度非常快。不过,我还有一些问题。

  1. 任何人都可以编写自己的并发限制实现吗?没有库等
  2. 像以前一样,如果我运行脚本并等待处理20k个文件(例如),如果我停止脚本并重新运行,它将很快达到20k(在此停止),然后会变慢。是什么原因?