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