ChatGPT解决这个技术问题 Extra ChatGPT

处理 CSV 文件中的逗号

csv

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

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

客户正在编写并上传
在 iOS 上,基本上您必须使用 github.com/Flinesoft/CSVImporter
我有完全相同的问题,试图在逗号分隔的 csv 文件中汇总一列。 awk 命令没有问题。不幸的是,某些单元格可能包含逗号(例如在地址中),而其他单元格则不会。正在寻找兼容 Linux 的解决方案,但不知道从哪里开始。
首先,让客户遵循 RFC-4180 并用双引号将包含逗号或换行符的字段括起来。如果您正在构建自己的数据处理管道,您可以查看 github.com/dbro/csvquote,它可以让 awk、cut、sort、wc 等工具正确地忽略嵌入的逗号和换行符。

T
TylerH

实际上有一个 CSV 格式的规范,RFC 4180 以及如何处理逗号:

包含换行符 (CRLF)、双引号和逗号的字段应该用双引号括起来。

http://tools.ietf.org/html/rfc4180

因此,要获得值 foobar,baz,您可以这样做:

foo,"bar,baz"

另一个需要考虑的重要要求(也来自规范):

如果使用双引号将字段括起来,则出现在字段内的双引号必须通过在其前面加上另一个双引号来进行转义。例如:"aaa","b""bb","ccc"


不是真正的规范,但仍然可能很方便。它说...“不存在正式的规范,它允许对 CSV 文件进行多种解释。本节记录了大多数实现似乎遵循的格式。”
此外,不要忘记,尽管名称如此,但行中的 CSV 值不仅可以用逗号分隔 - 至少在 Windows 平台上是这样。它取决于当前的区域设置(命令行中的 intl.cpl,“高级设置”),特别是列表分隔符:System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator
R
Rory O'Kane

正如其他人所说,您需要转义包含引号的值。这是 C♯ 中的一个小 CSV 阅读器,它支持引用的值,包括嵌入的引号和回车符。

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

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

using System;
public class test
{
    public static void Main()
    {
        using ( CsvReader reader = new CsvReader( "data.csv" ) )
        {
            foreach( string[] values in reader.RowEnumerator )
            {
                Console.WriteLine( "Row {0} has {1} values.", reader.RowIndex, values.Length );
            }
        }
        Console.ReadLine();
    }
}

这是课程。请注意,您也可以使用 Csv.Escape 函数来编写有效的 CSV。

using System.IO;
using System.Text.RegularExpressions;

public sealed class CsvReader : System.IDisposable
{
    public CsvReader( string fileName ) : this( new FileStream( fileName, FileMode.Open, FileAccess.Read ) )
    {
    }

    public CsvReader( Stream stream )
    {
        __reader = new StreamReader( stream );
    }

    public System.Collections.IEnumerable RowEnumerator
    {
        get {
            if ( null == __reader )
                throw new System.ApplicationException( "I can't start reading without CSV input." );

            __rowno = 0;
            string sLine;
            string sNextLine;

            while ( null != ( sLine = __reader.ReadLine() ) )
            {
                while ( rexRunOnLine.IsMatch( sLine ) && null != ( sNextLine = __reader.ReadLine() ) )
                    sLine += "\n" + sNextLine;

                __rowno++;
                string[] values = rexCsvSplitter.Split( sLine );

                for ( int i = 0; i < values.Length; i++ )
                    values[i] = Csv.Unescape( values[i] );

                yield return values;
            }

            __reader.Close();
        }
    }

    public long RowIndex { get { return __rowno; } }

    public void Dispose()
    {
        if ( null != __reader ) __reader.Dispose();
    }

    //============================================


    private long __rowno = 0;
    private TextReader __reader;
    private static Regex rexCsvSplitter = new Regex( @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))" );
    private static Regex rexRunOnLine = new Regex( @"^[^""]*(?:""[^""]*""[^""]*)*""[^""]*$" );
}

public static class Csv
{
    public static string Escape( string s )
    {
        if ( s.Contains( QUOTE ) )
            s = s.Replace( QUOTE, ESCAPED_QUOTE );

        if ( s.IndexOfAny( CHARACTERS_THAT_MUST_BE_QUOTED ) > -1 )
            s = QUOTE + s + QUOTE;

        return s;
    }

    public static string Unescape( string s )
    {
        if ( s.StartsWith( QUOTE ) && s.EndsWith( QUOTE ) )
        {
            s = s.Substring( 1, s.Length - 2 );

            if ( s.Contains( ESCAPED_QUOTE ) )
                s = s.Replace( ESCAPED_QUOTE, QUOTE );
        }

        return s;
    }


    private const string QUOTE = "\"";
    private const string ESCAPED_QUOTE = "\"\"";
    private static char[] CHARACTERS_THAT_MUST_BE_QUOTED = { ',', '"', '\n' };
}

您可能还需要翻译 \r\n 以符合 Windows,具体取决于您的应用程序。
@NadaNaeem,需要详细说明吗?
它没有正确计算 csv 文件行中的项目,它不能很好地处理字段中的逗号,勇气返回和点击
除了在极少数情况下,您的解决方案效果很好,我已经提供了详细的答案,说明了原因。
@MinhTran - "" 用于转义 C# 逐字字符串中的双引号。
r
reechard

CSV 格式使用逗号分隔值,包含回车符、换行符、逗号或双引号的值用双引号括起来。包含双引号的值被引用,并且每个文字引号都被紧接在前面的引号转义:例如,3 个值:

test
list, of, items
"go" he said

将被编码为:

test
"list, of, items"
"""go"" he said"

任何字段都可以被引用,但只有包含逗号、CR/NL 或引号的字段必须被引用。

CSV 格式没有真正的标准,但几乎所有应用程序都遵循记录在案的约定here。其他地方提到的 RFC 不是 CSV 的标准,它是在 MIME 中使用 CSV 的 RFC,并且包含一些非常规和不必要的限制,使其在 MIME 之外无用。

我见过的许多 CSV 模块不适应的一个问题是,可以在单个字段中编码多行,这意味着您不能假设每行都是单独的记录,您要么不需要在您的数据或准备好处理这个问题。


g
gargoylebident

在字符串周围加上双引号。这通常是 what Excel does

阿拉伊莱,

您将双引号转义为两个双引号。例如 "test1","foo""bar","test2"


与引用标识符基本相同的概念
您将双引号转义为两个双引号。例如 "test1","foo""bar","test2"
当 " 后面紧跟逗号时,仅在字符串周围加上双引号是行不通的
A
Adam Jaskiewicz

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

data,more data,more data\, even,yet more

您不必尝试匹配引号,并且要解析的异常更少。这也简化了您的代码。


快速而肮脏,但如果您实际上有一个包含“\”的条目,则不起作用
Sarp,这就是为什么双 \\ 是一个转义的反斜杠,因为它现在变成了另一个特殊字符。
这有效,但不是 CSV。这是a DSV
N
NikolaiDante

通过 nuget 可以使用一个库来处理几乎所有格式良好的 CSV (.net) - CsvHelper

映射到类的示例:

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

More Documentation


如果您包含一个如何使用 CsvHelper 库来解决 OP 问题的示例,那就更好了。
C
Community

如果您使用的是 *nix 系统,则可以访问 sed,并且可以有一个或多个 仅在 中不需要的逗号CSV 的特定字段,您可以按照 RFC4180 Section 2 的建议使用以下单行符将它们包含在 " 中:

sed -r 's/([^,]*,[^,]*,[^,]*,)(.*)(,.*,.*)/\1"\2"\3/' inputfile

根据不需要的逗号可能在哪个字段中,您必须更改/扩展正则表达式(和替换)的捕获组。上面的示例将第四个字段(共六个)括在引号中。

https://i.stack.imgur.com/cOxbi.png

结合 --in-place-option,您可以将这些更改直接应用于文件。

为了“构建”正确的正则表达式,需要遵循一个简单的原则:

对于 CSV 中在包含不需要的逗号的字段之前出现的每个字段,您编写一个 [^,]*,并将它们全部放在一个捕获组中。对于包含您编写 (.*) 的不需要的逗号的字段。对于带有不需要的逗号的字段之后的每个字段,您编写一个 ,.* 并将它们全部放在一个捕获组中。

以下是根据特定字段的不同可能的正则表达式/替换的简短概述。如果未给出,则替换为 \1"\2"\3

([^,]*)(,.*)                     #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)

如果您想用 sed 删除不需要的逗号,而不是用引号将它们括起来,请参阅 this answer


M
MikeDub

正如我在对 harpo 的回答的评论中提到的那样,他的解决方案很好,并且在大多数情况下都有效,但是在某些情况下,当逗号彼此直接相邻时,它无法在逗号上拆分。

这是因为 Regex 字符串意外地表现为逐字字符串。为了使这种行为正确,正则表达式字符串中的所有 " 字符都需要手动转义,而不使用逐字转义。

IE。正则表达式应该是使用手动转义的:

",(?=(?:[^\"\"]*\"\"[^\"\"]*\"\")*(?![^\"\"]*\"\"))"

翻译成 ",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"

使用逐字字符串 @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))" 时,它的行为如下所示,如果您调试正则表达式,则可以看到:

",(?=(?:[^"]*"[^"]*")*(?![^"]*"))"

所以总而言之,我推荐 harpo 的解决方案,但要注意这个小问题!

我在 CsvReader 中包含了一些可选的故障保护,以在发生此错误时通知您(如果您有预先知道的列数):

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;
}

您将如何处理标题行?我正在尝试将 csv 映射到所有类型的 C# 对象,但标题行打破了它,因为它的所有字符串......
[^""][^"] 不一样吗?在字符类规范中重复字符是多余的,对吧?
M
Mike Mackintosh

添加对 Microsoft.VisualBasic 的引用(是的,它说是 VisualBasic,但它也可以在 C# 中工作 - 请记住,最后它只是 IL)。

使用 Microsoft.VisualBasic.FileIO.TextFieldParser 类解析 CSV 文件下面是示例代码:

 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 

是的,这是一个在有点不幸的命名空间中非常有用的类;-)。但是,要解决原始问题,您还应该设置 parser.HasFieldsEnclosedInQuotes = true; 并且输入文件需要根据 CSV 规范将包含逗号的字段括在引号中 - excel 已经这样做了。
R
Rufus Pollock

您可以使用其他“分隔符”,例如“;”或“|”但最简单的可能只是引用大多数(体面的)CSV 库和最体面的电子表格支持的引用。

对于more on CSV delimiters and a spec for a standard format for describing delimiters and quoting see this webpage


N
Neil

如果您想重新发明轮子,以下可能对您有用:

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();
}

H
H. Pauwelyn

在欧洲我们有这个问题一定比这个问题更早。在欧洲,我们使用逗号作为小数点。请参阅下面的数字:

| American      | Europe        |
| ------------- | ------------- |
| 0.5           | 0,5           |
| 3.14159265359 | 3,14159265359 |
| 17.54         | 17,54         |
| 175,186.15    | 175.186,15    |

因此无法对 CSV 文件使用逗号分隔符。因此,欧洲的 CSV 文件用分号 (;) 分隔。

Microsoft Excel 等程序可以读取带有分号的文件,并且可以从分隔符切换。您甚至可以使用制表符 (\t) 作为分隔符。请参阅this answer from Supper User


K
Konstantine Nikka-Sher Piterma

这是一个简洁的小解决方法:

您可以改用希腊小数字符号 (U+0375)

好像是这样 ͵

使用这种方法也可以为您节省大量资源......


P
Phil

如果您对有关如何解析文件(以 CSV 为例)的更具教育性的练习感兴趣,可以查看 Julian Bucknall 的this article。我喜欢这篇文章,因为它把事情分解成更小的问题,这些问题更不容易克服。你首先创建一个语法,一旦你有了一个好的语法,将语法转换为代码是一个相对容易和有条理的过程。

文章使用C#,底部有下载代码的链接。


N
Nadar

我知道差不多 13 年后了,但我们遇到了类似的情况,客户端向我们输入 CSV 并使用逗号输入值,有 2 个用例:

如果客户端使用 Windows Excel 客户端编写 CSV(通常在 Windows 环境中就是这种情况),那么会自动将逗号添加到值中。

CSV 的实际文本值:

3786962,1st Meridian Care Services,John,"Person A,Person B, Person C, Person D",Voyager

如果客户以编程方式向您发送 excel,那么他应该遵守 RFC4180 并用“引号”将值括起来。例子:

Col1, Col2, "a, b, c", Col4


J
Jonathan Wood

只需在 NuGet 上使用 SoftCircuits.CsvParser。它将为您处理所有这些细节并有效地处理非常大的文件。而且,如果需要,它甚至可以通过将列映射到对象属性来导入/导出对象。此外,我的测试表明它的平均速度比流行的 CsvHelper 快近 4 倍。


P
Piotr Czapla

由于这是关于一般实践,让我们从经验法则开始:

不要使用 CSV,而是使用带有库的 XML 来读取和写入 xml 文件。如果您必须使用 CSV。正确执行并使用免费库来解析和存储 CSV 文件。

为了证明 1) 的合理性,大多数 CSV 解析器都没有编码意识,所以如果你不处理 US-ASCII,你就是在自找麻烦。例如,excel 2002 将 CSV 存储在本地编码中,而没有任何关于编码的注释。 CSV 标准没有被广泛采用 :(。另一方面 xml 标准被很好地采用并且它很好地处理了编码。

为了证明 2) 的合理性,几乎所有语言都有大量的 csv 解析器,因此即使解决方案看起来很简单,也无需重新发明轮子。

仅举几例:

对于 python 使用构建在 csv 模块中

对于 perl 检查 CPAN 和 Text::CSV

对于 php 使用内置 fgetcsv/fputcsv 函数

对于 java 检查 SuperCVS 库

如果你不打算在嵌入式设备上解析它,真的没有必要手动实现它。


XML 并不总是答案。当您有大量密集的表格数据(即电子表格)时,CSV 是适合该工作的格式。这些标签引入了很多开销,如果每一行都有相同的格式,则不需要明确每个值代表什么。当您有复杂的分层数据或带有可选字段的记录时,XML 非常有用。情况并非总是如此。
从理论上讲,“标签”会带来一些开销,但我想不出任何现实生活中的应用程序开始成为问题。你有任何实际的例子吗?要处理数据,应该使用数据库而不是 csv。如果我们谈论数据序列化(备份、数据交换),解析需要一周而不是 5 天是否重要?
基本上,在任何情况下,您都拥有最适合用表格表示的数据。假设您有来自十几个不同传感器的数据,您经常对其进行采样,并记录当时每个传感器的时间戳和值。每条记录都是相同的:timestamp, sensor0, sensor1, ... sensor11。 XML 非常适合表示复杂、不规则的数据,但它是一种相当重量级的格式,并不适合每一种情况。吻
我完全同意 xml 不能解决所有问题。特别是它不适合作为数据库替代品,也不适合配置文件。但这里的问题是关于 XML 设计用于的数据交换。
这取决于数据是什么,而不是它的用途。我不知道正在传输什么数据,所以我不确定 CSV 是否最合适,但如果它确实是常规的表格数据,那么表格格式比分层格式更有意义。人们经常将应该是 XML 的数据硬塞到另一种格式中,但我认为相反的情况同样糟糕,这是我的一个小烦恼。
E
Eric

您可以像这样读取 csv 文件。

这利用了拆分并处理了空间。

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++;
         }

h
hariszhr

我通常对可以包含任何逗号或任何特殊字符的字段进行 URL 编码。然后在任何视觉媒体中使用/显示时对其进行解码。

(逗号变成 %2C)

每种语言都应该有对字符串进行 URL 编码和解码的方法。

例如,在java中

URLEncoder.encode(myString,"UTF-8"); //to encode
URLDecoder.decode(myEncodedstring, "UTF-8"); //to decode

我知道这是一个非常通用的解决方案,对于用户想要手动查看 csv 文件内容的情况可能并不理想。


u
user1451111

我通常在我的 CSV 文件解析例程中执行此操作。假设“line”变量是 CSV 文件中的一行,并且所有列的值都用双引号括起来。执行以下两行后,您将在“值”集合中获得 CSV 列。

// 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();

为什么我的代码永远不会在 StackOverflow 上以多种颜色显示?我缩进四个空格。
D
Daniel

我发现的最简单的解决方案是 LibreOffice 使用的解决方案:

将所有文字“替换为”在字符串周围加上双引号

您还可以使用 Excel 使用的那个:

将所有文字 " 替换为 "" 在字符串周围加上双引号

请注意,其他人建议只执行上述第 2 步,但这不适用于 " 后跟 , 的行,例如在 CSV 中,您希望有一个包含字符串 hello",world 的列,因为 CSV 会显示:

"hello",world"

这被解释为具有两列的行:helloworld"


根据标准规则,任何包含拆分字符或引号的字段都被引号包围,并且其中的任何引号都是双引号,因此没有问题。您的 hello",world 字段只需保存为 "hello"",world",即可 100% 正确解析。
R
Rajat26
    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;
        }
    }

G
G_real

我使用了 Csvreader 库,但通过使用它,我通过从列值中的逗号(,)爆炸来获取数据。

因此,如果您想在大多数列值中插入包含逗号(,)的 CSV 文件数据,您可以使用以下函数。作者链接=> https://gist.github.com/jaywilliams/385876

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;
}

p
parag patel

我使用 papaParse 库来解析 CSV 文件并获得键值对(键/标题/CSV 文件值的第一行)。

这是我使用的示例:

https://codesandbox.io/embed/llqmrp96pm

它有 dummy.csv 文件,可以进行 CSV 解析演示。

我已经在 reactJS 中使用过它,尽管它很容易在用任何语言编写的应用程序中复制。


v
virgban

一个示例可能有助于展示如何在 .csv 文件中显示逗号。创建一个简单的文本文件,如下所示:

将此文本文件保存为后缀为“.csv”的文本文件,并在 Windows 10 中使用 Excel 2000 打开它。

aa,bb,cc,d;d "在电子表格演示中,下面的行应该看起来像上面的行,除了下面显示的是逗号而不是 d 之间的分号。" aa,bb,cc,"d,d", 即使在 Excel 中也可以使用

aa,bb,cc,"d,d", 即使在 Excel 2000 中也有效 aa,bb,cc,"d ,d", 即使在 Excel 2000 中也有效 aa,bb,cc,"d , d", 这有效即使在 Excel 2000 中

aa,bb,cc, "d,d", 这在 Excel 2000 中由于第一个引号后面的空格而失败 aa,bb,cc, "d ,d", 这在 Excel 2000 中由于第一个引号后面的空格而失败aa,bb,cc, "d , d", 这在 Excel 2000 中由于第一个引号后面的空格而失败

aa,bb,cc,"d,d" ,即使在 Excel 2000 中也可以使用,即使在第二个引号前后都有空格。 aa,bb,cc,"d ,d" ,即使在 Excel 2000 中也可以使用,即使在第二个引号前后都有空格。 aa,bb,cc,"d , d" ,即使在 Excel 2000 中也可以使用,即使在第二个引号前后都有空格。

规则:如果要在 .csv 文件的 aa 单元格(字段)中显示逗号:“以双引号开始和结束字段,但避免在第一个引号之前出现空格”


C
Community

首先,让我们问自己,“为什么我们觉得需要以不同的方式处理 CSV 文件的逗号?”

对我来说,答案是,“因为当我将数据导出到 CSV 文件时,字段中的逗号消失了,我的字段被分隔成多个字段,逗号出现在原始数据中。” (这是因为逗号是 CSV 字段分隔符。)

根据您的情况,分号也可以用作 CSV 字段分隔符。

根据我的要求,我可以使用一个看起来像逗号的字符,例如单个低 9 引号。

所以,这里是你如何在 Go 中做到这一点:

// 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
}

Replace 函数中的第二个逗号外观字符是十进制 8218。

请注意,如果您的客户端可能只有 ascii 文本阅读器,则此十进制 8218 字符看起来不像逗号。如果这是您的情况,那么我建议根据 RFC 4128 使用带有双引号的逗号(或分号)将该字段括起来:https://www.rfc-editor.org/rfc/rfc4180


j
jamesdeath123

我认为这个问题最简单的解决方案是让客户在 excel 中打开 csv,然后 ctrl + r 用你想要的任何标识符替换所有逗号。这对客户来说非常容易,只需更改一次代码即可读取您选择的分隔符。


谁说他们有 Excel?事实上,谁说它甚至是一个正在上传的人?...
P
Pierre

使用制表符 (\t) 分隔字段。


-1 很好,直到有人在他们的价值中使用一个标签,然后你就可以回到提出问题的人遇到的问题。将一个定界符字符换成另一个字符并不能解决问题。
废话。人们不能在他们的数据输入中输入标签。在大多数表单中,这只是将数据输入点移动到下一个字段。
“人们不能在他们的数据输入中输入标签”......你是认真的吗? A)当然,一个人可以在输入字段中放置一个选项卡 B)谁说它是数据来自的 GUI? C)谁说它甚至是输入数据的人?