c# - पाठ फ़ाइल से दोहरा मान पढ़ना




(5)

अगर मैं उस अधिकार को देख रहा हूं, तो आपके पास "फिक्स्ड चौड़ाई डेटा" प्रारूप है। आप बस उस तथ्य पर पार्स कर सकते हैं।

मान मान एक फ़ाइल में हैं 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 को अधिक स्थान आवंटित करना चाहिए।

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 दोहरे मान हैं। और इन दोहरे मूल्यों के बीच स्थान या कुछ अन्य सीमांकक होने की गारंटी नहीं है। यानी, यदि कोई ऋणात्मक है, तो उसके पहले एक "-" होगा और यह स्थान लेगा। तो मूल रूप से, यह संभव है कि सभी 6 दोहरे मूल्य एक साथ होंगे।

अब चुनौती है कि इस इनायत को कैसे निकाला जाए?

मैंने क्या कोशिश की:

String.Split(' ');

यह काम नहीं करेगा क्योंकि प्रारंभिक पूर्णांक मानों और फिर शेष डबल मानों के बीच एक स्थान की गारंटी नहीं है।

इसे s ++ में 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.

डबल मान वाले टेक्स्ट फ़ाइल को एक 3 पार्टी टूल द्वारा जनरेट किया जाता है और इसका आउटपुट पर मेरा कोई नियंत्रण नहीं है।

क्या कोई ऐसा तरीका है जिससे पूर्णांक और दोहरे मानों को सुंदर रूप से रेखा द्वारा रेखा से निकाला जा सकता है?


अगर हम string.Split उपयोग नहीं कर सकते हैं। तो हम string.Split मदद से नियमित अभिव्यक्ति द्वारा विभाजित करने का प्रयास कर सकते हैं; किसी दिए गए line

string line = @"  33 0.573140941467E-01 0.112914262390E-03 0.255553577735E-02 0.497192659486E-04 0.141869181079E-01-0.147813598922E-03";

हम कोशिश कर सकते है

// Split either
//   1. by space
//   2. zero length "char" which is just after a [0..9] digit and followed by "-" or "+"
var items = Regex
  .Split(line, @" |((?<=[0-9])(?=[+-]))")
  .Where(item => !string.IsNullOrEmpty(item)) // we don't want empty parts 
  .Skip(1)                                    // skip 1st 33
  .Select(item => double.Parse(item));        // we want double

Console.WriteLine(string.Join(Environment.NewLine, items));

और पाओ

0.573140941467E-01
0.112914262390E-03
0.255553577735E-02
0.497192659486E-04
0.141869181079E-01
-0.147813598922E-03

पाठ फ़ाइल के मामले में हमें प्रत्येक पंक्ति को विभाजित करना चाहिए:

Regex regex = new Regex(@" |((?<=[0-9])(?=[+-]))");

var records = File
  .ReadLines(@"c:\MyFile.txt") 
  .Select(line => regex
     .Split(line)
     .Where(item => !string.IsNullOrEmpty(item))
     .Skip(1)
     .Select(item => double.Parse(item))
     .ToArray());

डेमो:

  string[] test = new string[] {
     // your examples
     "  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",

     // Some challenging cases (mine)
     "    36 123+456-789    123e+78 9.9e-95 0.0001", 
  };

  Regex regex = new Regex(@" |((?<=[0-9])(?=[+-]))");

  var records = test
    .Select(line => regex
      .Split(line)
      .Where(item => !string.IsNullOrEmpty(item))
      .Skip(1)
      .Select(item => double.Parse(item))
      .ToArray());

  string testReport = string.Join(Environment.NewLine, records
    .Select(record => $"[{string.Join(", ", record)}]"));

  Console.WriteLine(testReport);

परिणाम:

[0.0573140941467, 0.00011291426239, 0.00255553577735, 4.97192659486E-05, 0.0141869181079, -0.000147813598922]
[0.0570076593453, 0.000100112550891, 0.00256427138318, -8.68691490164E-06, 0.0142821920093, -0.000346011975369]
[0.0715507714946, 0.000316132133031, -0.0106581466521, -9.205137369E-05, 0.0138018668842, -0.000212219497066]
[123, 456, -789, 1.23E+80, 9.9E-95, 0.0001]

आप ऐसा कर सकते हैं:

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

मैं सिर्फ गैर-इष्टतम गया और "E-" स्ट्रिंग को किसी अन्य चीज़ से बदल दिया, जबकि मैंने सभी नकारात्मक चिन्ह को एक स्थान और एक नकारात्मक चिन्ह ("-") से बदल दिया और फिर सभी "E-" मानों को वापस कर दिया।

तब मैं मूल्यों को निकालने के लिए विभाजन का उपयोग करने में सक्षम था।

private static IEnumerable<double> ExtractValues(string values)
{
    return values.Replace("E-", "E*").Replace("-", " -").Replace("E*", "E-").Split(' ').Select(v => double.Parse(v));
}



c#  

c#