Подтвердить что ты не робот

Чтение номеров из текстового файла в С#

Это то, что должно быть очень просто. Я просто хочу читать числа и слова из текстового файла, состоящего из токенов, разделенных пробелом. Как вы это делаете на С#? Например, в С++ следующий код будет работать для чтения целого числа, 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 файла также является хорошим примером того, почему вы хотите прекратить чтение файла, как только будет прочитан полный токен.

4b9b3361

Ответ 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);
  }

Ответ 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();
    }
}