在大多数情况下,CSV文件是包含以逗号分隔的记录的文本文件。但是,有时这些文件将以分号分隔。 (如果区域设置将小数分隔符设置为逗号,Excel将在保存CSV时使用分号分隔符 - 这在欧洲很常见。参考:http://en.wikipedia.org/wiki/Comma-separated_values#Application_support)
我的问题是,让程序猜测是用逗号分号还是以分号分隔的最佳方法是什么?
e.g。像1,1; 1,1这样的线可能不明确。它可以解释为逗号分隔为: 1 1; 1(一个字符串) 1
或分号分隔为 1,1 1,1
到目前为止,我最好的猜测是尝试使用和解析文件;分隔符,然后选择具有与第一行相同长度的行的解析(通常是标题行)。如果两者具有相同的行数,请选择具有更多列的行。这样做的主要缺点是额外的开销。
思想?
答案 0 :(得分:1)
根据您的工作情况,如果您保证有标题行,那么您尝试两者的方法可能是最好的整体练习。然后,一旦确定发生了什么,如果你进一步向下进入没有所需列数的行,那么你就知道格式不正确。
通常我会在上传时将其视为用户指定的选项,而不是程序化测试。
答案 1 :(得分:1)
如果每一行都应该具有相同的列数,我相信Excel就是这种情况,那么,使用逗号和分号,计算出行N和N + 1的列数。无论哪种方法(逗号或分号)产生不同的答案都是错误的(不是文件的格式)。你可以从头开始,你只需要去其中一个被证明不正确。您不需要标题行或任何内容。你没有必要阅读更多的文件,它不能给你一个错误的文件格式的答案,它可能会达到目的,还没有得出结论。您只需要为每一行保留相同数量的列属性。
答案 2 :(得分:1)
您可以阅读第一行
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是逗号还是分号可以使用最后一个值
答案 3 :(得分:0)
这是我的代码(没有对文本进行验证)......也许它可以帮助或建立基础:-)!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using MoreLinq; // http://stackoverflow.com/questions/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;
}
// ******************************************************************
}
}
答案 4 :(得分:0)
假设您的 csv 中有以下内容:
<!-- desserts.php -->
<!-- ##### New Recipe Area Start. This section displays all recipes from the database. ##### -->
<section class="small-receipe-area section-padding-80-0">
<div class="section-heading">
<h3>Dessert Recipes</h3>
</div>
<div class="container">
<div class="row">
<?php
while ($row = mysqli_fetch_assoc($result)){
list_of_recipes($row['recipe_name'], $row['recipe_img'], $row['recipe_link'], $row['stars'], $row['date_entered']);
}
?>
</div>
</div>
</section>
<!-- ##### New Recipe Area End ##### -->
<!-- recipe_list_component.php -->
<!-- ##### This function is called by desserts.php for every recipe found in the database in this category. ##### -->
<?php
function list_of_recipes($recipename, $recipeimg, $recipelnk, $stars, $recipedate){
$i = "";
$element = "
<!-- New Recipe Area -->
<div class=\"col-12 col-sm-6 col-lg-4\">
<div class=\"single-small-receipe-area d-flex\">
<!-- Recipe Thumb -->
<div class=\"receipe-thumb\">
<img src=\"$recipeimg\" alt=\"caramel_sauce\">
<!--<img src=\"img/bg-img/caramel1_thumb.jpg\" alt=\"\">-->
</div>
<!-- Recipe Content -->
<div class=\"receipe-content\">
<span>$recipedate</span>
<a href=\"$recipelnk\">
<h5>$recipename</h5>
</a>
<div class=\"ratings\">
<i class=\"fa fa-star\" aria-hidden=\"true\"></i>
<i class=\"fa fa-star\" aria-hidden=\"true\"></i>
<i class=\"fa fa-star\" aria-hidden=\"true\"></i>
<i class=\"fa fa-star\" aria-hidden=\"true\"></i>
<i class=\"fa fa-star\" aria-hidden=\"true\"></i>
</div>
<p>0 Comments</p>
</div>
</div>
</div>
";
echo $element;
}
?>
然后你可以使用python的内置CSV模块如下:
title,url,date,copyright,hdurl,explanation,media_type,service_version
打印名为 import csv
data = "title,url,date,copyright,hdurl,explanation,media_type,service_version"
sn = csv.Sniffer()
delimiter = sn.sniff(data).delimiter
的变量将返回 delimiter
,这是此处的分隔符。您可以使用一些不同的分隔符进行测试。