Подтвердить что ты не робот

Как программно угадать, является ли CSV файл запятой или точкой с запятой

В большинстве случаев CSV файлы представляют собой текстовые файлы с записями, разделенными запятыми. Однако иногда эти файлы будут разделены точкой с запятой. (Excel будет использовать разделители с запятой при сохранении CSV, если региональные настройки имеют десятичный разделитель, заданный как запятая - это распространено в Европе. Ссылка: http://en.wikipedia.org/wiki/Comma-separated_values#Application_support)

Мой вопрос в том, что лучший способ угадать, есть ли у него запятая или точка с запятой?

например. строка типа 1,1; 1,1 может быть неоднозначной. Его можно интерпретировать как запятую, как: 1 1; 1 (строка) 1

или точка с запятой 1,1 1,1

Мое лучшее догадка заключается в попытке разбора файла как с помощью, так и с; разделители, затем выберите синтаксический разбор, который имеет большинство строк той же длины, что и первая строка (обычно строка заголовка). Если оба имеют одинаковое количество строк, выберите тот, у которого больше столбцов. Основным недостатком этого является дополнительные накладные расходы.

Мысли?

4b9b3361

Ответ 1

В зависимости от того, с чем вы работаете, если вы гарантируете строку заголовка, ваш подход к попыткам обоих, может быть лучшей общей практикой. Затем, как только вы определите, что происходит, если вы дойдете до строки ниже, которая не имеет необходимого количества столбцов, вы знаете, что формат неверен.

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

Ответ 2

Если каждая строка должна иметь одинаковое количество столбцов, что, я считаю, имеет место в Excel, то, используя как запятые, так и точки с запятой, выведите число столбцов для строк N и N + 1. Какой бы метод (запятая или точка с запятой) не выдавал другой ответ, а не формат файла). Вы можете начать с самого начала, и вам нужно идти только до тех пор, пока один из них не окажется неверным. Вам не нужны строки заголовка или что-то еще. Вам не нужно читать больше файла, чем это необходимо, и он не может дать вам неправильный ответ для формата файла, он просто может прийти к концу и еще не пришел к выводу. Все, что вам нужно, это то, что каждая строка имеет такое же количество свойств столбцов.

Ответ 3

Вы можете прочитать первую строку

FileReader fileReader = new FileReader(filePath);
    BufferedReader bufferedReader = new BufferedReader(fileReader);
    String s = bufferedReader.readLine();
    String substring = s.substring(s.indexOf(firstColumnName) + 3, s.indexOf(firstColumnName) + 4);
    bufferedReader.close();
    fileReader.close();
    substring.charAt(0);

Затем вы фиксируете это значение

substring.charAt(0)

в зависимости от того, может ли CSV запятая или точка с запятой использовать последнее значение

Ответ 4

Это мой код (без проверки на текст)... возможно, это может помочь или сделать базу:-)!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using MoreLinq; // http://stackoverflow.com/info/15265588/how-to-find-item-with-max-value-using-linq

namespace HQ.Util.General.CSV
{
    public class CsvHelper
    {
        public static Dictionary<LineSeparator, Func<string, string[]>>  DictionaryOfLineSeparatorAndItsFunc = new Dictionary<LineSeparator, Func<string, string[]>>();

        static CsvHelper()
        {
            DictionaryOfLineSeparatorAndItsFunc[LineSeparator.Unknown] = ParseLineNotSeparated;
            DictionaryOfLineSeparatorAndItsFunc[LineSeparator.Tab] = ParseLineTabSeparated;
            DictionaryOfLineSeparatorAndItsFunc[LineSeparator.Semicolon] = ParseLineSemicolonSeparated;
            DictionaryOfLineSeparatorAndItsFunc[LineSeparator.Comma] = ParseLineCommaSeparated;
        }

        // ******************************************************************
        public enum LineSeparator
        {
            Unknown = 0,
            Tab,
            Semicolon,
            Comma
        }

        // ******************************************************************
        public static LineSeparator GuessCsvSeparator(string oneLine)
        {
            List<Tuple<LineSeparator, int>> listOfLineSeparatorAndThereFirstLineSeparatedValueCount = new List<Tuple<LineSeparator, int>>();

            listOfLineSeparatorAndThereFirstLineSeparatedValueCount.Add(new Tuple<LineSeparator, int>(LineSeparator.Tab, CsvHelper.ParseLineTabSeparated(oneLine).Count()));
            listOfLineSeparatorAndThereFirstLineSeparatedValueCount.Add(new Tuple<LineSeparator, int>(LineSeparator.Semicolon, CsvHelper.ParseLineSemicolonSeparated(oneLine).Count()));
            listOfLineSeparatorAndThereFirstLineSeparatedValueCount.Add(new Tuple<LineSeparator, int>(LineSeparator.Comma, CsvHelper.ParseLineCommaSeparated(oneLine).Count()));

            Tuple<LineSeparator, int> bestBet = listOfLineSeparatorAndThereFirstLineSeparatedValueCount.MaxBy((n)=>n.Item2);

            if (bestBet != null && bestBet.Item2 > 1)
            {
                return bestBet.Item1;
            }

            return LineSeparator.Unknown;
        }

        // ******************************************************************
        public static string[] ParseLineCommaSeparated(string line)
        {
            // CSV line parsing : From "jgr4" in http://www.kimgentes.com/worshiptech-web-tools-page/2008/10/14/regex-pattern-for-parsing-csv-files-with-embedded-commas-dou.html
            var matches = Regex.Matches(line, @"\s?((?<x>(?=[,]+))|""(?<x>([^""]|"""")+)""|""(?<x>)""|(?<x>[^,]+)),?",
                                        RegexOptions.ExplicitCapture);

            string[] values = (from Match m in matches
                               select m.Groups["x"].Value.Trim().Replace("\"\"", "\"")).ToArray();

            return values;
        }

        // ******************************************************************
        public static string[] ParseLineTabSeparated(string line)
        {
            var matchesTab = Regex.Matches(line, @"\s?((?<x>(?=[\t]+))|""(?<x>([^""]|"""")+)""|""(?<x>)""|(?<x>[^\t]+))\t?",
                            RegexOptions.ExplicitCapture);

            string[] values = (from Match m in matchesTab
                                select m.Groups["x"].Value.Trim().Replace("\"\"", "\"")).ToArray();

            return values;
        }

        // ******************************************************************
        public static string[] ParseLineSemicolonSeparated(string line)
        {
            // CSV line parsing : From "jgr4" in http://www.kimgentes.com/worshiptech-web-tools-page/2008/10/14/regex-pattern-for-parsing-csv-files-with-embedded-commas-dou.html
            var matches = Regex.Matches(line, @"\s?((?<x>(?=[;]+))|""(?<x>([^""]|"""")+)""|""(?<x>)""|(?<x>[^;]+));?",
                                        RegexOptions.ExplicitCapture);

            string[] values = (from Match m in matches
                               select m.Groups["x"].Value.Trim().Replace("\"\"", "\"")).ToArray();

            return values;
        }

        // ******************************************************************
        public static string[] ParseLineNotSeparated(string line)
        {
            string [] lineValues = new string[1];
            lineValues[0] = line;
            return lineValues;
        }

        // ******************************************************************
        public static List<string[]> ParseText(string text)
        {
            string[] lines = text.Split(new string[] { "\r\n" }, StringSplitOptions.None);
            return ParseString(lines);
        }

        // ******************************************************************
        public static List<string[]> ParseString(string[] lines)
        {
            List<string[]> result = new List<string[]>();

            LineSeparator lineSeparator = LineSeparator.Unknown;
            if (lines.Any())
            {
                lineSeparator = GuessCsvSeparator(lines[0]);
            }

            Func<string, string[]> funcParse = DictionaryOfLineSeparatorAndItsFunc[lineSeparator];

            foreach (string line in lines)
            {
                if (string.IsNullOrWhiteSpace(line))
                {
                    continue;
                }

                result.Add(funcParse(line));
            }

            return result;
        }

        // ******************************************************************
    }
}