处理CSV文件中的逗号

处理CSV文件中的逗号,csv,Csv,我正在寻找关于如何处理正在创建的csv文件的建议,然后由我们的客户上传,该文件的值中可能有逗号,如公司名称 我们正在考虑的一些想法是:引用标识符(值、值等)或使用|而不是逗号。最大的问题是我们必须让它变得简单,否则客户不会这么做 在字符串周围加双引号。一般来说是这样 阿拉·埃利 您将双引号转义为两个引号 双引号。例如。 “test1”、“foo”、“bar”、“test2” 2017年,csv完全指定为RFC 4180 它是一个非常常见的规范,并且被许多库()完全覆盖 只需使用任何易于获得的cs

我正在寻找关于如何处理正在创建的csv文件的建议,然后由我们的客户上传,该文件的值中可能有逗号,如公司名称


我们正在考虑的一些想法是:引用标识符(值、值等)或使用|而不是逗号。最大的问题是我们必须让它变得简单,否则客户不会这么做

在字符串周围加双引号。一般来说是这样

阿拉·埃利


您将双引号转义为两个引号 双引号。例如。 “test1”、“foo”、“bar”、“test2”


2017年,csv完全指定为RFC 4180

它是一个非常常见的规范,并且被许多库()完全覆盖

只需使用任何易于获得的csv库即可——即RFC 4180


CSV格式和如何处理逗号实际上有一个规范:


包含换行符(CRLF)、双引号和逗号的字段应包含在双引号中

因此,要获得值
foo
bar,baz
,您可以执行以下操作:

foo,"bar,baz"

另一个要考虑的重要要求(也从规格):


如果使用双引号括起字段,则使用双引号 出现在字段中时,必须在其前面加上 另一个双引号。例如:

"aaa","b""bb","ccc"

正如其他人所说,您需要转义包含引号的值。这里有一个C语言的CSV阅读器♯ 支持带引号的值,包括嵌入的引号和回车符

顺便说一下,这是经过单元测试的代码。我现在发布它是因为这个问题似乎经常出现,其他人可能不想要一个完整的库,而简单的CSV支持就可以了

您可以按如下方式使用它:

使用系统;
公开课考试
{
公共静态void Main()
{
使用(CsvReader reader=new CsvReader(“data.csv”))
{
foreach(reader.RowEnumerator中的字符串[]值)
{
WriteLine(“行{0}有{1}个值。”,reader.RowIndex,values.Length);
}
}
Console.ReadLine();
}
}
这些是课程。请注意,您也可以使用
Csv.Escape
函数编写有效的Csv

使用System.IO;
使用System.Text.RegularExpressions;
公共密封类CsvReader:System.IDisposable
{
公共CsvReader(字符串文件名):这个(新文件流(文件名,FileMode.Open,FileAccess.Read))
{
}
公共CsvReader(溪流)
{
__读卡器=新的流读卡器(流);
}
public System.Collections.IEnumerable行枚举器
{
得到{
如果(空==\uu读取器)
抛出新的System.ApplicationException(“没有CSV输入,我无法开始阅读”);
__rowno=0;
弦线;
字符串sNextLine;
while(null!=(sLine=\uu reader.ReadLine())
{
while(rexRunOnLine.IsMatch(sLine)&&null!=(sNextLine=\uu reader.ReadLine())
sLine+=“\n”+sNextLine;
__rowno++;
string[]values=rexCsvSplitter.Split(sLine);
for(int i=0;i-1)
s=报价+s+报价;
返回s;
}
公共静态字符串Unescape(字符串s)
{
如果(s.StartsWith(报价)和s.EndsWith(报价))
{
s=s.子串(1,s.长度-2);
如果(s.包含(转义)
s=s.Replace(转义,引号);
}
返回s;
}
private const string QUOTE=“\”;
私用常量字符串转义\u QUOTE=“\”\”;
私有静态字符[]字符,该字符必须被引用={',','“,'\n'};
}

您可以在字段周围加双引号。我不喜欢这种方法,因为它添加了另一个特殊字符(双引号)。只需定义转义字符(通常为反斜杠),并在需要转义的地方使用它:

data,more data,more data\, even,yet more 数据,更多数据,更多数据,甚至更多
您不必尝试匹配引号,而且要解析的异常也更少。这也简化了您的代码。

因为这是关于一般实践的,所以让我们从经验法则开始:

  • 不要使用CSV,而是使用XML和库来读写XML文件

  • 如果必须使用CSV。正确地执行此操作,并使用免费库解析和存储CSV文件

  • 为了证明1),大多数CSV解析器都不知道编码,因此如果您不处理US-ASCII,您就是在自找麻烦。 例如,Excel2002以本地编码存储CSV,而没有任何关于编码的说明。CSV标准没有被广泛采用:(。 另一方面,xml标准得到了很好的采用,它可以很好地处理编码

    为了证明这一点(2),几乎所有语言都有大量的csv解析器,因此即使解决方案看起来非常简单,也不需要重新发明轮子

    举几个例子:

    • 对于python,请使用内置模块

    • 对于perl,请检查CPAN和

    • 对于php,请使用内置fgetc
      test
      list, of, items
      "go" he said
      
      test
      "list, of, items"
      """go"" he said"
      
       Dim parser As TextFieldParser = New TextFieldParser("C:\mar0112.csv")
       parser.TextFieldType = FieldType.Delimited
       parser.SetDelimiters(",")      
      
         While Not parser.EndOfData         
            'Processing row             
            Dim fields() As String = parser.ReadFields         
            For Each field As String In fields             
               'TODO: Process field                   
      
            Next      
            parser.Close()
         End While 
      
      var csv = new CsvReader( textReader );
      var records = csv.GetRecords<MyClass>();
      
      var csv = new CsvReader( textReader );
      while( csv.Read() )
      {
          var intField = csv.GetField<int>( 0 );
          var stringField = csv.GetField<string>( 1 );
          var boolField = csv.GetField<bool>( "HeaderName" );
      }
      
      var csv = new CsvReader( textReader );
      csv.Configuration.Delimiter = "#";
      csv.Configuration.Quote = ''';
      // read the file however meets your needs
      
      ArrayList List = new ArrayList();
      static ServerSocket Server;
      static Socket socket;
      static ArrayList<Object> list = new ArrayList<Object>();
      
      
      public static void ReadFromXcel() throws FileNotFoundException
      {   
          File f = new File("Book.csv");
          Scanner in = new Scanner(f);
          int count  =0;
          String[] date;
          String[] name;
          String[] Temp = new String[10];
          String[] Temp2 = new String[10];
          String[] numbers;
          ArrayList<String[]> List = new ArrayList<String[]>();
          HashMap m = new HashMap();
      
               in.nextLine();
               date = in.nextLine().split(",");
               name = in.nextLine().split(",");
               numbers = in.nextLine().split(",");
               while(in.hasNext())
               {
                   String[] one = in.nextLine().split(",");
                   List.add(one);
               }
               int xount = 0;
               //Making sure the lines don't start with a blank
               for(int y = 0; y<= date.length-1; y++)
               {
                   if(!date[y].equals(""))
                   {   
                       Temp[xount] = date[y];
                       Temp2[xount] = name[y];
                       xount++;
                   }
               }
      
               date = Temp;
               name =Temp2;
               int counter = 0;
               while(counter < List.size())
               {
                   String[] list = List.get(counter);
                   String sNo = list[0];
                   String Surname = list[1];
                   String Name = list[2];
                   for(int x = 3; x < list.length; x++)
                   {           
                       m.put(numbers[x], list[x]);
                   }
                  Object newOne = new newOne(sNo, Name, Surname, m, false);
                   StudentList.add(s);
                   System.out.println(s.sNo);
                   counter++;
               }
      
      sed -r 's/([^,]*,[^,]*,[^,]*,)(.*)(,.*,.*)/\1"\2"\3/' inputfile
      
      ([^,]*)(,.*)                     #first field, regex
      "\1"\2                           #first field, substitution
      
      (.*,)([^,]*)                     #last field, regex
      \1"\2"                           #last field, substitution
      
      
      ([^,]*,)(.*)(,.*,.*,.*)          #second field (out of five fields)
      ([^,]*,[^,]*,)(.*)(,.*)          #third field (out of four fields)
      ([^,]*,[^,]*,[^,]*,)(.*)(,.*,.*) #fourth field (out of six fields)
      
      public static IEnumerable<string> SplitCSV(string line)
      {
          var s = new StringBuilder();
          bool escaped = false, inQuotes = false;
          foreach (char c in line)
          {
              if (c == ',' && !inQuotes)
              {
                  yield return s.ToString();
                  s.Clear();
              }
              else if (c == '\\' && !escaped)
              {
                  escaped = true;
              }
              else if (c == '"' && !escaped)
              {
                  inQuotes = !inQuotes;
              }
              else
              {
                  escaped = false;
                  s.Append(c);
              }
          }
          yield return s.ToString();
      }
      
      // Replace special CSV characters with single low-9 quotation mark
      func Scrub(a interface{}) string {
          s := fmt.Sprint(a)
          s = strings.Replace(s, ",", "‚", -1)
          s = strings.Replace(s, ";", "‚", -1)
          return s
      }
      
      URLEncoder.encode(myString,"UTF-8"); //to encode
      URLDecoder.decode(myEncodedstring, "UTF-8"); //to decode
      
      // The below two lines will split the columns as well as trim the DBOULE QUOTES around values but NOT within them
          string trimmedLine = line.Trim(new char[] { '\"' });
          List<string> values = trimmedLine.Split(new string[] { "\",\"" }, StringSplitOptions.None).ToList();
      
      ",(?=(?:[^"]*"[^"]*")*(?![^"]*"))"
      
      if (_expectedDataLength > 0 && values.Length != _expectedDataLength) 
      throw new DataLengthException(string.Format("Expected {0} columns when splitting csv, got {1}", _expectedDataLength, values.Length));
      
      public CsvReader(string fileName, int expectedDataLength = 0) : this(new FileStream(fileName, FileMode.Open, FileAccess.Read))
      {
          _expectedDataLength = expectedDataLength;
      }
      
      | American      | Europe        |
      | ------------- | ------------- |
      | 0.5           | 0,5           |
      | 3.14159265359 | 3,14159265359 |
      | 17.54         | 17,54         |
      | 175,186.15    | 175.186,15    |
      
      "hello",world"
      
          public static IEnumerable<string> LineSplitter(this string line, char 
               separator, char skip = '"')
          {
              var fieldStart = 0;
              for (var i = 0; i < line.Length; i++)
              {
                  if (line[i] == separator)
                  {
                      yield return line.Substring(fieldStart, i - fieldStart);
                      fieldStart = i + 1;
                  }
                  else if (i == line.Length - 1)
                  {
                      yield return line.Substring(fieldStart, i - fieldStart + 1);
                      fieldStart = i + 1;
                  }
      
                  if (line[i] == '"')
                      for (i++; i < line.Length && line[i] != skip; i++) { }
              }
      
              if (line[line.Length - 1] == separator)
              {
                  yield return string.Empty;
              }
          }
      
      function csv_to_array($filename='', $delimiter=',')
      {
          if(!file_exists($filename) || !is_readable($filename))
              return FALSE;
      
          $header = NULL;
          $data = array();
          if (($handle = fopen($filename, 'r')) !== FALSE)
          {
              while (($row = fgetcsv($handle, 1000, $delimiter)) !== FALSE)
              {
                  if(!$header)
                      $header = $row;
                  else
                      $data[] = array_combine($header, $row);
              }
              fclose($handle);
          }
          return $data;
      }