Проанализировать текстовый файл и удалить запятые внутри двойных кавычек

У меня есть текстовый файл, который нужно преобразовать в файл csv. Мой план:

  • проанализировать файл строки за строкой
  • искать и заменять запятые внутри двойных кавычек пробелом
  • затем удалите все двойные кавычки
  • добавьте строку в новый файл csv

Вопрос: Мне нужна функция, которая распознает запятую внутри двойной кавычки и заменяет ее.

Вот пример строки:

"MRS Brown", "4611 BEAUMONT ST", "," WARRIOR RUN, PA"

Ответ 1

Ваш файл, похоже, уже находится в формате жалобы CSV. Любой хороший читатель CSV мог бы правильно его прочитать.

Если ваша проблема просто правильно считывает значения полей, вам необходимо прочитать ее правильно.

Вот один из способов сделать это:

using Microsoft.VisualBasic.FileIO; 


    private void button1_Click(object sender, EventArgs e)
    {
        TextFieldParser tfp = new TextFieldParser("C:\\Temp\\Test.csv");
        tfp.Delimiters = new string[] { "," };
        tfp.HasFieldsEnclosedInQuotes = true;
        while (!tfp.EndOfData)
        {
            string[] fields = tfp.ReadFields();

            // do whatever you want to do with the fields now...
            // e.g. remove the commas and double-quotes from the fields.
            for (int i = 0; i < fields.Length;i++ )
            {
                fields[i] = fields[i].Replace(","," ").Replace("\"","");
            }

            // this is to show what we got as the output
            textBox1.AppendText(String.Join("\t", fields) + "\n");
        }
        tfp.Close();
    }

EDIT:

Я только заметил, что вопрос был подан в С#, VB.NET-2010. Вот версия VB.NET, на всякий случай, если вы кодируете в VB.

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim tfp As New FileIO.TextFieldParser("C:\Temp\Test.csv")
    tfp.Delimiters = New String() {","}
    tfp.HasFieldsEnclosedInQuotes = True
    While Not tfp.EndOfData
        Dim fields() As String = tfp.ReadFields

        '' do whatever you want to do with the fields now...
        '' e.g. remove the commas and double-quotes from the fields.
        For i As Integer = 0 To fields.Length - 1
            fields(i) = fields(i).Replace(",", " ").Replace("""", "")
        Next
        '' this is to show what we got as the output
        TextBox1.AppendText(Join(fields, vbTab) & vbCrLf)
    End While
    tfp.Close()
End Sub

Ответ 2

Здесь простая функция, которая удаляет запятые, вложенные между двумя двойными кавычками в строке. Вы можете передать длинную строку с несколькими вхождениями "abc, 123", 10/13/12, "некоторое описание"... и т.д. Он также удалит двойные кавычки.

Private Function ParseCommasInQuotes(ByVal arg As String) As String

    Dim foundEndQuote As Boolean = False
    Dim foundStartQuote As Boolean = False
    Dim output As New StringBuilder()

    '44 = comma
    '34 = double quote

    For Each element As Char In arg

        If foundEndQuote Then
            foundStartQuote = False
            foundEndQuote = False
        End If

        If element.Equals(Chr(34)) And (Not foundEndQuote) And foundStartQuote Then
            foundEndQuote = True
            Continue For
        End If


        If element.Equals(Chr(34)) And Not foundStartQuote Then
            foundStartQuote = True
            Continue For
        End If


        If (element.Equals(Chr(44)) And foundStartQuote) Then
            'skip the comma...its between double quotes
        Else
            output.Append(element)
        End If

    Next

    Return output.ToString()

End Function

Ответ 3

Благодаря Baz, The Glockster Answer в VB, я просто преобразовал его в С# и его работы хорошо. С помощью этого кода вам не нужен сторонний парсер.

string line = reader.ReadLine();                    
line = ParseCommasInQuotes(line);

private string ParseCommasInQuotes(string arg)
{

  bool foundEndQuote = false;
  bool foundStartQuote = false;
  StringBuilder output = new StringBuilder();

  //44 = comma
  //34 = double quote

  foreach (char element in arg)
  {
    if (foundEndQuote)
    {
      foundStartQuote = false;
      foundEndQuote = false;
    }

    if (element.Equals((Char)34) & (!foundEndQuote) & foundStartQuote)
    {
      foundEndQuote = true;
      continue;
    }

    if (element.Equals((Char)34) & !foundStartQuote)
    {
      foundStartQuote = true;
      continue;
    }

    if ((element.Equals((Char)44) & foundStartQuote))
    {
      //skip the comma...its between double quotes
    }
    else
    {
      output.Append(element);
    }
  }
  return output.ToString();
}

Ответ 4

Не похоже, что то, что вы описываете, окажется в виде файла csv, но чтобы ответить на ваш вопрос, я бы это сделал.

Сначала вам нужно получить текстовый файл в какой-нибудь полезный код, который можно прокрутить так:

    public static List<String> GetTextListFromDiskFile(String fileName)
    {
        List<String> list = new List<String>();
        try
        {
            //load the file into the streamreader 
            System.IO.StreamReader sr = new System.IO.StreamReader(fileName);

            //loop through each line of the file
            while (sr.Peek() >= 0)
            {
                list.Add(sr.ReadLine());
            }
            sr.Close();
        }
        catch (Exception ex)
        {
            list.Add("Error: Could not read file from disk. Original error: " + ex.Message);
        }

        return list;
    }

Затем прокрутите список и используйте простой цикл foreach и запустите замену в списке следующим образом:

        foreach (String item in list)
        {
            String x = item.Replace("\",\"", "\" \"");
            x = x.Replace("\"", "");
        }

После этого вам нужно создать файл csv по строкам. Я бы снова использовал StringBuilder, а затем просто выполнил команду sb.AppendLine(x), чтобы создать String, который станет текстовым файлом, а затем записать его на диск, используя что-то вроде этого.

    public static void SaveFileToDisk(String filePathName, String fileText)
    {
        using (StreamWriter outfile = new StreamWriter(filePathName))
        {
            outfile.Write(fileText);
        }
    }

Ответ 5

Я раньше не понимал ваш вопрос. Теперь я уверен, что правильно понял:

TextFieldParser parser = new TextFieldParser(@"c:\file.csv");
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
while (!parser.EndOfData) 
{
    //Processing row
    string[] fields = parser.ReadFields();
    foreach (string field in fields) 
    {
        //TODO: Do whatever you need
    }
}
parser.Close();

Ответ 6

var result = Regex.Replace(input,
                           @"[^\""]([^\""])*[^\""]", 
                           m => m.Value.Replace(",", " ") );

Ответ 7

Это сработало для меня. Надеюсь, это поможет кому-то другому.

Private Sub Command1_Click()
Open "c:\\dir\file.csv" For Input As #1
Open "c:\\dir\file2.csv" For Output As #2
Do Until EOF(1)
Line Input #1, test$
99
c = InStr(test$, """""")
If c > 0 Then
test$ = Left$(test$, c - 1) + Right$(test$, Len(test$) - (c + 1))
GoTo 99
End If
Print #2, test$
Loop
End Sub