C# 从文件C中读取双值#
我有一个txt文件,其格式为: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,然后转换它。 我想知道有没有更快的方法 致以最诚挚的问候,,听起来这是一个很好的解决方案。 无需改进。,这听起来是个不错的解决方案。 不需要改进。您可以执行一些微优化,但您建议的方式
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