Java 带有临时stringwrapper的正则表达式拆分行-can和#xB4;我不懂正则表达式

Java 带有临时stringwrapper的正则表达式拆分行-can和#xB4;我不懂正则表达式,java,regex,coldfusion,Java,Regex,Coldfusion,在csv导入程序中查找错误时遇到问题。任何决议都是伟大的 csv有这样的行。。。。正如您所看到的,引号并非围绕所有字段。 1.“昆德”;“录像机”;“名称” 2: 10000000;29;“xyz公司” 以下正则表达式应提供一个包含所有要导入的字段值的数组 line.split(;(?=([^\”]*\“[^\”]*\”*[^\“]*$)”,-1) 我必须描述一下,我不理解这个正则表达式 问题似乎是,引号并不总是被删除。所以我的插入是“xyz公司”,这是错误的 另外,整个过程非常慢。我们必须导入

在csv导入程序中查找错误时遇到问题。任何决议都是伟大的

csv有这样的行。。。。正如您所看到的,引号并非围绕所有字段。
1.“昆德”;“录像机”;“名称”
2: 10000000;29;“xyz公司”

以下正则表达式应提供一个包含所有要导入的字段值的数组

line.split(;(?=([^\”]*\“[^\”]*\”*[^\“]*$)”,-1)

我必须描述一下,我不理解这个正则表达式

问题似乎是,引号并不总是被删除。所以我的插入是“xyz公司”,这是错误的

另外,整个过程非常慢。我们必须导入数百万行…导入程序运行了数小时…不太好。
任何关于如何优化正则表达式的想法;这似乎是最大的瓶颈。

我处理csv文件所用的最快方法是cfhttp,但这是有缺陷的,很难在现实生活中使用。要导入csv提要,我们使用一个将csv数据保存到查询中的函数。然后我们将查询数据导入数据库

注意:使用James Moberg建议的CSV解析器可能会更快

资料来源:


“Kunde”;“Vtr”;“名称”
10000000;29;“xyz公司”

不要对不知道位于正确位置的分隔符使用拆分。使用正则表达式将所有分隔符匹配到一个数组中。要这样做吗?正则表达式非常不幸,并且由于该前瞻中嵌套了大量量词而导致速度减慢。为了提高效率,您应该使用一些成熟的CSV解析器。请注意,如果您的正则表达式有一点
;(?=([^“]“[^“]”[^“]$)
您会注意到没有量词将该断言带到字符串的末尾。所以,它永远不会匹配任何东西。@christian-Küpers我遇到了类似的问题&转而使用OpenCSV。如果你搜索,网上有一些ColdFusion示例。我编写了一个UDF来将分隔文件转换为查询。(注意:如果引用的值在数据中有换行符,或者数据行的长度不一致,此解决方案也可以使用。)@christian-Küpers-您是否因为数据库导入实用程序不起作用而使用正则表达式?你提到这个过程很慢。如何将数据插入数据库?通常,批量插入比一次插入一条记录快得多。
<!--- Option 1: Fastest method but prone to error --->
<cfhttp url="http://www.sharecsv.com/dl/9096d32f98aa0ac671a1cca16fa43be8/SalesJan2009.csv" name="q">
<Cfdump var=#q#>

<!--- Option 2: Slower but more stable --->
<cfsavecontent variable="strCSV">"Kunde";"Vtr";"Name"<Cfloop from=1 to=100 index=i>
10000000;29;"xyz Company"</cfloop></cfsavecontent>


<cfdump var="#CSVToQuery(strCSV,";","""",true)#"/>  

<cffunction name="CSVToQuery" access="public" returntype="query" output="false" hint="Converts the given CSV string to a query.">
        <!--- Define arguments. --->
        <cfargument name="CSV" type="string" required="true" hint="This is the CSV string that will be manipulated."/>
        <cfargument name="Delimiter" type="string" required="false" default="," hint="This is the delimiter that will separate the fields within the CSV value."/>
        <cfargument name="Qualifier" type="string" required="false" default="""" hint="This is the qualifier that will wrap around fields that have special characters embeded." />
        <cfargument name="SetColumnName" type="boolean" required="false" default="true" hint="Set the column name based on the first row of the csv file" />

        <cfset var LOCAL = StructNew() />
        <cfset ARGUMENTS.Delimiter = Left( ARGUMENTS.Delimiter, 1 ) />

        <cfif Len( ARGUMENTS.Qualifier )>
            <cfset ARGUMENTS.Qualifier = Left( ARGUMENTS.Qualifier, 1 ) />
        </cfif>

        <cfset LOCAL.LineDelimiter = Chr( 10 ) />

        <cfset ARGUMENTS.CSV = ARGUMENTS.CSV.ReplaceAll("\r?\n",LOCAL.LineDelimiter) />
        <cfset LOCAL.Delimiters = ARGUMENTS.CSV.ReplaceAll("[^\#ARGUMENTS.Delimiter#\#LOCAL.LineDelimiter#]+","").ToCharArray() />

        <cfset ARGUMENTS.CSV = (" " & ARGUMENTS.CSV) />
        <cfset ARGUMENTS.CSV = ARGUMENTS.CSV.ReplaceAll("([\#ARGUMENTS.Delimiter#\#LOCAL.LineDelimiter#]{1})","$1 ") />
        <cfset LOCAL.Tokens = ARGUMENTS.CSV.Split("[\#ARGUMENTS.Delimiter#\#LOCAL.LineDelimiter#]{1}") />
        <cfset LOCAL.Rows = ArrayNew( 1 ) />
        <cfset ArrayAppend(LOCAL.Rows,ArrayNew( 1 )) />
        <cfset LOCAL.RowIndex = 1 />
        <cfset LOCAL.IsInValue = false />
        <cfloop index="LOCAL.TokenIndex" from="1" to="#ArrayLen( LOCAL.Tokens )#" step="1">
            <cfset LOCAL.FieldIndex = ArrayLen(LOCAL.Rows[ LOCAL.RowIndex ]) />
            <cfset LOCAL.Token = LOCAL.Tokens[ LOCAL.TokenIndex ].ReplaceFirst("^.{1}","") />
            <cfif Len( ARGUMENTS.Qualifier )>
                <cfif LOCAL.IsInValue>
                    <cfset LOCAL.Token = LOCAL.Token.ReplaceAll("\#ARGUMENTS.Qualifier#{2}","{QUALIFIER}") />
                    <cfset LOCAL.Rows[ LOCAL.RowIndex ][ LOCAL.FieldIndex ] = (LOCAL.Rows[ LOCAL.RowIndex ][ LOCAL.FieldIndex ] &LOCAL.Delimiters[ LOCAL.TokenIndex - 1 ] &LOCAL.Token) />
                    <cfif (Right( LOCAL.Token, 1 ) EQ ARGUMENTS.Qualifier)>
                        <cfset LOCAL.Rows[ LOCAL.RowIndex ][ LOCAL.FieldIndex ] = LOCAL.Rows[ LOCAL.RowIndex ][ LOCAL.FieldIndex ].ReplaceFirst( ".{1}$", "" ) />
                        <cfset LOCAL.IsInValue = false />
                    </cfif>
                <cfelse>
                    <cfif (Left( LOCAL.Token, 1 ) EQ ARGUMENTS.Qualifier)>
                        <cfset LOCAL.Token = LOCAL.Token.ReplaceFirst("^.{1}","") />
                        <cfset LOCAL.Token = LOCAL.Token.ReplaceAll("\#ARGUMENTS.Qualifier#{2}","{QUALIFIER}") />
                        <cfif (Right( LOCAL.Token, 1 ) EQ ARGUMENTS.Qualifier)>
                            <cfset ArrayAppend(LOCAL.Rows[ LOCAL.RowIndex ],LOCAL.Token.ReplaceFirst(".{1}$","")) />
                        <cfelse>
                            <cfset LOCAL.IsInValue = true />
                            <cfset ArrayAppend(LOCAL.Rows[ LOCAL.RowIndex ],LOCAL.Token) />
                        </cfif>
                    <cfelse>
                        <cfset ArrayAppend(LOCAL.Rows[ LOCAL.RowIndex ],LOCAL.Token) />
                    </cfif>
                </cfif>
                <cfset LOCAL.Rows[ LOCAL.RowIndex ][ ArrayLen( LOCAL.Rows[ LOCAL.RowIndex ] ) ] = Replace(LOCAL.Rows[ LOCAL.RowIndex ][ ArrayLen( LOCAL.Rows[ LOCAL.RowIndex ] ) ],"{QUALIFIER}",ARGUMENTS.Qualifier,"ALL") />
            <cfelse>
                <cfset ArrayAppend(LOCAL.Rows[ LOCAL.RowIndex ],LOCAL.Token) />
            </cfif>
            <cfif ((NOT LOCAL.IsInValue) AND (LOCAL.TokenIndex LT ArrayLen( LOCAL.Tokens )) AND (LOCAL.Delimiters[ LOCAL.TokenIndex ] EQ LOCAL.LineDelimiter))>
            <cfset ArrayAppend(
                LOCAL.Rows,
                ArrayNew( 1 )
                ) />
            <cfset LOCAL.RowIndex = (LOCAL.RowIndex + 1) />
        </cfif>
    </cfloop>

    <cfset LOCAL.MaxFieldCount = 0 />
    <cfset LOCAL.EmptyArray = ArrayNew( 1 ) />

    <cfloop index="LOCAL.RowIndex" from="1" to="#ArrayLen( LOCAL.Rows )#" step="1">
        <cfset LOCAL.MaxFieldCount = Max(LOCAL.MaxFieldCount,ArrayLen(LOCAL.Rows[ LOCAL.RowIndex ])) />
        <cfset ArrayAppend(LOCAL.EmptyArray,"") />
    </cfloop>
    <cfset LOCAL.Query = QueryNew( "" ) />
    <cfloop index="LOCAL.FieldIndex" from="1" to="#LOCAL.MaxFieldCount#" step="1">
        <cfset QueryAddColumn(LOCAL.Query,"COLUMN_#LOCAL.FieldIndex#","CF_SQL_VARCHAR",LOCAL.EmptyArray) />
    </cfloop>

    <cfloop index="LOCAL.RowIndex" from="1" to="#ArrayLen( LOCAL.Rows )#" step="1">
        <cfloop index="LOCAL.FieldIndex" from="1" to="#ArrayLen( LOCAL.Rows[ LOCAL.RowIndex ] )#" step="1">
            <cfset LOCAL.Query[ "COLUMN_#LOCAL.FieldIndex#" ][ LOCAL.RowIndex ] = JavaCast("string",LOCAL.Rows[ LOCAL.RowIndex ][ LOCAL.FieldIndex ]) />
        </cfloop>
    </cfloop>

    <Cfif SetColumnName>
        <cfloop query="LOCAL.Query" startrow="1" endrow="1" >
            <cfloop list="#LOCAL.Query.columnlist#" index="LOCAL.col_name">
                <cfset local.field = LOCAL.Query[col_name]>
                <cfset QueryChangeColumnName(LOCAL.Query,col_name,field) >
            </cfloop>
        </cfloop>

        <cfset LOCAL.Query.RemoveRows( JavaCast( "int", 0 ), JavaCast( "int", 1 ) ) />
    </cfif>

    <cfreturn LOCAL.Query />
</cffunction>


<cffunction name="QueryChangeColumnName" access="public" output="false" returntype="query" hint="Uses java to rename a given query object column">
      <cfargument name="queryObj" required="true" type="query">
      <cfargument name="oldColName" required="true" type="string">
      <cfargument name="newColName" required="true" type="string">

      <cfset var colNameArray = queryObj.getColumnNames()>
      <cfset var i = 0>

      <cfif arrayLen(colNameArray)>
            <cfloop from="1" to="#arrayLen(colNameArray)#" index="i">
                  <cfif compareNoCase(colNameArray[i],arguments.oldColName) EQ 0>
                        <cfset colNameArray[i] = arguments.newColName>
                  </cfif>
            </cfloop>
      </cfif>

      <cfset queryObj.setColumnNames(colNameArray)>

      <cfreturn queryObj />
</cffunction>