Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从文件C中读取双值#_C# - Fatal编程技术网

C# 从文件C中读取双值#

C# 从文件C中读取双值#,c#,C#,我有一个txt文件,其格式为: 0.32423 1.3453 3.23423 0.12332 3.1231 9.23432432 9.234324234 -1.23432 12.23432 ... 每行有三个双值。此文件中有10000多行。我可以使用ReadStream.ReadLine和String.Split,然后转换它。 我想知道有没有更快的方法 致以最诚挚的问候,,听起来这是一个很好的解决方案。 无需改进。,这听起来是个不错的解决方案。 不需要改进。您可以执行一些微优化,但您建议的方式

我有一个txt文件,其格式为:

0.32423 1.3453 3.23423
0.12332 3.1231 9.23432432
9.234324234 -1.23432 12.23432
...
每行有三个双值。此文件中有10000多行。我可以使用ReadStream.ReadLine和String.Split,然后转换它。 我想知道有没有更快的方法

致以最诚挚的问候,

,听起来这是一个很好的解决方案。
无需改进。

,这听起来是个不错的解决方案。

不需要改进。

您可以执行一些微优化,但您建议的方式听起来很简单

10000行应该不会花很长时间-您是否尝试过,并发现您实际上遇到了性能问题?例如,这里有两个短程序-一个创建10000行文件,另一个读取该文件:

CreateFile.cs:

using System;
using System.IO;

public class Test
{
    static void Main()
    {
        Random rng = new Random();
        using (TextWriter writer = File.CreateText("test.txt"))
        {
            for (int i = 0; i < 10000; i++)
            {
                writer.WriteLine("{0} {1} {2}", rng.NextDouble(),
                                 rng.NextDouble(), rng.NextDouble());
            }
        }
    }
}

在我的上网本上(承认里面有SSD),读取文件只需要82毫秒。我认为这可能不是问题:)

您可能可以执行一些微优化,但您所建议的方式听起来非常简单

10000行应该不会花很长时间-您是否尝试过,并发现您实际上遇到了性能问题?例如,这里有两个短程序-一个创建10000行文件,另一个读取该文件:

CreateFile.cs:

using System;
using System.IO;

public class Test
{
    static void Main()
    {
        Random rng = new Random();
        using (TextWriter writer = File.CreateText("test.txt"))
        {
            for (int i = 0; i < 10000; i++)
            {
                writer.WriteLine("{0} {1} {2}", rng.NextDouble(),
                                 rng.NextDouble(), rng.NextDouble());
            }
        }
    }
}

在我的上网本上(承认里面有SSD),读取文件只需要82毫秒。我认为这可能不是问题:)

你的方法已经很好了


您可以通过编写一个readline函数来改进它,该函数返回一个double数组,并在其他程序中重用该函数

你的方法已经很好了


您可以通过编写一个readline函数来改进它,该函数返回一个double数组,并在其他程序中重用该函数

我建议你一次读完所有的台词

string[] lines = System.IO.File.ReadAllLines(fileName);

这将确保以最大效率完成I/O。您必须测量(配置文件),但我预计转换所需的时间要少得多。

我建议您使用

string[] lines = System.IO.File.ReadAllLines(fileName);

这将确保以最大效率完成I/O。您必须测量(配置文件),但我预计转换所需的时间要少得多。

此解决方案稍微慢一点(请参见末尾的基准测试),但阅读起来更好。它还应该具有更高的内存效率,因为此时只缓冲当前字符(而不是整个文件或行)

读取数组是该读取器中的一个附加功能,它假定数组的大小始终作为int值排在第一位

IParsable
是另一项功能,它使各种类型的
Parse
方法的实现变得容易

class StringSteamReader {
    private StreamReader sr;

    public StringSteamReader(StreamReader sr) {
        this.sr = sr;
        this.Separator = ' ';
    }

    private StringBuilder sb = new StringBuilder();
    public string ReadWord() {
        eol = false;
        sb.Clear();
        char c;
        while (!sr.EndOfStream) {
            c = (char)sr.Read();
            if (c == Separator) break;
            if (IsNewLine(c)) {
                eol = true;
                char nextch = (char)sr.Peek();
                while (IsNewLine(nextch)) {
                    sr.Read(); // consume all newlines
                    nextch = (char)sr.Peek();
                }
                break;
            }
            sb.Append(c);
        }
        return sb.ToString();
    }

    private bool IsNewLine(char c) {
        return c == '\r' || c == '\n';
    }

    public int ReadInt() {
        return int.Parse(ReadWord());
    }

    public double ReadDouble() {
        return double.Parse(ReadWord());
    }

    public bool EOF {
        get { return sr.EndOfStream; }
    }

    public char Separator { get; set; }

    bool eol;
    public bool EOL {
        get { return eol || sr.EndOfStream; }
    }

    public T ReadObject<T>() where T : IParsable, new() {
        var obj = new T();
        obj.Parse(this);
        return obj;
    }

    public int[] ReadIntArray() {
        int size = ReadInt();
        var a = new int[size];
        for (int i = 0; i < size; i++) {
            a[i] = ReadInt();
        }
        return a;
    }

    public double[] ReadDoubleArray() {
        int size = ReadInt();
        var a = new double[size];
        for (int i = 0; i < size; i++) {
            a[i] = ReadDouble();
        }
        return a;
    }

    public T[] ReadObjectArray<T>() where T : IParsable, new() {
        int size = ReadInt();
        var a = new T[size];
        for (int i = 0; i < size; i++) {
            a[i] = ReadObject<T>();
        }
        return a;
    }

    internal void NextLine() {
        eol = false;
    }
}

interface IParsable {
    void Parse(StringSteamReader r);
}
我使用了一个包含1.000.000行双值(每行3个值)的文件。文件位于SSD磁盘上,每个测试在释放模式下重复多次。以下是结果(平均):


因此,正如前面提到的
StringStreamReader
比其他方法慢一点。对于10.000行,性能大约为(120ms/95ms/100ms)。

此解决方案稍微慢一点(请参见末尾的基准测试),但阅读起来更好。它还应该具有更高的内存效率,因为此时只缓冲当前字符(而不是整个文件或行)

读取数组是该读取器中的一个附加功能,它假定数组的大小始终作为int值排在第一位

IParsable
是另一项功能,它使各种类型的
Parse
方法的实现变得容易

class StringSteamReader {
    private StreamReader sr;

    public StringSteamReader(StreamReader sr) {
        this.sr = sr;
        this.Separator = ' ';
    }

    private StringBuilder sb = new StringBuilder();
    public string ReadWord() {
        eol = false;
        sb.Clear();
        char c;
        while (!sr.EndOfStream) {
            c = (char)sr.Read();
            if (c == Separator) break;
            if (IsNewLine(c)) {
                eol = true;
                char nextch = (char)sr.Peek();
                while (IsNewLine(nextch)) {
                    sr.Read(); // consume all newlines
                    nextch = (char)sr.Peek();
                }
                break;
            }
            sb.Append(c);
        }
        return sb.ToString();
    }

    private bool IsNewLine(char c) {
        return c == '\r' || c == '\n';
    }

    public int ReadInt() {
        return int.Parse(ReadWord());
    }

    public double ReadDouble() {
        return double.Parse(ReadWord());
    }

    public bool EOF {
        get { return sr.EndOfStream; }
    }

    public char Separator { get; set; }

    bool eol;
    public bool EOL {
        get { return eol || sr.EndOfStream; }
    }

    public T ReadObject<T>() where T : IParsable, new() {
        var obj = new T();
        obj.Parse(this);
        return obj;
    }

    public int[] ReadIntArray() {
        int size = ReadInt();
        var a = new int[size];
        for (int i = 0; i < size; i++) {
            a[i] = ReadInt();
        }
        return a;
    }

    public double[] ReadDoubleArray() {
        int size = ReadInt();
        var a = new double[size];
        for (int i = 0; i < size; i++) {
            a[i] = ReadDouble();
        }
        return a;
    }

    public T[] ReadObjectArray<T>() where T : IParsable, new() {
        int size = ReadInt();
        var a = new T[size];
        for (int i = 0; i < size; i++) {
            a[i] = ReadObject<T>();
        }
        return a;
    }

    internal void NextLine() {
        eol = false;
    }
}

interface IParsable {
    void Parse(StringSteamReader r);
}
我使用了一个包含1.000.000行双值(每行3个值)的文件。文件位于SSD磁盘上,每个测试在释放模式下重复多次。以下是结果(平均):


因此,正如前面提到的
StringStreamReader
比其他方法慢一点。对于10000行,性能大约为(120ms/95ms/100ms)。

C很好,但我需要C#。马克,对于I/O绑定的问题,为什么C会更快?如果你多次解析文件,你会看到C的改进。但我对海报的问题是,你是在多次解析文件吗?如果是,为什么?如果不是,为什么这甚至是一个问题?在我看来,如果你甚至不得不问这个问题,你的程序设计有问题。C很好,但我需要C。马克,为什么C对于I/O绑定的问题会更快?如果你多次解析文件,你会看到C的改进。但我对海报的问题是,你是在多次解析文件吗?如果是,为什么?如果不是,为什么这甚至是一个问题?在我看来,如果你甚至不得不问这个问题,你的程序设计就有问题。这可能是一件危险的事情,因为你不知道文件中有多少行。:-)Rev,你是对的,但在问题中:“超过10000行”,我认为是“少于20000行”,我会不假思索地使用
ReadAllLines()
最多100000行。这可能是一件危险的事情,因为你不知道文件中有多少行。:-)Rev,你是对的,但在问题中:“超过10000行”,我认为是“少于20000行”,我会不假思索地使用
ReadAllLines()
最多100000行。如果你想知道你能跑多快,请查看该解决方案:如果你想知道你能跑多快,请查看该解决方案:
Test_StringStreamReader: 00:00:01.1980975
Test_ReadLine:           00:00:00.9117553
Test_ReadAllLines:       00:00:01.1362452