Объект CSV-файла в JSON в угловой

#json #angular #typescript #csv

Вопрос:

В интерфейсе моего приложения я хотел проанализировать некоторые данные, связанные с загружаемым ими CSV. С помощью инструмента загрузки файлов я сначала получаю объект списка файлов, а затем извлекаю из него 1 файл.

Я хочу превратить его в объект json, который я мог бы затем повторить. Я думал использовать csv-анализатор пользователя из узла, но я не вижу способа использовать файловый объект, хранящийся в памяти.

Как я могу этого добиться?

Сначала я занимался:

 let f = fileList.item(0);
let decoder = new window.TextDecoder('utf-8');
f.arrayBuffer().then( data => {
   let _data = decoder.decode(data)
   console.log("Dataset", data, _data)
});
 

И это означало передачу буфера массива и декодирование строки. Хотя я мог бы написать универсальный инструмент, который обрабатывает эти строковые данные на основе n и’, я хотел, чтобы это было немного легче читать.

Я хотел сделать что-то вроде:

 let json = csvParser(f)
 

есть ли способ использовать csv-анализатор пользователя из узла (3.0.0) или есть другой инструмент, который я должен использовать? Я думал, что модули управления на основе браузера ( новое окно.TextDecoder (…)) — плохая форма, так как у него есть возможность потерпеть неудачу.

Есть ли инструмент, который делает это? я пытаюсь создать некоторые примеры данных и, учитывая файл, выбранный из входного типа=»файл», я бы хотел, чтобы это было просто и прямолинейно.

Приведенный ниже пример работает, но я чувствую зависимость от окна, и внутреннее чувство заставляет меня думать, что это наивно.

 const f : File = fileList.item(0)
console.log("[FOO] File", f)
let decoder = new window.TextDecoder('utf-8');
f.arrayBuffer().then( data => {
    let _data = decoder.decode(data)
    console.log("Dataset", data, _data)
    let lines = _data.split("n")
    let headers = lines[0].split(',')
    let results = []
    for ( let i = 1; i < lines.length; i  ) {
        let line = lines[i]
        let row = {}
        line.split(",").forEach( (item, idx) => {
            row[headers[idx]] = item;
        })
        results.push(row)
    }
    console.log("JSON ARRAY", results)
})
 

Проблема, с которой я сталкиваюсь, когда останавливаюсь и делаю: ng serve заключается в том, что ему не нравится использовать функцию ArrayBuffer и получать доступ к TextDecoder из окна, поскольку эти функции/классы не являются частью файла и окна соответственно во время сборки.

Есть какие-нибудь мысли?

Ответ №1:

Это то, что я в конечном итоге сделал, учитывая ввод файла, передаваемый в эту функцию:

 updateTranscoders(project: Project, fileList: FileList, choice: string = 'replace') {
    const f: File = fileList.item(0)
        //Reads a File into a string.
        function readToString(file) : Promise<any> {
            const reader = new FileReader();
            const future = new Promise( (resolve,reject) => {
                reader.addEventListener("load", () => {
                    resolve(reader.result);
                }, false)
                reader.addEventListener("error", (event) => {
                    console.error("ERROR", event)
                    reject(event)
                }, false)
                reader.readAsText(file)
            }); 
            return future;
        }
        readToString(f).then( data => {
            let lines = data.split("n")
            let headers = lines[0].split(',')
            let results = []
            for (let i = 1; i < lines.length; i  ) {
                let line = lines[i]
                let row = {}
                line.split(",").forEach((item, idx) => {
                    row[headers[idx]] = item;
                })
                results.push(row)
            }
            if (choice.toLowerCase() === 'replace'){
                let rows = project.csvListContents.toJson().rows.filter( row => row.isDeployed)
                rows.push( ...results)
                project.csvListContents = CsvDataset.fromJson({ rows: rows })
            }else if (choice.toLowerCase() === 'append') {
                let r = project.csvListContents.toJson();
                r.rows.push(...results);
                project.csvListContents = CsvDataset.fromJson(r);
            }else {
                alert("Invalid option for Choice.")
            }
                
            this.saveProject(project)
        })
    }
 

Теперь в части ВЫБОРА кода у меня есть двоичный вариант для жесткой замены содержимого CSV или просто добавления к нему. Затем я бы соответственно сохранил проект. Это также означает, что первая строка содержит заголовки столбцов.