2009-03-23 2 views
0
Dim re As New Regex("((?<field>[^"",\r\n]+)|""(?<field>([^""]|"""")+)"")((?<rowbreak>,\r\n|\r\n|\n|$)|,)") 


3700,Collin,Franc,,[email protected],Collins,Francine,,[email protected],"Enel North America, Inc.",One T Drive,Suite 220,MyCity,MA,77774,1,[email protected],,,,,3700, 
3701,Steur,Larry,,[email protected],Steur,Larry,,[email protected],"St. Petersburg Corp, Inc.",10490 Gady Blvd,,MyCity,FL,33772,1,[email protected],,,,,3701 
3705,Giger,Tina,CFO,[email protected],Giger,Tina,CFO,[email protected],Net Technologies,23 Calab Rd,Suite 202,Calabas,CA,77777,1,[email protected],,,,,3705, 

내가 사용하는 RegEx는 비어있는 열이있는 경우 다음 열을 그 위치로 "슬라이드"한다는 점에서 작동하지 않습니다. 다음과 같이하면 각 행에 5 개의 열이 생기도록 허용하려면 어떻게해야합니까?정규 표현식에 빈 값이 누락 되었습니까?

<%@ Page Language="VB" MasterPageFile="~/_Common/MasterPage.master" %> 

<%@ Import Namespace="System.Data" %> 
<%@ Import Namespace="System.IO" %> 
<%@ Import Namespace="System.Text.RegularExpressions" %> 
<%@ Import Namespace="System.Xml" %> 

<script runat="server"> 

    Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) 
    
     ' call the parser 
     Dim dt As DataTable = ParseCSVFile(Server.MapPath("Documents/Test.csv")) 
    
     ' bind the resulting DataTable to a DataGrid Web Control 
     GridView1.DataSource = dt 
     GridView1.DataBind() 
    End Sub 

    Public Function ParseCSV(ByVal inputString As String) As DataTable 
    
     Dim dt As New DataTable() 
    
     ' declare the Regular Expression that will match versus the input string 
     Dim re As New Regex("((?<field>[^"",\r\n]+)|""(?<field>([^""]|"""")+)"")((?<rowbreak>,\r\n|\r\n|\n|$)|,)") 
    
     Dim colArray As New ArrayList() 
     Dim rowArray As New ArrayList() 
    
     Dim colCount As Integer = 0 
     Dim maxColCount As Integer = 0 
     Dim rowbreak As String = "" 
     Dim field As String = "" 
    
     Dim mc As MatchCollection = re.Matches(inputString) 
    
     For Each m As Match In mc 
        
      ' retrieve the field and replace two double-quotes with a single double-quote 
      field = m.Result("${field}").Replace("""""", """") 
        
      rowbreak = m.Result("${rowbreak}") 
        
      If field.Length > 0 Then 
       colArray.Add(field) 
       colCount += 1 
      End If 
        
      If rowbreak.Length > 0 Then 
            
       ' add the column array to the row Array List 
       rowArray.Add(colArray.ToArray()) 
            
       ' create a new Array List to hold the field values 
       colArray = New ArrayList() 
            
       If colCount > maxColCount Then 
        maxColCount = colCount 
       End If 
            
       colCount = 0 
      End If 
     Next 
    
     If rowbreak.Length = 0 Then 
      ' this is executed when the last line doesn't 
      ' end with a line break 
      rowArray.Add(colArray.ToArray()) 
      If colCount > maxColCount Then 
       maxColCount = colCount 
      End If 
     End If 
    
     ' create the columns for the table 
     For i As Integer = 0 To maxColCount - 1 
      dt.Columns.Add([String].Format("col{0:000}", i)) 
     Next 
    
     ' convert the row Array List into an Array object for easier access 
     Dim ra As Array = rowArray.ToArray() 
     For i As Integer = 0 To ra.Length - 1 
        
      ' create a new DataRow 
      Dim dr As DataRow = dt.NewRow() 
        
      ' convert the column Array List into an Array object for easier access 
      Dim ca As Array = DirectCast((ra.GetValue(i)), Array) 
        
      ' add each field into the new DataRow 
      For j As Integer = 0 To ca.Length - 1 
       dr(j) = ca.GetValue(j) 
      Next 
        
      ' add the new DataRow to the DataTable 
      dt.Rows.Add(dr) 
     Next 
    
     ' in case no data was parsed, create a single column 
     If dt.Columns.Count = 0 Then 
      dt.Columns.Add("NoData") 
     End If 
    
     Return dt 
    End Function 

    Public Function ParseCSVFile(ByVal path As String) As DataTable 
    
     Dim inputString As String = "" 
    
     ' check that the file exists before opening it 
     If File.Exists(path) Then 
        
      Dim sr As New StreamReader(path) 
      inputString = sr.ReadToEnd() 
      sr.Close() 
        
     End If 
    
     Return ParseCSV(inputString) 
    End Function 

</script> 


<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server"> 

</asp:Content> 

<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server"> 
    <asp:FileUpload ID="FileUpload1" runat="server" /> 
    <asp:Button ID="btnUpload" runat="server" Text="Upload" /> 
    <asp:GridView ID="GridView1" runat="server"> 
    </asp:GridView> 
</asp:Content> 

실제로 Linq에 함께이 일을 선호하지만 난에 쉼표를 포함 값 (값을 인용 한 CSV 파일을 사용하는 예제를 찾을 수 없습니다 :

1,2,3,4,5 
Test,,,Test, 
Test,,Test,, 

여기 내 전체 코드입니다 가치 그 자체).

**

** UPDATE 나는이에 정규식을 변경하고 가까이 저를 점점 :

Dim re As New Regex("(?<field>,)|((?<field>[^"",\r\n]+)|""(?<field>([^""]|"""")+)"")(,|(?<rowbreak>\r\n|\n|$))") 

지금 올바른 컬럼의 모든 데이터를두고 있지만 단지 쉼표있다 빈 열

+0

. 바퀴를 재발 명하지 마십시오. "LINQ to CSV"또는 비슷한 것을 검색하십시오. – MarcinJuraszek

답변

1

왜 정규 표현식을 사용합니까? 꽤 간단한 구문 분석 작업이 있습니다. 따옴표 안에 있지 않으면 쉼표를 구분 기호로 사용하십시오. 따라서 문자별로 각 라인 문자를 반복하고 반대 인용을 칠 때 플래그를 설정하고 끝 인용을 칠 때 플래그를 설정 해제 할 수 있습니다. "내부 따옴표"는 쉼표를 무시합니다. (I이 사용하는 정규 표현식을하려고 포기)이 시도 :

private DataTable GetDataTableFromCsv(string csvContent) 
    { 
     DataTable dt = new DataTable(); 
     string all = csvContent; 
     string[] lines = all.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); 
     foreach (String s in lines) 
     { 
      bool isInsideQuote = false; 
      List<string> values = new List<string>(); 
      string accumulator = ""; 
      for (int j = 0; j < s.Length; j++)// (char c in s) 
      { 
       char c = s[j]; 
       if (c == '"') 
       { 
        if (!isInsideQuote) 
        { 
         isInsideQuote = true; 
        } 
        else 
        { 
         isInsideQuote = false; 
        } 
        accumulator += "\""; 
       } 
       else if (c == ',' && !isInsideQuote) 
       { 
        values.Add(accumulator); 
        accumulator = ""; //reset 
       } 
       else if (j == s.Length - 1) 
       { 
        accumulator += c; 
        values.Add(accumulator); 
        accumulator = ""; 
       } 
       else 
       { 
        accumulator += c; 
       } 
      } 
      //first time, create relevant columns 
      if (dt.Columns.Count == 0) 
      { 
       foreach (string colExample in values) 
       { 
        dt.Columns.Add(); 
       } 
       //list of strings now contains an example. 
      } 
      DataRow dr = dt.NewRow(); 
      for (int i = 0; i < values.Count; i++) 
      { 
       dr[i] = values[i]; 
      } 
      dt.Rows.Add(dr); 
     } 
     return dt; 
    } 
0

이 같은 것을보십시오 : CSV 파일을 다루는 .NET 라이브러리의 무리입니다 "(?<field1>.*),(?<field2>.*),(?<field3>.*),(?<field4>.*),(?<field5>.*)"

관련 문제