2016-08-29 38 views
0

データが正しいはずです。私はデータを支配しておらず、私の上司は誰かの間違いに対処する方法を理解する必要があると私に教えてくれるだけです。ですから、データが悪いということは私の問題ではないということを教えてください。不正なcsvデータを解析する方法を教えてください。

"Words","[email protected]","","4253","57574","FirstName","","LastName, MD","","","576JFJD","","1971","","Words","Address","SUITE "A"","City","State","Zip","Phone","","" 

データは機密保持の理由でスクラブされています:

とにかく、これは私が探しているものです。

このように、データには引用符が含まれており、引用符付きのフィールドにはカンマが含まれています。だから私はそれらを削除することはできません。しかし、 "スイートA" "はパーサを投げ捨てています。引用符が多すぎます。 >。

  parser.HasFieldsEnclosedInQuotes = true; 
      parser.SetDelimiters(","); 
      parser.TextFieldType = FieldType.Delimited; 

エラーが

MalformedLineException: Line 9871 cannot be parsed using the current delimiters.

私はアカウントに何らかの形でデータをスクラブしたいです。私はこれらの設定でMicrosoft.VisualBasic.FileIO名前空間のTextFieldParserを使用してい<

これはどうしたらいいのか分かりません。あるいは、この行をスキップする方法がありますか?私の上層部は、必要と思われるデータをスキップするだけで私を承認するとは思えませんが。

+0

問題引用符をエスケープしようとしましたか? – itsme86

+0

@ itsme86はどのようにエスケープしていますか? –

+2

不正な行をスキップし、定期的に手動で修正して再実行するファイルにそれらを記録してください。うまくいけば、それは退屈になるほど多くの悪い行がないでしょう。 – Kevin

答えて

2

あなただけしようとしている場合

:あなたのcsvファイルに浮遊 "マークを取り除くために、あなたはそれらを見つけると '

String sourcestring = "source string to match with pattern"; 
String matchpattern = @"(?<!^|,)""(?!(,|$))"; 
String replacementpattern = @"$1'"; 
Console.WriteLine(Regex.Replace(sourcestring,matchpattern,replacementpattern,RegexOptions.Multiline)); 

説明とそれらを交換するには、次の正規表現を使用することができます0

@"(?<!^|,)""(?!(,|$))";は、文字列の先頭に先行されていない任意の"、または,を見つけるでしょうし、それは私がかつてaswellこれをしなければならなかった文字列の末尾または,

+0

ありがとう、これは私が必要としていたものです。 –

1

私は、最初のステップは、次のステップは一緒に属しているセグメントを組み合わせることであるstring.split(',')

を使用してデータを解析することで、前にこれを行うには

を持っていました。私は基本的にやった

  • は、文字列は引用符で始まる場合
  • 組み合わせた文字列を表す新しいリストを作ることが始まらない場合は、新しいリスト
  • にプッシュしました引用符、リスト内の最後の文字列に
  • ボーナスを、それを追加します。文字列は引用符で終わるが、次のいずれかが引用
で始まらないときに例外を投げます

データに実際に現れるものに関するルールが何であるかに応じて、そのためにコードを変更する必要があります。

1

CSV's file formatのコアでは、各行は行であり、その行の各セルはコンマで区切られています。あなたの場合、あなたの書式には、引用符の中のコンマが区切り文字としてカウントされず、代わりにデータの一部であるという(非常に不幸な)規定も含まれています。間違った引用符が行の残りの部分に影響し、標準ASCIIの引用符ではオープンとクローズを区別しないので、元の意図を知らなくてもこれを回復するために何もできません。

あなたは人はが、本来の意図(データを提供した人は)ファイルを見て、エラーを修正することができます知っていないような方法でメッセージログインしたときです:

if (parse_line(line, &data)) { 
    // save the data 
} else { 
    // log the error 
    fprintf(&stderr, "Bad line: %s", line); 
} 

を引用符はエスケープ改行ではないので、このエラーが発生した後に次の行に進むことができます。

追加:あなたの会社に選択肢がある場合(つまり、あなたのデータが社内ツールでシリアル化されている場合)、CSVは使用しないでください。はるかに明確に定義された解析メカニズムを持つXMLやJSONのようなものを使用してください。

2

私はTextFieldParserに精通していません。しかしCsvHelperと、無効なデータのためにカスタムハンドラを追加することができます。

var config = new CsvConfiguration(); 
config.IgnoreReadingExceptions = true; 
config.ReadingExceptionCallback += (e, row) => 
{ 
    // you can add some custom patching here if possible 
    // or, save the line numbers and add/edit them manually later. 
}; 

using(var file = File.OpenRead(".csv")) 
using(var reader = new CsvReader(reader, config)) 
{ 
    reader.GetRecords<YourDtoClass>(); 
} 
1

(私たちはすべてがあったので)誰もが言っていることに私の唯一のほかは、あなたが遭遇するそれぞれの新しい問題を是正しようとしようとすることですコード付き。適切なREGEX文字列がある場合はhttps://www.google.com/?ion=1&espv=2#q=c-sharp+regex+csv+cleanか、String.Replace(String.Replace( "\" \ "\" "、" ")を使用して手動で修正できます。 ( "\" ,, "、" \ "、")など)。最終的に、間違いを検出して訂正する方法を見つけると、手動復旧率が大幅に低下します(ほとんどの悪いデータは、同様の過ちからくる可能性が高い)。乾杯!

PS - アイデアっぽい(それはしばらくしている - 私はメモリから書いているようロジックは、いくつかの調整をneeed場合があります)がありますが、要点を取得します:

public string[] parseCSVWithQuotes(string csvLine,int expectedNumberOfDataPoints) 
    { 
     string ret = ""; 
     string thisChar = ""; 
     string lastChar = ""; 
     bool needleDown = true; 
     for(int i = 0; i < csvLine.Length; i++) 
     { 
      thisChar = csvLine.Substring(i, 1); 
      if (thisChar == "'"&&lastChar!="'") 
       needleDown = needleDown == true ? false : true;//when needleDown = true, characters are treated literally 
      if (thisChar == ","&&lastChar!=",") { 
       if (needleDown) 
       { 
        ret += "|";//convert literal comma to pipe so it doesn't cause another break on split 
       }else 
       { 
        ret += ",";//break on split is intended because the comma is outside the single quote 
       } 
      } 
      if (!needleDown && (thisChar == "\"" || thisChar == "*")) {//repeat for any undesired character or use RegEx 
                     //do not add -- this eliminates any undesired characters outside single quotes 
      } 
      else 
      { 
       if ((lastChar == "'" || lastChar == "\"" || lastChar == ",") && thisChar == lastChar) 
       { 
        //do not add - this eliminates double characters 
       }else 
       { 
        ret += thisChar; 
        lastChar = thisChar; 
        //this character is not an undesired character, is no a double, is valid. 
       } 
      } 
     } 
     //we've cleaned as best we can 
     string[] parts = ret.Split(','); 
     if(parts.Length==expectedNumberOfDataPoints){ 
     for(int i = 0; i < parts.Length; i++) 
     { 
      //go back and replace the temporary pipe with the literal comma AFTER split 
      parts[i] = parts[i].Replace("|", ","); 
     } 

     return parts; 
     }else{ 
      //save ret to bad CSV log 
      return null; 
     } 
    } 
+0

CSV解析を処理するためにどのように使用したかのサンプルを(メモリから呼び出すことができる限り)追加しました。それは一度に文字を通過するのでちょっと吸うが、あなたは良いRegExer場合は、おそらくもっと良いことを達成することができます。それはかなりではないかもしれないが、それ(またはそれのようなもの)は私のために働いた。がんばろう! –

0

が続いていません。私のアプローチは、私が読んでいたものを追跡して追跡することでした。 基本的には、入力回線からトークンを切り落とす私自身のスキャナをコード化していました。私の欠陥のある.csvデータを完全に制御することができました。

これは私がやったことです:

For each character on a line of input. 
1. when outside of a string meeting a comma => all of the previous string (which can be empty) is a valid token. 
2. when outside of a sting meeting anything but a comma or a quote => now you have a real problem, unquoted tekst => handle as you see fit. 
3. when outside of a string meeing a quote => found a start of string. 
4. when inside of a string meeting a comma => accept the comma as part of the string. 
5. when inside of the string meeting a qoute => trouble starts here, mark this point. 
    6. continue and when meeting a comma (skipping white space if desired) close the string, 'unread' the comma and continue. (than will bring you to point 1.) 
    7. or continue and when meeting a quote -> obviously, what was read must be part of the string, add it to the string, 'unread' the quote and continue. (that will you bring to point 5) 
    8. or continue and find an whitespace, then End Of Line ('\n') -> the last qoute must be the closing quote. accept the string as a value. 
    9. or continue and fine non-whitespace, then End Of Line. -> now you have a real problem, you have the start of a string but it is not closed -> handle the error as you see fit. 

.csvファイル内のフィールドの数が固定されている場合は、あなたがフィールドseperatorsとして認識し、あなたが行の最後を見たとき、あなたはあなたを知っているカンマの数をカウントすることができます別の問題があるかどうか。

入力行から受け取った文字列のストリームで、「クリーン」.csv行を作成することができます。この方法で、既存のコードで使用できる受け入れられ、消去された入力のバッファを構築できます。

関連する問題