1

我有一个巨大的(~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 elt)。

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

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

我的基本策略是什么?

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

我猜没有通读整个文件的捷径......

4

3 回答 3

2

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

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

实际上,您可能不会明确调用Close. 该类StreamReader实现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,否则您需要通读该文件,直到找到您要查找的数据。

于 2013-10-14T21:26:53.880 回答
1

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

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

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

于 2013-10-14T21:00:14.833 回答
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[] 的解析和创建。

于 2013-10-15T01:10:32.013 回答