从文本文件中提取数组

时间:2013-10-14 20:55:09

标签: c# arrays file extract

我有一个巨大的(~500K)文本文件,如下所示:

{   // H-20e180a.wav 
    {-7,5,-4,-1,-9,2,-5,-1,2,-12,12,-33,34,-48,41,-40,16,20,730,4751,3861},
    {-7,5,-4,-1,-9,2,-5,-1,2,-12,12,-33,34,-48,41,-40,16,20,}
}

(注意:在实际文件中有一些额外的混乱,并且每个〜140 elts的数组对更长)。

我希望创建一个允许我提取一对数组的C#/ .NET例程:

int [] [] elev_neg20__azi_180 = ArraysForLocation( -20, 180 );

我的基本策略是什么?

从我编写BASIC的日子开始,我会一次读一行,寻找'// H',然后提取2个数字,如果匹配,我将处理接下来的两行。但事情可能已经发生了变化!

我猜测没有阅读整个文件的快捷方式......

3 个答案:

答案 0 :(得分:2)

  

从我编写BASIC的日子开始,我会一次读一行,寻找'// H',然后提取2个数字,如果匹配,我会处理接下来的两行。< / em>的

以同样的方式接近它。使用System.IO.StreamReader,您可以重复ReadLine,直到找到所需的部分,然后阅读接下来的两行数据和Close。然后String.Split以逗号分隔的值和Convert.ToInt32

实际上你可能不会明确地调用CloseStreamReader类实现IDisposable,因此最佳做法是将其包装在using语句中(自动调用将关闭流的Dispose)。

using (var reader = new StreamReader("somefile.txt"))
{
   string line = reader.ReadLine();
}

解析包含一行数据的字符串可以这样做:

string line = "{-7,5,-4,-1,-9,2,-5,-1,2,-12,12,-33,34,-48,41,-40,16,20,730,4751,3861},";

var regex = new Regex("[{},]");
int[] ints = regex.Replace(line, " ").Trim().
                   Split(new char[] { ' ' }).Select(int.Parse).ToArray();

从方法返回数组的选项是使用out值。这样,您的正常回报值可用于表示成功。像这样的方法签名:

public bool ArraysForLocation(int x, int y, out int[] array1, out int[] array2)

可以像这样调用:

int[] a1;
int[] a2;
bool ok = ArraysForLocation(-20, 180, out a1, out a2);
  

我猜测没有阅读整个文件的快捷方式......

除非您正在寻找的是尾声,否则您不会阅读整个文件。您流式传输数据,因此一次只能读取一行。除非对文件内容进行排序,以便您可以使用FileStream.Seek进行二进制搜索,否则您需要仔细阅读该文件,直到找到所需的数据为止。

答案 1 :(得分:1)

您可以使用string.Split(Char [])方法:http://msdn.microsoft.com/en-us/library/b873y76a.aspx

此方法返回一个字符串数组。

char参数是您要拆分的分隔符。因此,您可以将其调用一次,将长字符串拆分为所需的两个数组,然后在逗号上拆分每个数组以获取各个值的相应数组。之后,如果需要,您可以将字符串转换为int。

答案 2 :(得分:1)

如果您进行了大量查找,速度比内存更重要,您可能需要处理一次文件并将信息放入字典中。这样查找速度非常快,您只需要读取一次文件。

以下是一些解析数据的代码,如您给出的示例:

class Program
{
    static void Main(string[] args)
    {
        string filename = "example.txt";

        Dictionary<string, int[][]> myDictionary = new Dictionary<string, int[][]>();

        BuildMyDataDictionary(filename, myDictionary);

        //lookup via key
        int x = 20;
        int y = 180;
        string key = string.Format("{0}.{1}", x, y);
        int[][] values = myDictionary[key];

        //print the values to check
        foreach (int[] array in values)
            foreach (int i in array)
                Console.Write(i + ", ");
        Console.WriteLine();

        Console.ReadKey();
    }

    private static void BuildMyDataDictionary(string filename, Dictionary<string, int[][]> myDictionary)
    {
        using (StreamReader r = new StreamReader(filename))
        {
            string line = r.ReadLine();
            // read through the file line by line and build the dictionary
            while (line != null)
            {
                Regex regx = new Regex(@"//\s*H\-(\d*)\w(\d*)");
                Match m = regx.Match(line);
                if (m.Success)
                {
                    // make a key of the two parts int 1 and int2 separated by a "."
                    string key = string.Format("{0}.{1}", m.Groups[1], m.Groups[2]);

                    // continue reading the block
                    List<int[]> intList = new List<int[]>();
                    line = r.ReadLine();
                    while (!Regex.IsMatch(line, @"^\s*\}"))
                    {
                        Regex regex = new Regex("[{},]");
                        intList.Add(regex.Replace(line, " ").Trim().Split(new char[] { ' ' }).Select(int.Parse).ToArray());
                        line = r.ReadLine();
                    }
                    myDictionary.Add(key, intList.ToArray());
                }
                line = r.ReadLine();
            }
        }
    }
}

我测试过的示例文件是:

{   // H-20e180a.wav 
    {-7,5,-4,-1,-9,2,-5,-1,2,-12,12,-33,34,-48,41,-40,16,20,730,4751,3861},
    {-7,5,-4,-1,-9,2,-5,-1,2,-12,12,-33,34,-48,41,-40,16,20,}
}
{   // H-21e181a.wav 
    {-7,5,-4,-1,-9,2,-5,-1,2,-12,12,-33,34,-48,41,-40,16,20,730,4751,3861},
    {-7,5,-4,-1,-9,2,-5,-1,2,-12,12,-33,34,-48,41,-40,16,20,}
    {-7,5,-4,-1,-9,2,-5,-1,2,-12,12,-33,34,-48,41,-40,16,20,730,4751,3861},
}

我从上面的jltrem借用了int []解析和创建。