c# - 從文本文件讀取雙精度值




(5)

到目前為止,我看到的答案非常複雜。 這是一個簡單的,沒有過多考慮的東西

根據@ Veljko89的評論,我已經更新了代碼,並且支持無限制號碼

    List<double> ParseLine(string line)
    {
        List<double> ret = new List<double>();

        ret.Add(double.Parse(line.Substring(0, line.IndexOf(' '))));
        line = line.Substring(line.IndexOf(' ') + 1);

        for (; !string.IsNullOrWhiteSpace(line); line = line.Substring(line.IndexOf('E') + 4))
        {
            ret.Add(double.Parse(line.Substring(0, line.IndexOf('E') + 4)));
        }

        return ret;
    }

嘗試使用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

33、34、35是整數值,後跟6個double值。 並且不能保證這些雙精度值之間有空格或其他定界符。 即,如果雙精度數為負數,則它前面將帶有“-”,這將佔用空間。 因此,基本上所有6個double值都可能在一起。

現在的挑戰是,如何優雅地提取它?

我試過的

String.Split(' ');

這將無法正常工作,因為不能保證在初始整數值與其餘雙精度值之間留有空格。

這可以在C ++中使用 sscanf 輕鬆解決。

double a, b, c, d, e, f;

sscanf(string, "%d %lf%lf%lf%lf%lf%lf", &a, &b, &c, &d, &e, &f);
// here string contains a line of data from text file.

包含雙精度值的文本文件是由第三方工俱生成的,我無法控制其輸出。

有沒有一種方法可以逐行優雅地提取整數和雙精度值?


另一種解決方案,單獨處理每行並包含int值:

    static void Main(string[] args) {
        string[] fileLines = {
            "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(@"\b([-+]?\d+(?:\.\d+(?:E[+-]\d+)?)?)\b", RegexOptions.Compiled);
        foreach (var line in fileLines) {

            var dblValues = new List<double>();
            foreach (Match match in rex.Matches(line)) {
                string strVal = match.Groups[1].Value;
                double number = Double.Parse(strVal, NumberFormatInfo.InvariantInfo);
                dblValues.Add(number);
            }

            Console.WriteLine(string.Join("; ", dblValues));
        }

        Console.ReadLine();
    }
}

結果/輸出為:

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

如果我認為正確,則您具有“固定寬度數據”格式。 比您可以簡單地解析這個事實。

即假設值在文件 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}");
    }
}

輸出:

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

PS:根據您的確切數據, int 應該分配更多的空間。


您可以這樣做:

public void ParseFile(string fileLocation)
{
   string[] lines = File.ReadAllLines(fileLocation);

   foreach(var line in lines)
   {
       string[] parts = var Regex.Split(line, "(?((?<!E)-)| )");

       if(parts.Any())
       {
          int first = int.Parse(parts[0]);

          double[] others = parts.Skip(1).Select(a => double.Parse(a)).ToArray();
       }
   }
}   

用正則表達式解決。 我的第一槍是:

"[\s-+]\d+\.\d+E[+-]\d\d"

我只是這樣嘗試的:

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();
        }
    }
}

使用以下輸出(德語本地化,逗號作為小數點分隔符):

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





c#  

c#