1

.csv ファイルがあり (データを制御できません)、何らかの理由ですべてが引用符で囲まれています。

"Date","Description","Original Description","Amount","Type","Category","Name","Labels","Notes"
"2/02/2012","ac","ac","515.00","a","b","","javascript://"
"2/02/2012","test","test","40.00","a","d","c",""," "

私はファイルヘルパーを使用していますが、これらの引用符をすべて削除する最善の方法は何でしょうか? 「引用符が削除された場合。引用符が見つからない場合は何もしない」というものはありますか?

不要な余分な引用符があるため、これはデータを台無しにし"\"515.00\""ます(特に、この場合は文字列ではなく10進数にしたいので).

また、「javascript」が何であるか、なぜ生成されたのかはわかりませんが、これは私が制御できないサービスからのものです。

編集 これは私がcsvファイルを消費する方法です。

    using (TextReader textReader = new StreamReader(stream))
        {
            engine.ErrorManager.ErrorMode = ErrorMode.SaveAndContinue; 

            object[] transactions = engine.ReadStream(textReader);
        }
4

4 に答える 4

9

こちらFieldQuotedの属性ページで最もよく説明されている属性を使用できます。この属性は、任意の FileHelpers フィールドに適用できることに注意してください (タイプが であっても)。(FileHelpers クラスはインポート ファイルの仕様を記述していることを思い出してください。そのため、フィールドを としてマークすると、ファイル内で、このフィールドは引用符で囲まれます。 )DecimalDecimalFieldQuoted

引用符がオプションかどうかを指定することもできます

[FieldQuoted('"', QuoteMode.OptionalForBoth)] 

以下は、データを操作するコンソール アプリケーションです。

class Program
{
    [DelimitedRecord(",")]
    [IgnoreFirst(1)]
    public class Format1
    {
        [FieldQuoted]
        [FieldConverter(ConverterKind.Date, "d/M/yyyy")]
        public DateTime Date;
        [FieldQuoted]
        public string Description;
        [FieldQuoted]
        public string OriginalDescription;
        [FieldQuoted]
        public Decimal Amount;
        [FieldQuoted]
        public string Type;
        [FieldQuoted]
        public string Category;
        [FieldQuoted]
        public string Name;
        [FieldQuoted]
        public string Labels;
        [FieldQuoted]
        [FieldOptional]
        public string Notes;
    }

    static void Main(string[] args)
    {
        var engine = new FileHelperEngine(typeof(Format1));

        // read in the data   
        object[] importedObjects = engine.ReadString(@"""Date"",""Description"",""Original Description"",""Amount"",""Type"",""Category"",""Name"",""Labels"",""Notes""
""2/02/2012"",""ac"",""ac"",""515.00"",""a"",""b"","""",""javascript://""
""2/02/2012"",""test"",""test"",""40.00"",""a"",""d"",""c"","""","" """);

        // check that 2 records were imported
        Assert.AreEqual(2, importedObjects.Length);

        // check the values for the first record
        Format1 customer1 = (Format1)importedObjects[0];
        Assert.AreEqual(DateTime.Parse("2/02/2012"), customer1.Date);
        Assert.AreEqual("ac", customer1.Description);
        Assert.AreEqual("ac", customer1.OriginalDescription);
        Assert.AreEqual(515.00, customer1.Amount);
        Assert.AreEqual("a", customer1.Type);
        Assert.AreEqual("b", customer1.Category);
        Assert.AreEqual("", customer1.Name);
        Assert.AreEqual("javascript://", customer1.Labels);
        Assert.AreEqual("", customer1.Notes);

        // check the values for the second record
        Format1 customer2 = (Format1)importedObjects[1];
        Assert.AreEqual(DateTime.Parse("2/02/2012"), customer2.Date);
        Assert.AreEqual("test", customer2.Description);
        Assert.AreEqual("test", customer2.OriginalDescription);
        Assert.AreEqual(40.00, customer2.Amount);
        Assert.AreEqual("a", customer2.Type);
        Assert.AreEqual("d", customer2.Category);
        Assert.AreEqual("c", customer2.Name);
        Assert.AreEqual("", customer2.Labels);
        Assert.AreEqual(" ", customer2.Notes);
    }
}

Notes(注: データの最初の行には 9 つではなく 8 つのフィールドがあるように見えるので、フィールドを でマークしましたFieldOptional)。

于 2012-02-06T11:12:06.710 に答える
0

これを行う1つの方法は次のとおりです。

string[] lines = new string[]
{
    "\"Date\",\"Description\",\"Original Description\",\"Amount\",\"Type\",\"Category\",\"Name\",\"Labels\",\"Notes\"",
    "\"2/02/2012\",\"ac\",\"ac\",\"515.00\",\"a\",\"b\",\"\",\"javascript://\"",
    "\"2/02/2012\",\"test\",\"test\",\"40.00\",\"a\",\"d\",\"c\",\"\",\" \"",
};

string[][] values =
    lines.Select(line =>
        line.Trim('"')
            .Split(new string[] { "\",\"" }, StringSplitOptions.None)
            .ToArray()
        ).ToArray();

lines配列は、サンプルの行を表します。各文字は、C# 文字列リテラルの"ようにエスケープする必要があります。\"

各行について、最初と最後の文字を削除することから始め、文字シーケンスを区切り文字として"使用して部分文字列のコレクションに分割します。","

上記のコードは、値内に自然に発生する文字がある場合 (エスケープされている場合でも)機能しないことに注意してください。"

編集: CSV をストリームから読み取る場合は、次のことを行う必要があります。

var lines = new List<string>();
using (var streamReader = new StreamReader(stream))
    while (!streamReader.EndOfStream)
        lines.Add(streamReader.ReadLine());

上記のコードの残りの部分はそのまま機能します。

編集:新しいコードを指定して、次のようなものを探しているかどうかを確認します。

for (int i = 0; i < transactions.Length; ++i)
{
    object oTrans = transactions[i]; 
    string sTrans = oTrans as string;
    if (sTrans != null && 
        sTrans.StartsWith("\"") &&
        sTrans.EndsWith("\""))
    {
        transactions[i] = sTrans.Substring(1, sTrans.Length - 2);
    }
}
于 2012-02-03T19:09:07.773 に答える
0

私は同じ苦境にあり、値をリスト オブジェクトにロードするときに引用符を置き換えます。

using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;

namespace WindowsFormsApplication6
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            LoadCSV();
        }

        private void LoadCSV()
        {
            List<string> Rows = new List<string>();
            string m_CSVFilePath = "<Path to CSV File>";

            using (StreamReader r = new StreamReader(m_CSVFilePath))
            {
                string row;

                while ((row = r.ReadLine()) != null)
                {
                    Rows.Add(row.Replace("\"", ""));
                }

                foreach (var Row in Rows)
                {
                    if (Row.Length > 0)
                    {
                        string[] RowValue = Row.Split(',');

                        //Do something with values here
                    }
                }
            }
        }

    }
}
于 2012-02-03T20:23:26.563 に答える