私は最近プログラミングの学習を開始し、Visual Studio Express で .NET を選択しました。学習経験として CSV パーサーを作成しようとしていますが、予想よりも多くの問題が発生しています。私は読者から始めています。パーサーで私が別の方法で行っていることの 1 つは、引用符を使用していないことです。コンマをバックスラッシュで、バックスラッシュをバックスラッシュで、改行をバックスラッシュでエスケープしています。たとえば、コンマの前に偶数のバックスラッシュがある場合、それはフィールドであり、バックスラッシュのブロックを半分にします。奇数の場合は、フィールドの終わりではなく、バックスラッシュのブロックを半分にします。これが機能するようになった場合、これがどれほど堅牢になるかはわかりませんが、私はこの時点で学習しているだけであり、主にデータ構造を操作する演習として見ています。
この投稿の最後にあるコード スニペットに関して質問があります。コード スニペットをそれほど静的で制限的なものにせず、コンパイルして実行する方法について質問があります。
次のコード行:
var contents = (String)fileContents;
柔軟性を高め、次のようにするために、より動的にすることを試み続けています。
var contents = (otherVariableThatCouldChangeTypeAtRuntime.GetType())fileContents;
これを実行してコンパイルするためにできることはありますか? たぶん、VB.NET の Option Infer のようなものが役立つかもしれませんが、それが見つからない場合を除きます。
また、これもVB.NETで書いています。VB.NET では、var を何度も入力する必要がなく、インデックス カウント変数を整数に何度もキャストし続ける必要がないなど、以下に投稿したものよりもかなり動的なスタイルを使用できるように思えます。 Option Strict と Option Explicit をオフにし、Option Infer をオンにすると、再び。たとえば、C# では、実行時に呼び出すメソッドとプロパティが実行時に存在することを知っていても、次の VB.NET コードに類似したものを入力できません。
Dim contents As Object = returnObjectICantDetermineAtComplieTime()
contents.MethodIKnowWillBeThereAtRunTime()
これらのことを C# で行うことはできますか? とにかく、ここにコードがあります。応答をお待ちしております。
public class Widget
{
public object ID { get; set; }
public object PartNumber { get; set; }
public object VendorID { get; set; }
public object TypeID { get; set; }
public object KeyMarkLoc { get; set; }
public Widget() { }
}
public object ReadFromFile(object source)
{
var fileContents = new FileService().GetFileContents(source);
object records = null;
if (fileContents == null)
return null;
var stringBuffer = "";
var contents = (String)fileContents;
while (contents.Length > 0 && contents != "\r\n")
{
for (object i = 0; (int)i < contents.Length; i=(int)i+1 )
{
object character = contents[(int)i];
if (!stringBuffer.EndsWith("\r\n"))
{
stringBuffer += character.ToString();
}
if (stringBuffer.EndsWith("\r\n"))
{
var bSlashes = getBackSlashes(stringBuffer.Substring(0, stringBuffer.Length - 4));
stringBuffer = stringBuffer.Substring(0, stringBuffer.Length - 4);
if ((int)bSlashes % 2 == 0)
{
break;
}
}
}
contents = contents.Substring(stringBuffer.Length+2);
records = records == null ? getIncrementedList(new List<object>(), getNextObject(getFields(stringBuffer))) : getIncrementedList((List<object>)records, getNextObject(getFields(stringBuffer)));
}
return records;
}
private Widget getNextRecord(object[] fields)
{
var personStudent = new Widget();
personStudent.ID = fields[0];
personStudent.PartNumber = fields[1];
personStudent.VendorID = fields[2];
personStudent.TypeID = fields[3];
personStudent.GridPath = fields[4];
return personStudent;
}
private object[] getFields(object buffer)
{
var fields = new object[5];
var intFieldCount = 0;
var fieldVal = "";
var blocks = buffer.ToString().Split(',');
foreach (var block in blocks)
{
var bSlashes = getBackSlashes(block);
var intRemoveCount = (int)bSlashes / 2;
if ((int)bSlashes % 2 == 0) // Delimiter
{
fieldVal += block.Substring(0, block.Length - intRemoveCount);
fields[intFieldCount] += fieldVal;
intFieldCount++;
fieldVal = "";
}
else // Part of Field
{
fieldVal += block.Substring(0, block.Length - intRemoveCount - 1) + ",";
}
}
return fields;
}
private object getBackSlashes(object block)
{
object bSlashes = block.ToString().Length == 0 ? new int?(0) : null;
for (object i = block.ToString().Length - 1; (int)i>-1; i=(int)i-1)
{
if (block.ToString()[(int)i] != '\\') return bSlashes = bSlashes == null ? 0 : bSlashes;
bSlashes = bSlashes == null ? 1 : (int)bSlashes + 1;
}
return bSlashes;
}
}
これがWebサービスコードです。
[WebMethod]
public object GetFileContents(object source)
{
return File.ReadAllText(source.ToString());
}