将树数据结构保存到文本文件JavaScript

将树数据结构保存到文本文件JavaScript,javascript,tree,text-files,Javascript,Tree,Text Files,我想将树结构保存到文本文件中,然后通过读取文本文件来重建文件。 它将用于文件树,该文件树应如下所示: rootnode |-dir 1 | |-file 1 | |-file 2 | |-dir 2 | |-dir 3 |-file 3.1 | |-dir 3.1 |-fileName 这是我的一个遍历: Tree.prototype.traversalDF = function(callBack) { (function depth(curren

我想将树结构保存到文本文件中,然后通过读取文本文件来重建文件。 它将用于文件树,该文件树应如下所示:

rootnode
|-dir 1
| |-file 1
| |-file 2
|
|-dir 2
|
|-dir 3
  |-file 3.1
  |
  |-dir 3.1
    |-fileName
这是我的一个遍历:

    Tree.prototype.traversalDF = function(callBack) {

        (function depth(currentNode) {
            for (var i=0, length = currentNode.children.length; i < length; i++) {
                depth(currentNode.children[i]);
            }
            callBack(currentNode);
        })(this._root);
    };
这只会将此“[object,object]”保存为相同的节点数。但是我想保存数据

这是节点和树属性:

//Every Node will have these properties
function Node(data) {
    this.data = data;
    this.children = [];
};

function Tree(data) {
    //this creates an instance of a node with data passed
    var node = new Node(data);
    //allows access to the properties of node
    this._root = node;

};
这是保存的数据,如何重建它:

{“数据”:“2.2”,“子项”:[]}
{“数据”:“2.1”,“儿童”:[]}
{“数据”:“2”,“子项”:[{“数据”:“2.1”,“子项”:[]},{“数据”:“2.2”,“子项”:[]}]
{“数据”:“柠檬”,“儿童”:[]}
{“数据”:“4.1”,“儿童”:[{“数据”:“柠檬”,“儿童”:[]}]}
{“数据”:“lemons2”,“子项”:[]}
{“数据”:“5.11”,“儿童”:[{“数据”:“lemons2”,“儿童”:[]}}
{“数据”:“4”,“儿童”:[{“数据”:“4.1”,“儿童”:[{“数据”:“柠檬”,“儿童”:[]}]},{“数据”:“5.11”,“儿童”:[{“数据”:“柠檬2”,“儿童”:[]}]}
{“数据”:“一”,“儿童”:[{“数据”:“2”,“儿童”:[{“数据”:“2.1”,“儿童”:[]},{“数据”:“2.2”,“儿童”:[]}},{“数据”:“4”,“儿童”:[{“数据”:“4.1”,“儿童”:[{“数据”:“柠檬”,“儿童”:[]}},{“数据”:“5.11”,“儿童”:[{“数据”:“柠檬2”,“儿童”:[]}]}}}
使用
JSON.stringify
而不仅仅是
traversalDF
回调中的
节点
。实际上,您根本不需要遍历它;您应该能够调用
JSON.stringify(obj)
对其进行序列化


要对其进行反序列化,只需在从文件中读取后使用
JSON.parse(/*string*/)

创建的树与所需的树相同,但它存储了所需的所有数据。以下是代码:

const fs = require('fs');
const path = require('path');



//Every Node will have these properties
function Node(data) {
    this.data = data;
    this.children = [];
};

function Tree(data) {
    //this creates an instance of a node with data passed
    var node = new Node(data);
    //allows access to the properties of node
    this._root = node;

};

//--------------------------graph traversal code--------------------------------//

Tree.prototype.traversalDF = function(callBack) {

    (function depth(currentNode) {
        for (var i=0, length = currentNode.children.length; i < length; i++) {
            depth(currentNode.children[i]);
        }
        callBack(currentNode);
    })(this._root);
};

Tree.prototype.traversalBF = function(node, pathPart) {
    //determines number of children of the given node

    var length = node.children.length;

    var i = 0;
    var found = false;
    //cycles through until there is a match
    while( found != true && i <= length){
        if(node.children[i] != null){
            if(node.children[i].data == pathPart){
                found = true;
                //when there is a match it returns the node

                return node.children[i];
            }
        } else if( i == length) {
            var nodeFile = new Node(pathPart);

            //adds the file name onto the the node
            node.children.push(nodeFile);
            //sets the node parent to the currentNode
        // nodeFile.parent = node;

            return nodeFile;
        }
        i++;
    }
}

Tree.prototype.add = function(path){
var pathSplit = path.split('/');
//gets the length of the path
var pathLength = pathSplit.length;
//this compares the path to the nodes/directories
let compare = (currentNode, n) => {

    if(n == pathLength -1){

        //create a new node with file name as data
        var nodeFile = new Node(pathSplit[n]);
        //adds the file name onto the the node
        currentNode.children.push(nodeFile);
    }else{
        var newNode = () => this.traversalBF(currentNode, pathSplit[n]);

        compare(newNode(), n+1);
    };

};
compare(this._root, 1);
};


var tree = new Tree('one');

tree.add('one/2/2.1');
tree.add('one/2/2.2');
tree.add('one/hi');
tree.add('one/4/4.1');


tree.add('one/4/4.1/lemons');
tree.add('one/4/5.11/lemons2');

    tree.traversalDF(function(node){
        console.log(node.data);
    });

    //writeFileSyn used instead on appendFile so it overwrites the data in the .txt
    //necessary to use 'writeFileSync' otherwise next line attempts to read an empty file
    fs.writeFileSync(path.join(__dirname, '/testTree.txt'), JSON.stringify(tree) + '\n', 'utf8');
    //reads data from txt file
    var treeRecon = JSON.parse(fs.readFileSync(path.join(__dirname, '/testTree.txt')));
    //creates a tree
    var Reconstructed = new Tree(treeRecon._root.data);
    console.log(Reconstructed);

    for (i = 0; i < treeRecon._root.children.length; i++) {
        //for each child in the root in the children of the root.
        //the children are pushed onto the roots children hence recreating it.
        Reconstructed._root.children.push(treeRecon._root.children[i]);
    }
    console.log(Reconstructed);

    Reconstructed.traversalDF(function(node){
        console.log(node.data);

    });
const fs=require('fs');
const path=require('path');
//每个节点都将具有这些属性
功能节点(数据){
这个数据=数据;
这是:children=[];
};
功能树(数据){
//这将创建传递数据的节点实例
var节点=新节点(数据);
//允许访问节点的属性
这个。_根=节点;
};
//--------------------------图遍历码--------------------------------//
Tree.prototype.traversalDF=函数(回调){
(功能深度(currentNode){
对于(变量i=0,长度=currentNode.children.length;ithis.traversalBF(currentNode,pathspilt[n]);
比较(newNode(),n+1);
};
};
比较(这是根,1);
};
变量树=新树(“一”);
添加('one/2/2.1');
添加('one/2/2.2');
树。添加('one/hi');
树。添加('one/4/4.1');
添加('1/4/4.1/柠檬');
添加('one/4/5.11/lemons2');
tree.traversalDF(函数(节点){
console.log(node.data);
});
//改为在appendFile上使用writeFileSyn,以便它覆盖.txt中的数据
//必须使用“writeFileSync”,否则下一行将尝试读取空文件
fs.writeFileSync(path.join(uu dirname,'/testTree.txt')、JSON.stringify(tree)+'\n',utf8');
//从txt文件读取数据
var treeRecon=JSON.parse(fs.readFileSync(path.join(uu dirname,'/testTree.txt'));
//创建一棵树
重建的var=新树(treeRecon.\u root.data);
console.log(重构);
对于(i=0;i
我以前尝试过,但收到了以下错误:“将循环结构转换为JSON”@helpplease在这种情况下,您有一个循环结构而不是一个树。您需要指定遇到重复引用时要执行的操作,因为默认情况下是无限递归(在现实世界中显然不可能)。无论如何,您都不应该对
深度
的所有参数调用
回调
,因为这将对
当前节点及其所有子节点调用
回调
,而我相信您只想对子节点执行此操作。不过,我相信您的代码应该像您描述的那样无限递归。如果循环引用是由于每个节点上的属性而不是
子节点
(我看到每个节点都有一个
父节点
属性,这很可能是罪魁祸首),您可能只需要将
回调(currentNode)
包装在
if(currentNode.children){}
block或类似内容。如果您能以类似JSON的格式发布一个
对象的示例,这将对我非常有帮助。解决方案可能不会像您希望的那样简单。不确定正确的术语。如果我不得不猜测,“树”实际上必须是非循环的,所以从技术上讲,具有父节点的节点实际上不是树(当然,它们在概念上是树)。如果我是你,我只需在整个结构上调用
JSON.stringify(…)
,而不是单个部分,然后调用
JSON.parse(…)
在字符串上。否则,您可能需要签出lodash.set以查看如何在对象上设置属性
2.1
。如果我稍后得到时间,我可能会决定帮助
const fs = require('fs');
const path = require('path');



//Every Node will have these properties
function Node(data) {
    this.data = data;
    this.children = [];
};

function Tree(data) {
    //this creates an instance of a node with data passed
    var node = new Node(data);
    //allows access to the properties of node
    this._root = node;

};

//--------------------------graph traversal code--------------------------------//

Tree.prototype.traversalDF = function(callBack) {

    (function depth(currentNode) {
        for (var i=0, length = currentNode.children.length; i < length; i++) {
            depth(currentNode.children[i]);
        }
        callBack(currentNode);
    })(this._root);
};

Tree.prototype.traversalBF = function(node, pathPart) {
    //determines number of children of the given node

    var length = node.children.length;

    var i = 0;
    var found = false;
    //cycles through until there is a match
    while( found != true && i <= length){
        if(node.children[i] != null){
            if(node.children[i].data == pathPart){
                found = true;
                //when there is a match it returns the node

                return node.children[i];
            }
        } else if( i == length) {
            var nodeFile = new Node(pathPart);

            //adds the file name onto the the node
            node.children.push(nodeFile);
            //sets the node parent to the currentNode
        // nodeFile.parent = node;

            return nodeFile;
        }
        i++;
    }
}

Tree.prototype.add = function(path){
var pathSplit = path.split('/');
//gets the length of the path
var pathLength = pathSplit.length;
//this compares the path to the nodes/directories
let compare = (currentNode, n) => {

    if(n == pathLength -1){

        //create a new node with file name as data
        var nodeFile = new Node(pathSplit[n]);
        //adds the file name onto the the node
        currentNode.children.push(nodeFile);
    }else{
        var newNode = () => this.traversalBF(currentNode, pathSplit[n]);

        compare(newNode(), n+1);
    };

};
compare(this._root, 1);
};


var tree = new Tree('one');

tree.add('one/2/2.1');
tree.add('one/2/2.2');
tree.add('one/hi');
tree.add('one/4/4.1');


tree.add('one/4/4.1/lemons');
tree.add('one/4/5.11/lemons2');

    tree.traversalDF(function(node){
        console.log(node.data);
    });

    //writeFileSyn used instead on appendFile so it overwrites the data in the .txt
    //necessary to use 'writeFileSync' otherwise next line attempts to read an empty file
    fs.writeFileSync(path.join(__dirname, '/testTree.txt'), JSON.stringify(tree) + '\n', 'utf8');
    //reads data from txt file
    var treeRecon = JSON.parse(fs.readFileSync(path.join(__dirname, '/testTree.txt')));
    //creates a tree
    var Reconstructed = new Tree(treeRecon._root.data);
    console.log(Reconstructed);

    for (i = 0; i < treeRecon._root.children.length; i++) {
        //for each child in the root in the children of the root.
        //the children are pushed onto the roots children hence recreating it.
        Reconstructed._root.children.push(treeRecon._root.children[i]);
    }
    console.log(Reconstructed);

    Reconstructed.traversalDF(function(node){
        console.log(node.data);

    });