Чтение номеров из текстового файла в С#
Это то, что должно быть очень просто. Я просто хочу читать числа и слова из текстового файла, состоящего из токенов, разделенных пробелом. Как вы это делаете на С#? Например, в С++ следующий код будет работать для чтения целого числа, float и word. Я не хочу использовать регулярное выражение или писать какой-либо специальный синтаксический код.
ifstream in("file.txt");
int int_val;
float float_val;
string string_val;
in >> int_val >> float_val >> string_val;
in.close();
Кроме того, всякий раз, когда читается токен, должно считываться не более одного символа за маркером. Это позволяет читать дальше чтение файла в зависимости от значения прочитанного токена. В качестве конкретного примера рассмотрим
string decider;
int size;
string name;
in >> decider;
if (decider == "name")
in >> name;
else if (decider == "size")
in >> size;
else if (!decider.empty() && decider[0] == '#')
read_remainder_of_line(in);
Анализ двоичного PNM файла также является хорошим примером того, почему вы хотите прекратить чтение файла, как только будет прочитан полный токен.
Ответы
Ответ 1
Ответ Brannon объясняет, как читать двоичные данные. Если вы хотите читать текстовые данные, вы должны читать строки и затем анализировать их, для которых, конечно, есть встроенные методы.
Например, чтобы прочитать файл с данными:
10
10.5
hello
Вы можете использовать:
using (TextReader reader = File.OpenText("test.txt"))
{
int x = int.Parse(reader.ReadLine());
double y = double.Parse(reader.ReadLine());
string z = reader.ReadLine();
}
Обратите внимание, что это не имеет обработки ошибок. В частности, он будет генерировать исключение, если файл не существует, первые две строки имеют несоответствующие данные или есть менее двух строк. Он оставит значение null
в z
, если файл имеет только две строки.
Для более надежного решения, которое может потерпеть неудачу более изящно, вы хотите проверить, вернул ли reader.ReadLine()
null
(указывающий конец файла) и использовал int.TryParse
и double.TryParse
вместо Parse
методы.
Предположим, что существует разделитель строк между значениями. Если вы действительно хотите прочитать такую строку:
10 10.5 hello
тогда код будет очень похож:
using (TextReader reader = File.OpenText("test.txt"))
{
string text = reader.ReadLine();
string[] bits = text.Split(' ');
int x = int.Parse(bits[0]);
double y = double.Parse(bits[1]);
string z = bits[2];
}
Опять же, вы хотите выполнить соответствующее обнаружение и обработку ошибок. Обратите внимание, что если файл действительно состоял только из одной строки, вы можете вместо этого использовать File.ReadAllText
, чтобы сделать его несколько проще. Там также File.ReadAllLines
, который считывает весь файл в строковый массив строк.
EDIT: если вам нужно разделить любые пробелы, вам, вероятно, лучше всего прочитать весь файл с помощью File.ReadAllText
, а затем использовать регулярное выражение для его разделения. В этот момент я задаюсь вопросом, как вы представляете строку, содержащую пробел.
В моем опыте вы обычно знаете больше о формате, чем это: будет ли разделитель строк или несколько значений в одной строке, разделенных пробелами и т.д.
Я бы также добавил, что смешанные двоичные/текстовые форматы, как правило, неприятны для решения. Простая и эффективная обработка текста имеет тенденцию читать в буфер, что становится проблематичным, если есть двоичные данные. Если вам нужен текстовый раздел в двоичном файле, лучше всего включить префикс длины, чтобы можно было декодировать только эту часть данных.
Ответ 2
using (FileStream fs = File.OpenRead("file.txt"))
{
BinaryReader reader = new BinaryReader(fs);
int intVal = reader.ReadInt32();
float floatVal = reader.ReadSingle();
string stringVal = reader.ReadString();
}
Ответ 3
Не совсем ответ на ваш вопрос, но просто идея, если вы новичок в С#: если вы используете пользовательский текстовый файл для чтения некоторых параметров конфигурации, вы можете проверить темы сериализации XML в .NET.
Сериализация XML обеспечивает простой способ записи и чтения файлов в формате XML. Например, если у вас есть класс конфигурации, подобный этому:
public class Configuration
{
public int intVal { get; set; }
public float floatVal { get; set; }
public string stringVal { get; set; }
}
вы можете просто сохранить его и загрузить с помощью класса XmlSerializer
:
public void Save(Configuration config, string fileName)
{
XmlSerializer xml = new XmlSerializer(typeof(Configuration));
using (StreamWriter sw = new StreamWriter(fileName))
{
xml.Serialize(sw, config);
}
}
public Configuration Load(string fileName)
{
XmlSerializer xml = new XmlSerializer(typeof(Configuration));
using (StreamReader sr = new StreamReader(fileName))
{
return (Configuration)xml.Deserialize(sr);
}
}
Метод Save
, как определено выше, создаст файл со следующим содержанием:
<Configuration>
<intVal>0</intVal>
<floatVal>0.0</floatVal>
<stringVal></stringVal>
</Configuration>
В этом подходе хорошо то, что вам не нужно менять методы Save
и Load
в случае изменения класса Configuration
.
Ответ 4
Мне нравится использовать StreamReader для быстрого и легкого доступа к файлам. Что-то вроде....
String file = "data_file.txt";
StreamReader dataStream = new StreamReader(file);
string datasample;
while ((datasample = dataStream.ReadLine()) != null)
{
// datasample has the current line of text - write it to the console.
Console.Writeline(datasample);
}
Ответ 5
Попробуйте следующее:
http://stevedonovan.blogspot.com/2005/04/reading-numbers-from-file-in-c.html
IMHO Возможно, чтобы прочитать учебник С#, будет очень полезно иметь в виду всю картину, прежде чем задавать
Ответ 6
У С#, похоже, нет форматированных считывателей потоков, таких как С++ (я был бы рад, если бы был исправлен). Поэтому подход Джона Скита для чтения содержимого в виде строки и разбора их на нужный тип был бы лучшим.
Ответ 7
Вот мой код для чтения чисел из текстового файла. Он демонстрирует концепцию чтения чисел из текстового файла "2 3 5 7..."
public class NumberReader
{
StreamReader reader;
public NumberReader(StreamReader reader)
{
this.reader = reader;
}
public UInt64 ReadUInt64()
{
UInt64 result = 0;
while (!reader.EndOfStream)
{
int c = reader.Read();
if (char.IsDigit((char) c))
{
result = 10 * result + (UInt64) (c - '0');
}
else
{
break;
}
}
return result;
}
}
Вот пример кода для использования этого класса:
using (StreamReader reader = File.OpenText("numbers.txt"))
{
NumberReader numbers = new NumberReader(reader);
while (! reader.EndOfStream)
{
ulong lastNumber = numbers.ReadUInt64();
}
}