Класс FileReader в C # - PullRequest
       9

Класс FileReader в C #

1 голос
/ 13 октября 2009

Я ищу быстрый класс для работы с текстовыми файлами и удобного чтения различных объектов (методы вроде NextInt32, NextDouble, NextLine и т. Д.). Можете мне что-нибудь посоветовать?

Редактировать: BinaryReader - плохой класс в моем случае. Формат моих данных не является двоичным. У меня есть файл как

1 2 3
FirstToken NextToken
1.23 2,34

И я хочу прочитать этот файл с кодом вроде:

int a = FileReader.NextInt32();
int b = FileReader.NextInt32();
int c = FileReader.NextInt32();
int d = FileReader.NextString();
int e = FileReader.NextString();
int f = FileReader.NextDouble();
int g = FileReader.NextDouble();

Edit2: Ищу аналоговый сканер с Java

Ответы [ 7 ]

4 голосов
/ 13 октября 2009

Я собираюсь добавить это как отдельный ответ, потому что он совершенно отличается от ответа, который я уже дал. Вот как вы можете начать создавать свой собственный класс Scanner:

class Scanner : System.IO.StringReader
{
  string currentWord;

  public Scanner(string source) : base(source)
  {
     readNextWord();
  }

  private void ReadNextWord()
  {
     System.Text.StringBuilder sb = new StringBuilder();
     char nextChar;
     int next;
     do
     {
        next = this.Read();
        if (next < 0)
           break;
        nextChar = (char)next;
        if (char.IsWhiteSpace(nextChar))
           break;
        sb.Append(nextChar);
     } while (true);
     while((this.Peek() >= 0) && (char.IsWhiteSpace((char)this.Peek())))
        this.Read();
     if (sb.Length > 0)
        currentWord = sb.ToString();
     else
        currentWord = null;
  }

  public bool HasNextInt()
  {
     if (currentWord == null)
        return false;
     int dummy;
     return int.TryParse(currentWord, out dummy);
  }

  public int NextInt()
  {
     try
     {
        return int.Parse(currentWord);
     }
     finally
     {
        readNextWord();
     }
  }

  public bool HasNextDouble()
  {
     if (currentWord == null)
        return false;
     double dummy;
     return double.TryParse(currentWord, out dummy);
  }

  public double NextDouble()
  {
     try
     {
        return double.Parse(currentWord);
     }
     finally
     {
        readNextWord();
     }
  }

  public bool HasNext()
  {
     return currentWord != null;
  }
}
4 голосов
/ 13 октября 2009

Я считаю, что этот метод расширения для TextReader поможет:

public static class TextReaderTokenizer
{
    // Adjust as needed. -1 is EOF.
    private static int[] whitespace = { -1, ' ', '\r' , '\n', '\t' };

    public static T ReadToken<T>(this TextReader reader)
    {
        StringBuilder sb = new StringBuilder();
        while (Array.IndexOf(whitespace, reader.Peek()) < 0)
        {
            sb.Append((char)reader.Read());
        }
        return (T)Convert.ChangeType(sb.ToString(), typeof(T));
    }    
}

Может использоваться таким образом:

TextReader reader = File.OpenText("foo.txt");
int n = reader.ReadToken<int>();
string s = reader.ReadToken<string>();

[РЕДАКТИРОВАТЬ] В соответствии с запросом в комментариях к вопросу, приведенная выше версия обертки экземпляра, параметризованная с разделителями и CultureInfo:

public class TextTokenizer
{
    private TextReader reader;
    private Predicate<char> isDelim;
    private CultureInfo cultureInfo;

    public TextTokenizer(TextReader reader, Predicate<char> isDelim, CultureInfo cultureInfo)
    {
        this.reader = reader;
        this.isDelim = isDelim;
        this.cultureInfo = cultureInfo;
    }

    public TextTokenizer(TextReader reader, char[] delims, CultureInfo cultureInfo)
    {
        this.reader = reader;
        this.isDelim = c => Array.IndexOf(delims, c) >= 0;
        this.cultureInfo = cultureInfo;
    }

    public TextReader BaseReader
    {
        get { return reader; }
    }

    public T ReadToken<T>()
    {
        StringBuilder sb = new StringBuilder();
        while (true)
        {
            int c = reader.Peek();
            if (c < 0 || isDelim((char)c))
            {
                break;
            }
            sb.Append((char)reader.Read());
        }
        return (T)Convert.ChangeType(sb.ToString(), typeof(T));
    }    
}

Пример использования:

TextReader reader = File.OpenText("foo.txt");
TextTokenizer tokenizer = new TextTokenizer(
    reader,
    new[] { ' ', '\r', '\n', '\t' },
    CultureInfo.InvariantCulture);
int n = tokenizer.ReadToken<int>();
string s = tokenizer.ReadToken<string>();
4 голосов
/ 13 октября 2009

Вы должны определить точно как должен выглядеть ваш формат файла. Как бы вы представили строку с пробелом в нем? Что определяет, куда идут терминаторы строки?

Как правило, вы можете использовать TextReader и метод ReadLine, а затем double.TryParse, int.TryParse и т. Д., Но сначала вам нужно будет закрепить формат вниз.

2 голосов
/ 13 октября 2009

Вы проверили класс BinaryReader? Да, это текстовый файл, но ничто не мешает вам рассматривать его как двоичные данные и, следовательно, использовать BinaryReader. В нем есть все методы, которые вы ищете, за исключением ReadLine. Однако реализовать этот метод поверх BinaryReader не составит труда.

1 голос
/ 13 октября 2009

Если вам нужно нужны текстовые файлы (т. Е. Кодировка UTF-8 или ASCII), тогда двоичный модуль записи работать не будет.

Вы можете использовать TextReader, но в отличие от BinaryReader и TextWriter он не поддерживает никаких типов, кроме Line и char. Вам нужно будет определить, какие разделители разрешены, и проанализировать данные базы Line самостоятельно.

0 голосов
/ 13 октября 2009

Вероятно, вы можете использовать класс System.IO.File для чтения файла и System.Convert для анализа строк, которые вы читаете из файла.

string line = String.Empty;
while( (line = file.ReadLine()).IsNullOrEmpty() == false )
{
   TYPE value = Convert.ToTYPE( line );
}

Где TYPE - это тот тип, с которым вы имеете дело в этой конкретной строке / файле.

Если в одной строке несколько значений, вы можете выполнить разбиение и прочитать отдельные значения, например,

string[] parts = line.Split(' ');
if( parts.Length > 1 )
{
   foreach( string item in parts )
   {
      TYPE value = Convert.ToTYPE( item );
   }
}
else
{
   // Use the code from before
}
0 голосов
/ 13 октября 2009

Класс System.IO.BinaryReader - это то, что вам нужно.

Пример реализации метода ReadLine :

public static class Extensions
{
    public static String ReadLine(this BinaryReader binaryReader)
    {
        var bytes = new List<Byte>();
        byte temp;

        while ((temp = (byte)binaryReader.Read()) < 10)
            bytes.Add(temp);

        return Encoding.Default.GetString(bytes.ToArray());
    }
}

Пример использования этого класса:

using System;
using System.IO;
using System.Security.Permissions;

class Test
{
    static void Main()
    {
        // Load application settings.
        AppSettings appSettings = new AppSettings();
        Console.WriteLine("App settings:\nAspect Ratio: {0}, " +
            "Lookup directory: {1},\nAuto save time: {2} minutes, " +
            "Show status bar: {3}\n",
            new Object[4]{appSettings.AspectRatio.ToString(),
            appSettings.LookupDir, appSettings.AutoSaveTime.ToString(),
            appSettings.ShowStatusBar.ToString()});

        // Change the settings.
        appSettings.AspectRatio   = 1.250F;
        appSettings.LookupDir     = @"C:\Temp";
        appSettings.AutoSaveTime  = 10;
        appSettings.ShowStatusBar = true;

        // Save the new settings.
        appSettings.Close();
    }
}

// Store and retrieve application settings.
class AppSettings
{
    const string fileName = "AppSettings#@@#.dat";
    float  aspectRatio;
    string lookupDir;
    int    autoSaveTime;
    bool   showStatusBar;

    public float AspectRatio
    {
        get{ return aspectRatio; }
        set{ aspectRatio = value; }
    }

    public string LookupDir
    {
        get{ return lookupDir; }
        set{ lookupDir = value; }
    }

    public int AutoSaveTime
    {
        get{ return autoSaveTime; }
        set{ autoSaveTime = value; }
    }

    public bool ShowStatusBar
    {
        get{ return showStatusBar; }
        set{ showStatusBar = value; }
    }

    public AppSettings()
    {
        // Create default application settings.
        aspectRatio   = 1.3333F;
        lookupDir     = @"C:\AppDirectory";
        autoSaveTime  = 30;
        showStatusBar = false;

        if(File.Exists(fileName))
        {
            BinaryReader binReader =
                new BinaryReader(File.Open(fileName, FileMode.Open));
            try
            {
                // If the file is not empty,
                // read the application settings.
                // First read 4 bytes into a buffer to
                // determine if the file is empty.
                byte[] testArray = new byte[3];
                int count = binReader.Read(testArray, 0, 3);

                if (count != 0)
                {
                    // Reset the position in the stream to zero.
                    binReader.BaseStream.Seek(0, SeekOrigin.Begin);

                    aspectRatio   = binReader.ReadSingle();
                    lookupDir     = binReader.ReadString();
                    autoSaveTime  = binReader.ReadInt32();
                    showStatusBar = binReader.ReadBoolean();
                }
            }

            // If the end of the stream is reached before reading
            // the four data values, ignore the error and use the
            // default settings for the remaining values.
            catch(EndOfStreamException e)
            {
                Console.WriteLine("{0} caught and ignored. " +
                    "Using default values.", e.GetType().Name);
            }
            finally
            {
                binReader.Close();
            }
        }

    }

    // Create a file and store the application settings.
    public void Close()
    {
        using(BinaryWriter binWriter =
            new BinaryWriter(File.Open(fileName, FileMode.Create)))
        {
            binWriter.Write(aspectRatio);
            binWriter.Write(lookupDir);
            binWriter.Write(autoSaveTime);
            binWriter.Write(showStatusBar);
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...