C#中的FileReader类

我正在寻找快速的类来处理文本文件和舒适阅读不同的对象(像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的模拟扫描仪

我将把它作为一个单独的答案添加,因为它与我已经给出的答案截然不同。 以下是如何开始创建自己的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; } } 

您应该准确定义文件格式的外观。 你会如何表示一个包含空格的字符串? 什么决定了线路终结器的去向?

通常,您可以使用TextReader及其ReadLine方法,然后使用double.TryParseint.TryParse等 – 但您需要先将格式固定下来。

我相信TextReader这种扩展方法可以解决这个问题:

 public static class TextReaderTokenizer { // Adjust as needed. -1 is EOF. private static int[] whitespace = { -1, ' ', '\r' , '\n', '\t' }; public static T ReadToken(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(); string s = reader.ReadToken(); 

[编辑]正如问题评论中所要求的,这是上面的实例包装器版本,它使用分隔符和CultureInfo参数化:

 public class TextTokenizer { private TextReader reader; private Predicate isDelim; private CultureInfo cultureInfo; public TextTokenizer(TextReader reader, Predicate 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() { 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(); string s = tokenizer.ReadToken(); 

你检查过BinaryReader类了吗? 是的,它是一个文本文件,但没有什么能阻止您将其视为二进制数据,因此使用BinaryReader。 它具有您正在寻找的所有方法,但ReadLine除外。 但是,在BinaryReader之上实现该方法并不困难。

如果确实需要文本文件(即UTF-8或ASCII编码),那么二进制编写器将无法工作。

您可以使用TextReader ,但与BinaryReaderTextWriter不同,它不支持除Line和char之外的任何类型。 您必须定义允许的分隔符并自行解析Line基础数据。

System.IO.BinaryReader类是您所需要的。

ReadLine方法的实现示例:

 public static class Extensions { public static String ReadLine(this BinaryReader binaryReader) { var bytes = new List(); 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); } } } 

您可以使用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 }