Могу ли я импортировать данные CSV в localStorage как МАССИВ, а не ОБЪЕКТ?

Предполагается, что следующий код импортирует данные в localStorage из файла CSV. Цель состоит в том, чтобы заменить/обновить любые существующие данные localStorage. Я использую FileReader для импорта и пытаюсь использовать JSON.stringify, чтобы сохранить его в localStorage.

const fileInput = document.getElementById('csv');

const readFile = () => {
  const reader = new FileReader();
  
  reader.onload = () => {
    localStorage.setItem("entry_list", JSON.stringify(reader.result));
  }
  reader.readAsArrayBuffer(fileInput.files[0]);
};

fileInput.addEventListener('change', readFile);

Я считаю, что проблема в том, что он пытается импортировать это как ОБЪЕКТ, а не МАССИВ. Как мне подойти к этой проблеме или решить эту проблему?

ОБНОВЛЯТЬ: Благодаря ответу, опубликованному zzzggghhh ниже, мне удалось решить эту проблему на 90%. Единственная оставшаяся проблема заключается в том, что один из элементов массива, который является числом, должен быть числом с плавающей запятой. Таким образом, метод разделения должен каким-то образом учитывать это. Возможно ли это вообще?

Вот что импортируется:

Мне нужно, чтобы его импортировали следующим образом (без кавычек в плавающей запятой):

в чем проблема или проблема вашего кода?

Mr. Brickowski 08.04.2024 11:51

Вот для этого я и прошу помощи. При импорте данные импортируются неправильно. Кажется, что из импорта CSV создается ОБЪЕКТ вместо МАССИВА. Кроме того, он не передает никаких данных. В файле CSV есть данные, но они не импортируются.

user3146788 08.04.2024 11:58
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
2
77
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Проблема в том, что вы пытаетесь использовать JSON.stringify на объекте ArrayBuffer. ArrayBuffer не имеет перечислимых свойств объекта и, следовательно, становится просто {} при строковом преобразовании.

Либо превратите его в обычный массив, используя JSON.stringify(Array.from(new Uint8Array(reader.result))), чтобы получить каждый байт в файле как число, либо — моя рекомендация, поскольку его легче снова превратить в файл и хранить меньшего размера — не читайте его как ArrayBuffer в первом поместите, а как URI данных (который будет использовать кодировку Base64), заменив readAsArrayBuffer на readAsDataURL.

Однако, основываясь на ваших комментариях, я теперь совершенно уверен, что вы хотели бы также проанализировать содержимое CSV, а не просто сохранить файл. В этом случае взгляните на один из многочисленных пакетов анализа CSV, например csv-parse.

Вот пример того, как его использовать:

const fileInput = document.getElementById('csv');

const readFile = () => {
  const reader = new FileReader();
  
  reader.onload = () => {
    const csvData = csv_parse_sync.parse(reader.result, { columns: true });
    // Commented out because sandboxed demo cannot access localStorage
    //localStorage.setItem("entry_list", JSON.stringify(csvData));
    
    // For demo purposes, show would normally get stored
    document.getElementById('output').innerText = JSON.stringify(csvData);
  }
  reader.readAsText(fileInput.files[0]);
};

fileInput.addEventListener('change', readFile);
<script src = "https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/sync.min.js"></script>

<input type = "file" id = "csv">

<pre id = "output"></pre>

Вместо CDN, который я использовал здесь, вы обычно копируете соответствующий файл из пакета на свой сервер (или устанавливаете пакет там, если можете) и ссылаетесь на файл таким образом.

Да, надеюсь, я не перепутал. Я не хочу хранить его в виде файла. У меня уже есть данные в файле CSV. Та часть моего кода, которая здесь не показана, работает отлично. Мне нужно прочитать данные в CSV и поместить в localStorage (обновить/заменить) то, что уже есть. Я надеюсь в этом есть смысл. Спасибо

user3146788 08.04.2024 12:02

Да, но каким образом? CSV-файл содержит только байты. Вам решать, как их интерпретировать. Я предполагаю, что вы хотите проанализировать CSV в массив объектов на основе имен столбцов, и в этом вам могут помочь такие пакеты, как csv-parse, но вы этого не сказали. С таким же успехом вы можете хранить массив массивов ячеек или просто текст, анализируемый в какой-либо кодировке, например UTF-8. (Или необработанные байты, как я изначально думал.)

CherryDT 08.04.2024 12:04

Хорошо, я должен признать, я новичок, поэтому, возможно, я не совсем знаю, «что сказать». В настоящее время у меня есть массив объектов в локальном хранилище. Все, что я хочу сделать, это заменить или обновить эти данные данными, хранящимися в CSV. Я последую вашему совету и поищу дополнительную информацию о синтаксическом анализе csv, хотя он предназначен для Node.JS, который я не использую. Нет ли подхода с использованием ванильного JS?

user3146788 08.04.2024 12:11

Не уверен, что это поможет, но я попробовал это: localStorage.setItem("entry_list", JSON.stringify(Array.from(reader.result))); но массив по-прежнему пуст в localStorage, но ошибок нет

user3146788 08.04.2024 12:22

Нет, csv-parse также для браузера. Цитирую страницу, на которую я дал ссылку: Multiple distributions: Node.js, Web, ECMAScript modules and CommonJS. Все это объяснено на их сайте.

CherryDT 08.04.2024 12:24

Кроме того, что касается того, что вы пробовали в последний раз, это тоже не может сработать, потому что вы забыли промежуточное преобразование в new Uint8Array, как я показал в своем ответе выше. Но теперь я совершенно уверен, что исходное содержимое файла вам все равно не понадобится.

CherryDT 08.04.2024 12:25

Первый шаг в инструкциях по синтаксическому анализу csv: Запустите npm install csv, чтобы установить полный модуль CSV, или запустите npm install csv-parse, если вас интересует только синтаксический анализатор CSV. У меня нет Node.JS, и это должно быть решение на стороне клиента. Я ценю эту помощь, но мне нужен практический пример. Думаю, мне нужно нанять кого-нибудь, чтобы помочь мне найти решение. Я действительно не думал, что получить практический пример или демо-версию от этого сообщества так сложно. Я, очевидно, иду по пути, который выходит за рамки моих навыков. Спасибо...

user3146788 08.04.2024 12:32

Обычно ваш интерфейс в настоящее время также использует узел для сборки. В конце вы получаете только код на стороне клиента, но процесс сборки использует пакеты узлов, поэтому в первом объяснении используется npm, но вам не обязательно идти по этому пути. Вы также можете использовать предоставленный браузерный дистрибутив IIFE, на веб-сайте это также показано в качестве примера. Я собираюсь добавить это более подробно в свой ответ, теперь, когда я совершенно уверен, что понимаю, что вам нужно.

CherryDT 08.04.2024 12:40

Я добавил конкретный пример.

CherryDT 08.04.2024 12:47

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

const fileInput = document.getElementById('csv')

const update = async () => {
    const [header, ... rows] = (await fileInput.files[0].text()).trim().split(/[\r\n]+/).map(line => line.split(','))
    const records = rows.map(row => row.reduce((record, field, i) => Object.assign(record, {[header[i]]: field}), {}))
    localStorage.setItem("entry_list", JSON.stringify(records))
}

fileInput.addEventListener('change', update) 

Это неправильно анализирует файл CSV. (И нет, разделения запятыми тоже будет недостаточно, потому что вы можете иметь поля в кавычках, вы также можете иметь поля в кавычках, охватывающие несколько строк, и вы можете экранировать кавычки внутри полей в кавычках.) - Вот почему я предложил использовать существующая библиотека для этого.

CherryDT 08.04.2024 12:29

Ваш тоже, ему решать, какой сторонний пакет CSV он хочет использовать.

zzzggghhh 08.04.2024 12:31

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

CherryDT 08.04.2024 12:33

Вы действительно можете получить файл.

zzzggghhh 08.04.2024 12:34

Посмотрите сами: jsfiddle.net/ytcksnbL — вы получаете некоторый HTML-мусор, потому что в конечном итоге получаете страницу 404, пытаясь получить данные из URL-адреса [object%20File].

CherryDT 08.04.2024 12:35

Круто, он не опубликовал HTML, поэтому я предположил, что это код сервера Node.

zzzggghhh 08.04.2024 12:42

Спасибо, zzzggghhh, это очень близко приближает меня к успеху. Я думаю, что узнаю, что здесь происходит. Кажется, есть одна небольшая проблема: если у меня возникают проблемы, я думаю, что это связано с тем, как они разбиваются, и выходные данные должны быть массивом или массивами... Вот что я получаю, используя ваше решение: '[" type,title,amount","expense,Rent,1900","expense,Hydro,100‌​"]' Что мне нужно: '[{"type,title,amount"},{"expense,Rent,1900 "},{"expense,Hydr‌​o,100"]}' Возможно, я перепутал терминологию, думаю, мы называем это массивом массива?

user3146788 08.04.2024 13:06

Возможно, это сложно понять, но я отредактировал его, добавив что-то, что должно подойти для вашего случая. Было бы лучше использовать существующий пакет, например csv-parse, и импортировать его в реальный проект веб-приложения. Вы можете узнать о Node.js и Express.js, это хорошее место для начала создания веб-приложения.

zzzggghhh 08.04.2024 14:44

zzzggghhh, Еще раз спасибо за эту информацию, и как только я закончу этот проект, я рассмотрю Node и Express. Предоставленный вами код работает нормально, за исключением чисел, которые, как я считаю, должны быть числами с плавающей запятой (возможно ли это?). Я не очень хорош в обратном проектировании вашего кода, но с помощью консоли я обнаружил, что это то, что я получаю: 0: {type: 'expense', title: 'Rent', sum: '1900'} где мне нужно это: 0: {type: 'expense', title: 'Rent', sum: 1900} убрать кавычки из номера, я не неблагодарный, я многому учусь, мне бы хотелось купить пользователю кофе на этом сайте .

user3146788 08.04.2024 15:27

@ user3146788 В CSV нет типов данных, поэтому вы не можете отличить строку 123 от числа 123. Однако если вы знаете, что в определенном столбце всегда есть числа, вы можете сопоставить значения с числами в конце. Или вы можете реализовать эвристику, в которой вы используете регулярное выражение, например -?\d+(\.\d+)?, для обнаружения вещей, которые выглядят как числа, а затем преобразуют их в реальные числа.

CherryDT 09.04.2024 00:29

Привет, CherryDT, ну, у меня не было слов, чтобы описать это так, как у тебя, но это была моя мысль. Способ нацеливания на последний элемент (ключ: количество. значение: число с плавающей запятой) каждой строки, поскольку он всегда будет числом с плавающей запятой. Признаюсь, я пока не совсем понимаю, как я думаю, array.row[2]. Или разрезать массив и собрать его заново, что, как я теперь знаю, является регулярным выражением. Мне придется это изучить. Мне бы хотелось использовать готовый код, предоставленный zzzhhhggg, потому что я в значительной степени понимаю, что там происходит. Мне нужно это число как число с плавающей запятой, потому что остальная часть приложения выполняет несколько математических вычислений, которые теперь не работают.

user3146788 09.04.2024 04:19
Ответ принят как подходящий

Вот что я придумал. Кажется, это работает. Спасибо всем, кто помог.

const fileInput = document.getElementById('csv');

const update = async () => {
    const [header, ...rows] = (await fileInput.files[0].text()).trim().split(/[\r\n]+/).map(line => line.split(','));
    const records = rows.map(row => {
        // Assuming the last column is a float
        const floatValue = parseFloat(row[row.length - 1]);
        // Remove the last element (float value) from the row
        const fields = row.slice(0, -1);
        // Create the record object with fields and float value
        const record = fields.reduce((record, field, i) => Object.assign(record, { [header[i]]: field }), {});
        // Add the float value to the record
        record[header[header.length - 1]] = floatValue;
        return record;
    });
    // Save data to localStorage
    localStorage.setItem("entry_list", JSON.stringify(records));
};

fileInput.addEventListener('change', update);

Другие вопросы по теме