一点背景。我不熟悉在专业环境中使用C#。我的经验主要是在SQL中。我有一个文件,我需要解析,以提取某些信息。我可以弄清楚如何解析每一行,但却一直在寻找特定的信息。我对有人为我完成此代码不感兴趣。相反,我感兴趣的是关于我可以从这里走的地方。 以下是我编写的代码示例。
class Program
{
private static Dictionary<string, List<string>> _arrayLists = new Dictionary<string, List<string>>();
static void Main(string[] args)
{
string filePath = "c:\\test.txt";
StreamReader reader = new StreamReader(filePath);
string line;
while (null !=(line = reader.ReadLine()))
{
if (line.ToLower().Contains("disconnected"))
{
// needs to continue on search for Disconnected or Subscribed
}
else
{
if (line.ToLower().Contains("subscribed"))
{
// program needs to continue reading file
// looking for and assigning values to
// dvd, cls, jhd, dxv, hft
// records start at Subscribed and end at ;
}
}
}
}
}
对该文件的一点解释。我基本上需要提取订阅和第一个词之间存在的数据;我来了。具体来说,我需要获取诸如dvd = 234之类的值,并将它们分配给代码中的相同变量。并非每条记录都有相同的变量。
以下是我需要解析的文本文件示例。
test information
annoying information
Subscribed more annoying info
more annoying info
dvd = 234,
cls = 453,
jhd = 567,
more annoying info
more annoying info
dxv = 456,
hft = 876;
more annoying info
test information
annoying information
Subscribed more annoying info
more annoying info
dvd = 234,
cls = 455,
more annoying info
more annoying info
dxv = 456,
hft = 876,
jjd = 768;
more annoying info
test information
annoying information
Disconnected more annoying info
more annoying info
more annoying info
修改
我对这个模糊的问题道歉。我必须学习如何提出更好的问题。
我的思维过程是确保程序将订阅和;
之间的所有细节关联为一条记录。我认为我困惑的部分是阅读线条。在我的脑海中,我看到循环读取订阅的行,然后进入方法并读取下一行并分配值,依此类推,直到它到达;
。一旦完成,我试图弄清楚如何告诉程序退出该方法,但继续从分号后的行读取。也许我在想这个。
我会接受我给出的建议,看看我能提出什么来解决这个问题。谢谢。
答案 0 :(得分:0)
与问题的所有代码解决方案一样,有许多可能的方法可以实现您的目标。有些人会比其他人更好。以下是一种可以帮助您指明正确方向的方法。
您可以检查字符串是否以关键字或值开头,例如“dvd”(请参阅MSDN String.StartsWith)。
如果是,那么您可以将字符串拆分为一个部分数组(参见MSDN String.Split)。
然后,您可以使用所需值的索引从字符串数组中获取每个部分的值。
使用检索到的值执行您需要的操作。
继续检查每一行的关键业务规则(即将结束该部分的分号)。也许你可以检查字符串的最后一个字符。 (见String.EndsWith)
答案 1 :(得分:0)
从你的问题来看,现在还不清楚你正在努力解决的具体问题。我建议您编辑您的问题,提供您想要克服的具体挑战。目前你的问题陈述是&#34;已经停留在搜索特定的信息片段#34;。这是非特定的。
说过我会尽力帮助你。
首先,你永远不会像if
那样进入:
line.ToLower().Contains("Disconnected")
在这里,您将所有字符转换为小写,然后您尝试在其中查找大写为"D"
的子字符串。上面的表达式(几乎)总是评估为false。
其次,为了让您的应用程序执行您想要执行的操作,需要跟踪当前的解析状态。我会忽略&#34; Disconnected&#34;现在,你没有表现出它的重要性。
我假设您正在尝试在文件中找到Subscribed和第一个分号之间的所有内容。我还会对可以构成字符串的内容做出其他一些假设,我不会在这里列出。这些可能是错误的,但考虑到您提供的信息,这是我最好的猜测。
您的程序将从状态开始&#34;寻找订阅&#34;。你已经设置了read循环,这很好。在这个循环中,你读取文件的行,你会发现一个包含单词Subscription。
一旦找到这样的行,你的解析器就需要转移到#34;解析订阅&#34;州。在这种状态下,当你读取行时,你会寻找像jjd = 768
这样的行,最后可能会用分号。您可以使用正则表达式检查线条是否与图案匹配。
正则表达式还可以将匹配划分为捕获组,以便您可以分别提取名称(jjd
)和值(768
)。分号的存在或不存在可能是另一个RegEx组。
请注意,RegEx并不是解决此问题的唯一方法,但这是第一个想到的方法。
然后你继续匹配你的正则表达式的行,并提取名称和值,直到你遇到分号,此时你切换回&#34;寻找订阅&#34;状态。
使用当前状态来决定如何处理下一个读取行。
您将一直持续到文件结束。
一般来说,你想阅读解析。
希望这有帮助。
答案 2 :(得分:0)
处理包含半结构化数据的文本文件时,状态变量可以简化算法。在下面的代码中,布尔状态变量isInRecord
用于跟踪记录中line
的时间。
using System;
using System.Collections.Generic;
using System.IO;
namespace ConsoleApplication19
{
public class Program
{
private readonly static String _testData = @"
test information
annoying information
Subscribed more annoying info
more annoying info
dvd = 234,
cls = 453,
jhd = 567,
more annoying info
more annoying info
dxv = 456,
hft = 876;
more annoying info
test information
annoying information
Subscribed more annoying info
more annoying info
dvd = 234,
cls = 455,
more annoying info
more annoying info
dxv = 456,
hft = 876,
jjd = 768;
more annoying info
test information
annoying information
Disconnected more annoying info
more annoying info
more annoying info";
public static void Main(String[] args)
{
/* Create a temporary file containing the test data. */
var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Path.GetRandomFileName());
File.WriteAllText(testFile, _testData);
try
{
var p = new Program();
var records = p.GetRecords(testFile);
foreach (var kvp in records)
{
Console.WriteLine("Record #" + kvp.Key);
foreach (var entry in kvp.Value)
{
Console.WriteLine(" " + entry);
}
}
}
finally
{
File.Delete(testFile);
}
}
private Dictionary<String, List<String>> GetRecords(String path)
{
var results = new Dictionary<String, List<String>>();
var recordNumber = 0;
var isInRecord = false;
using (var reader = new StreamReader(path))
{
String line;
while ((line = reader.ReadLine()) != null)
{
line = line.Trim();
if (line.StartsWith("Disconnected"))
{
// needs to continue on search for Disconnected or Subscribed
isInRecord = false;
}
else if (line.StartsWith("Subscribed"))
{
// program needs to continue reading file
// looking for and assigning values to
// dvd, cls, jhd, dxv, hft
// records start at Subscribed and end at ;
isInRecord = true;
recordNumber++;
}
else if (isInRecord)
{
// Check if the line has a general format of "something = something".
var parts = line.Split("=".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
if (parts.Length != 2)
continue;
// Update the relevant dictionary key, or add a new key.
List<String> entries;
if (results.TryGetValue(recordNumber.ToString(), out entries))
entries.Add(line);
else
results.Add(recordNumber.ToString(), new List<String>() { line });
// Determine if the isInRecord state variable should be toggled.
var lastCharacter = line[line.Length - 1];
if (lastCharacter == ';')
isInRecord = false;
}
}
}
return results;
}
}
}