从文本文件中提取数组
本文关键字:提取 数组 文件 文本 | 更新日期: 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[] 解析和创建。