1

Cuong がここで提案したソリューションを実装しました: C# 固定幅ファイルの処理

また、フォルダーを通過させ、そのフォルダー内のすべての .txt ファイルに適用しました。

すべて正常に動作しますが、一部の .txt ファイルでは、var csvLines で次のエラーが発生して失敗します。

{"Index and length must refer to a location within the string.\r\nParameter name: length"}

A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll
System.ArgumentOutOfRangeException: Index and length must refer to a location within the string.
Parameter name: length
   at System.String.InternalSubStringWithChecks(Int32 startIndex, Int32 length, Boolean fAlwaysCopy)
   at System.String.Substring(Int32 startIndex, Int32 length)
   at FixedWidthFiles.Main.<>c__DisplayClass11.<>c__DisplayClass13.<buttonProcessAllFiles_Click>b__d(KeyValuePair`2 pair) in \\GBMACCMPFS11\Shhk$\Visual Studio 2010\Projects\FixedWidthFiles\FixedWidthFiles\Main.cs:line 138
   at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
   at System.String.Join(String separator, IEnumerable`1 values)
   at FixedWidthFiles.Main.<>c__DisplayClass11.<buttonProcessAllFiles_Click>b__c(String line) in \\GBMACCMPFS11\Shhk$\Visual Studio 2010\Projects\FixedWidthFiles\FixedWidthFiles\Main.cs:line 137
   at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
   at System.IO.File.InternalWriteAllLines(TextWriter writer, IEnumerable`1 contents)
   at System.IO.File.WriteAllLines(String path, IEnumerable`1 contents)
   at FixedWidthFiles.Main.buttonProcessAllFiles_Click(Object sender, EventArgs e) in \\GBMACCMPFS11\Shhk$\Visual Studio 2010\Projects\FixedWidthFiles\FixedWidthFiles\Main.cs:line 140

何が間違っているのですか?それはファイルかもしれませんが、コードで何かを修正/改善できることを願っています:)


コードはこれです:

private void buttonProcessAllFiles_Click(object sender, EventArgs e)
{
    if (fileFolderPath == "")
    {
        MessageBox.Show("Load Folder First", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

    }
    else
    {
        int count = 0;
        //foreach (var file in Directory.GetFiles(fileFolderPath, "*.txt", SearchOption.AllDirectories))
        foreach (var file in Directory.GetFiles(fileFolderPath, "*.txt"))
        {
            count++;
            System.Diagnostics.Debug.WriteLine(count);
            fileFolderFull = Path.GetFullPath(file);
            System.Diagnostics.Debug.WriteLine(fileFolderFull);
            fileFolderName = Path.GetFileNameWithoutExtension(file);
            System.Diagnostics.Debug.WriteLine(fileFolderName);

            //MessageBox.Show("Full Folder: " + fileFolderFull);
            //MessageBox.Show("File Name: " + fileFolderName);

            var lines = File.ReadAllLines(fileFolderFull);

            var widthList = lines.First().GroupBy(c => c)
                                         .Select(g => g.Count())
                                         .ToList();

            var list = new List<KeyValuePair<int, int>>();

            int startIndex = 0;

            for (int i = 0; i < widthList.Count(); i++)
            {
                var pair = new KeyValuePair<int, int>(startIndex, widthList[i]);
                list.Add(pair);

                startIndex += widthList[i];
            }

            try
            {
                var csvLines = lines.Select(line => string.Join(",",
                                    list.Select(pair => line.Substring(pair.Key, pair.Value))));

                File.WriteAllLines(fileFolderPath + "\\" + fileFolderName + ".csv", csvLines);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex);
            } 
        }

        MessageBox.Show("File Saved", "Completed", MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
}

エラーがこれである行:

var csvLines = lines.Select(line => string.Join(",",
                                        list.Select(pair => line.Substring(pair.Key, pair.Value))));
4

2 に答える 2

3

スタック トレースを読み取ります。最初の興味深い場所は次のとおりです。

Visual Studio 2010\Projects\FixedWidthFiles\FixedWidthFiles\Main.cs:line 138

これは、コードを含むファイルです。そして例外は、文字列サイズよりも大きいインデックスから文字列を読み取っていることです。これはすべて、コードのバグを示しています。そのファイルに移動し、その行を分析します。それについて考えて、その場所でインデックスが範囲外になる理由がわからない場合は、そのコードといくつかのコードをコピーして、ここに投稿してください。そのスタックトレースだけでこれ以上何かを伝えるのは難しい..

編集: コードを追加しました。

部分文字列では間違いなく失敗するため、部分文字列がインデックスとして取るものを確認してください。それはペアからの値です。値は列幅の増分合計から得られるため、ほとんどの場合、入力ファイルの 1 つに短すぎる行が含まれている可能性があります。ファイルの最初または最後に偽の空行がないかチェックしてください!

これらの行のファイルを削除するか、それに対してコードを修正する必要があります: substring をやみくもに呼び出す代わりに、if または Math.min で保護します。

str.Substring(
    Math.Min(str.Length, pair.Key), // here it MAY be needed a str.Length-1 instead!
    Math.Min(Math.Max(0,str.Length-pair.Key), pair.Value)
)

このように、短すぎるすべての行に対して、フィールドカッターは空の文字列を返します。両方のパラメーターを保護することは良いことであり、また、Length-StartIndex をネガティブに対してチェックする価値があることに注意してください。StartIndex は、空の行の長さよりも大きくなる可能性があるためです:)

ところで。StartIndex とはもちろん、pair.Key.. のことです。

于 2012-10-02T22:27:42.830 に答える
1

Substringメソッドでは失敗していると思います。line.Length>(pair.Key + pair.Value)のチェックを追加できますか?

于 2012-10-02T22:30:57.793 に答える