尝试使用C#应用程序从文本文件读取数据。有多行数据,每行以整数开头,然后是一堆双精度值。文本文件的一部分看起来像这样,
33 0.573140941467E-01 0.112914262390E-03 0.255553577735E-02 0.497192659486E-04 0.141869181079E-01-0.147813598922E-03
34 0.570076593453E-01 0.100112550891E-03 0.256427138318E-02-0.868691490164E-05 0.142821920093E-01-0.346011975369E-03
35 0.715507714946E-01 0.316132133031E-03-0.106581466521E-01-0.920513736900E-04 0.138018668842E-01-0.212219497066E-03
Run Code Online (Sandbox Code Playgroud)
33、34、35是整数值,后跟6个double值。并且不能保证这些双精度值之间有空格或其他定界符。即,如果双精度数为负数,则其前面将带有“-”,这将占用空间。因此,基本上所有6个double值都可能在一起。
现在的挑战是,如何优雅地提取它?
我试过的
String.Split(' ');
Run Code Online (Sandbox Code Playgroud)
这将无法正常工作,因为不能保证在初始整数值与其余双精度值之间留有空格。
这可以使用C ++在C ++中轻松解决sscanf。
String.Split(' ');
Run Code Online (Sandbox Code Playgroud)
包含双精度值的文本文件是由第三方工具生成的,我无法控制其输出。
有没有一种方法可以逐行优雅地提取整数和双精度值?
Cet*_*soz 12
如果我认为正确,则您具有“固定宽度数据”格式。比您可以简单地解析这个事实。
即假设值在文件中d:\temp\doubles.txt:
void Main()
{
var filename = @"d:\temp\doubles.txt";
Func<string, string[]> split = (s) =>
{
string[] res = new string[7];
res[0] = s.Substring(0, 2);
for (int i = 0; i < 6; i++)
{
res[i + 1] = s.Substring(2 + (i * 19), 19);
}
return res;
};
var result = from l in File.ReadAllLines(filename)
let la = split(l)
select new
{
i = int.Parse(la[0]),
d1 = double.Parse(la[1]),
d2 = double.Parse(la[2]),
d3 = double.Parse(la[3]),
d4 = double.Parse(la[4]),
d5 = double.Parse(la[5]),
d6 = double.Parse(la[6])
};
foreach (var e in result)
{
Console.WriteLine($"{e.i}, {e.d1}, {e.d2}, {e.d3}, {e.d4}, {e.d5}, {e.d6}");
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
33, 0.0573140941467, 0.00011291426239, 0.00255553577735, 4.97192659486E-05, 0.0141869181079, -0.000147813598922
34, 0.0570076593453, 0.000100112550891, 0.00256427138318, -8.68691490164E-06, 0.0142821920093, -0.000346011975369
35, 0.0715507714946, 0.000316132133031, -0.0106581466521, -9.205137369E-05, 0.0138018668842, -0.000212219497066
Run Code Online (Sandbox Code Playgroud)
PS:使用您的准确数据,int应该分配更多空间。
用正则表达式解决。我的第一枪是:
"[\s-+]\d+\.\d+E[+-]\d\d"
Run Code Online (Sandbox Code Playgroud)
我只是这样尝试的:
using System;
using System.Globalization;
using System.Text.RegularExpressions;
namespace ConsoleApp1 {
class Program {
static void Main(string[] args) {
var fileContents =
"33 0.573140941467E-01 0.112914262390E-03 0.255553577735E-02 0.497192659486E-04 0.141869181079E-01-0.147813598922E-03"
+ "34 0.570076593453E-01 0.100112550891E-03 0.256427138318E-02-0.868691490164E-05 0.142821920093E-01-0.346011975369E-03"
+ "35 0.715507714946E-01 0.316132133031E-03-0.106581466521E-01-0.920513736900E-04 0.138018668842E-01-0.212219497066E-03";
var rex = new Regex(@"[\s-+]\d+\.\d+E[+-]\d\d", RegexOptions.Multiline);
foreach (Match match in rex.Matches(fileContents)) {
double d = double.Parse(match.Value.TrimStart(), NumberFormatInfo.InvariantInfo);
Console.WriteLine("found a match: " + match.Value.TrimStart() + " => " + d);
}
Console.ReadLine();
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用以下输出(德语本地化,逗号作为小数点分隔符):
found a match: 0.573140941467E-01 => 0,0573140941467
found a match: 0.112914262390E-03 => 0,00011291426239
found a match: 0.255553577735E-02 => 0,00255553577735
found a match: 0.497192659486E-04 => 4,97192659486E-05
found a match: 0.141869181079E-01 => 0,0141869181079
found a match: -0.147813598922E-03 => -0,000147813598922
found a match: 0.570076593453E-01 => 0,0570076593453
found a match: 0.100112550891E-03 => 0,000100112550891
found a match: 0.256427138318E-02 => 0,00256427138318
found a match: -0.868691490164E-05 => -8,68691490164E-06
found a match: 0.142821920093E-01 => 0,0142821920093
found a match: -0.346011975369E-03 => -0,000346011975369
found a match: 0.715507714946E-01 => 0,0715507714946
found a match: 0.316132133031E-03 => 0,000316132133031
found a match: -0.106581466521E-01 => -0,0106581466521
found a match: -0.920513736900E-04 => -9,205137369E-05
found a match: 0.138018668842E-01 => 0,0138018668842
found a match: -0.212219497066E-03 => -0,000212219497066
Run Code Online (Sandbox Code Playgroud)