从文本文件中提取数组

本文关键字:提取 数组 文件 文本 | 更新日期: 2023-09-27 18:35:15

我有一个巨大的(~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 个数字,如果它们匹配,我会处理接下来的两行。 但从那以后,事情可能已经发生了变化!

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

从文本文件中提取数组

从我编码 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 进行二叉搜索,否则您需要通读文件,直到找到要查找的数据。

您可以使用该字符串。拆分(字符[]) 方法:http://msdn.microsoft.com/en-us/library/b873y76a.aspx

此方法返回字符串数组。

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

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

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

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[] 解析和创建。