C ++ - чтение столбцов CSV-файлов и сохранение только тех, которые начинаются с определенной строки

0

поэтому я пытаюсь выяснить, как сортировать файлы CSV, чтобы помочь организовать данные, которые мне нужны для экономической статьи. Файлы массивны и их много (около 587 мб файлов на молнии). Файлы организованы по столбцам, в которых все имена переменных находятся в первой строке, и все данные для этой переменной находятся под ней. Моя цель состоит в том, чтобы иметь возможность брать столбцы, начинающиеся с указанной строки (ex input: "MC1", Get: MC10RT2, MC1WE02,...), а затем сохранять их в отдельный файл. Кто-нибудь имеет какие-либо рекомендации относительно того, какую форму должен принимать код?

  • 0
    Используйте электронную таблицу. Они очень хороши в таких вещах. У некоторых даже есть язык сценариев.
  • 1
    Разве мне не нужно просматривать все нужные мне файлы? Проблема в том, что мне нужно отсортировать 145 файлов Excel в формате CSV. Могу ли я использовать сценарии между документами?
Теги:
csv

2 ответа

1
Лучший ответ

Просто для удовольствия небольшая программа, которая должна работать на вас. Вещь, в которую вы будете boost::split(columns, str, boost::is_any_of(","), boost::token_compress_off); - boost::split(columns, str, boost::is_any_of(","), boost::token_compress_off); что здесь создайте vector string из string csv-стиля.

Очень простой пример, но ваш вопрос был предлогом немного поиграть с алгоритмами boost string, которые я знал, но никогда не использовал...

#include <boost/algorithm/string.hpp>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <set>

// Typedefs for eye candy
typedef std::vector<std::string> Fields;
typedef std::vector<Fields> Results;
typedef std::set<unsigned long> Columns;


// Split the CSV string to a vector of string
Fields split_to_fields(const std::string& str)
{
  Fields columns;

  boost::split(columns, str, boost::is_any_of(","), 
    boost::token_compress_off);
  return columns;
}

// Read all the wanted columns
Results read_columns_of_csv(std::istream& stream, const Columns& wanted_columns)
{
  std::string str;  
  Results results;

  while (getline(stream, str))
  {
    Fields line{split_to_fields(str)};
    Fields fields;

    for (unsigned long wanted_column: wanted_columns)
    {
      if (line.size() < wanted_column)
      {
        std::cerr << "Line " << (results.size()  + 1 )
          << " does not contain enough fields: "
          << line.size() << " < " << wanted_column
          << std::endl;         
      }
      else
      {       
        fields.push_back(line[wanted_column]);
      }
    }

    results.push_back(fields);
  }

  return results;
}

// Read the ids of the columns you want to get
Columns read_wanted_columns(unsigned long max_id)
{
  Columns wanted_columns;
  unsigned long column;
  do
  {   
    std::cin >> column;

    if ((column < max_id)
        && (column > 0))
    {
      wanted_columns.insert(column - 1);
    }
  }
  while (column > 0);

  return wanted_columns;
}

// Whole read process (header + columns)
Results read_csv(std::istream& stream)
{
  std::string str;

  if (!getline(stream, str))
  {
    std::cerr << "Empty file !" << std::endl;
    return Results{};
  }

  // Get the column name
  Fields columns{split_to_fields(str)};

  // Output the column with id
  unsigned long column_id = 1;
  std::cout 
    << "Select one of the column by entering its id (enter 0 to end): " 
    << std::endl;
  for (const std::string elem: columns)
  {
    std::cout << column_id++ << ": " << elem << std::endl;
  };

    // Read the choosen cols
  return read_columns_of_csv(stream, read_wanted_columns(column_id));
}

int main(int argc, char* argv[])
{
    // Manage errors for filename
    if (argc < 2)
    {
        std::cerr << "Please specify a filename" << std::endl;
        return -1;
    }

    std::ifstream file(argv[1]);

    if (!file)
    {
         std::cerr << "Invalid filename: " << argv[1] << std::endl;   
         return -2;
    }

    // Process 
    Results results{read_csv(file)};

    // Output
    unsigned long line = 1;

    std::cout << "Results: " << results.size() << " lines" << std::endl;
    for (Fields fields: results)
    {
      std::cout << line++ << ": ";
      std::copy(fields.begin(), fields.end(), 
        std::ostream_iterator<std::string>(std::cout, ","));
      std::cout << std::endl;
    }

    return 0;
}
  • 0
    Это очень помогает, большое спасибо ... Я так сильно хочу тебя поддержать, но у меня недостаточно репутации, чтобы сделать это. Пожалуйста, знайте, что вы имеете мою благодарность. Если моя дипломная работа действительно будет опубликована, я вернусь на сайт, чтобы включить вас в качестве помощи.
0

Я предлагаю использовать вектор структур.

Структура позволит каждой строке иметь другой тип.

Ваша программа будет иметь следующую структуру:

  1. Чтение данных в вектор.
  2. Дополнительные необходимые поля из каждой структуры в векторе и запись в новый файл.
  3. Закройте все файлы.
  • 0
    Хорошо, на данный момент моя программа пустая, но я думал о векторе <vector <string >> для ввода всего этого, я предполагаю, что всякий раз, когда программа находит столбец, который она хочет, она просто делает строку ++, Есть ли что-то, что я должен иметь в виду с такой структурой?
  • 0
    Если вам не нужно сравнивать целые или двойные числа, тогда каждое поле (столбец) будет обрабатываться как строка.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню