逐字阅读文本文件

我有一个文本文件,只包含小写字母,除空格外没有标点符号。 我想知道通过char读取文件char的最佳方法,如果下一个char是空格,它表示一个单词的结尾和一个新单词的开头。 即,当每个字符被读取时,它被添加到字符串中,如果下一个字符是空格,则该字被传递给另一个方法并重置,直到读者到达文件的末尾。

我正在尝试使用StringReader执行此操作,如下所示:

public String GetNextWord(StringReader reader) { String word = ""; char c; do { c = Convert.ToChar(reader.Read()); word += c; } while (c != ' '); return word; } 

并将GetNextWord方法放在while循环中直到文件结束。 这种方法有意义还是有更好的方法来实现这一目标?

有一个更好的方法: string.Split() :如果你读取整个字符串,C#可以自动在每个空间分割它:

 string[] words = reader.ReadToEnd().Split(' '); 

words数组现在包含文件中的所有单词,您可以随意使用它们。

此外,您可能希望调查System.IO命名空间中的File.ReadAllText方法 – 它可以使文件导入文本的生活更轻松。

编辑:我想这假设您的文件不是很大; 只要整个事物可以合理地读入内存,这将最容易。 如果你有数千兆字节的数据要读,你可能会想回避这一点。 我建议尽可能使用这种方法:它可以更好地利用您拥有的框架。

如果你对即使在非常大的文件上也有良好的性能感兴趣,你应该看看新的(4.0) MemoryMappedFile -Class 。

例如:

 using (var mappedFile1 = MemoryMappedFile.CreateFromFile(filePath)) { using (Stream mmStream = mappedFile1.CreateViewStream()) { using (StreamReader sr = new StreamReader(mmStream, ASCIIEncoding.ASCII)) { while (!sr.EndOfStream) { var line = sr.ReadLine(); var lineWords = line.Split(' '); } } } } 

来自MSDN:

内存映射文件将文件的内容映射到应用程序的逻辑地址空间。 内存映射文件使程序员能够处理非常大的文件,因为可以同时管理内存,并且它们允许完全随机访问文件而无需搜索。 内存映射文件也可以跨多个进程共享。

CreateFromFile方法从指定路径或磁盘上现有文件的FileStream创建内存映射文件。 取消映射文件时,更改会自动传播到磁盘。

CreateNew方法创建一个未映射到磁盘上现有文件的内存映射文件; 适用于为进程间通信(IPC)创建共享内存。

内存映射文件与名称相关联。

您可以创建内存映射文件的多个视图,包括文件各部分的视图。 您可以将文件的同一部分映射到多个地址以创建并发内存。 要使两个视图保持并发,必须从同一个内存映射文件创建它们。 使用两个视图创建同一文件的两个文件映射不提供并发性。

首先: StringReader从已经在内存中的字符串中读取。 这意味着您必须完整地加载输入文件才能从中读取,这种方式一次性地读取​​了几个字符的目的; 如果输入非常大,它也可能是不合需要的甚至是不可能的。

从文本 (对数据源进行抽象)读取的类是StreamReader ,您可能希望使用该类。 现在, StreamReaderStringReader共享一个抽象基类TextReader ,这意味着如果您针对TextReader进行编码,那么您可以充分利用这两个世界。

TextReader的公共接口确实会支持你的示例代码,所以我认为这是一个合理的起点。 您只需修复一个明显的错误:没有检查Read returns -1(表示可用数据的结束)。

所有在一行中,你去(假设ASCII,也许不是2GB文件):

 var file = File.ReadAllText(@"C:\myfile.txt", Encoding.ASCII).Split(new[] { ' ' }); 

这将返回一个字符串数组,您可以迭代它并执行您需要的任何操作。

如果你想通过分割字符串来读取它 – 例如行太长,所以你可能会遇到OutOfMemoryException,你应该这样做(使用streamreader):

 while (sr.Peek() >= 0) { c = (char)sr.Read(); if (c.Equals(' ') || c.Equals('\t') || c.Equals('\n') || c.Equals('\r')) { break; } else word += c; } return word; 

这是将你的单词分开的方法,而它们是由空格或超过1个空格(例如两个空格)/

 StreamReader streamReader = new StreamReader(filePath); //get the file string stringWithMultipleSpaces= streamReader.ReadToEnd(); //load file to string streamReader.Close(); Regex r = new Regex(" +"); //specify delimiter (spaces) string [] words = r.Split(stringWithMultipleSpaces); //(convert string to array of words) foreach (String W in words) { MessageBox.Show(W); } 

我会做这样的事情:

 IEnumerable ReadWords(StreamReader reader) { string line; while((line = reader.ReadLine())!=null) { foreach(string word in line.Split(new [1] {' '}, StringSplitOptions.RemoveEmptyEntries)) { yield return word; } } } 

如果要使用reader.ReadAllText,它会将整个文件加载到您的内存中,这样您就可以获得OutOfMemoryException和许多其他问题。

我根据您提到的文件创建了一个简单的控制台程序,它应该很容易运行和检查。 请查找随附的代码。 希望这可以帮助

 static void Main(string[] args) { string[] input = File.ReadAllLines(@"C:\Users\achikhale\Desktop\file.txt"); string[] array1File = File.ReadAllLines(@"C:\Users\achikhale\Desktop\array1.txt"); string[] array2File = File.ReadAllLines(@"C:\Users\achikhale\Desktop\array2.txt"); List finalResultarray1File = new List(); List finalResultarray2File = new List(); foreach (string inputstring in input) { string[] wordTemps = inputstring.Split(' ');// .Split(' '); foreach (string array1Filestring in array1File) { string[] word1Temps = array1Filestring.Split(' '); var result = word1Temps.Where(y => !string.IsNullOrEmpty(y) && wordTemps.Contains(y)).ToList(); if (result.Count > 0) { finalResultarray1File.AddRange(result); } } } foreach (string inputstring in input) { string[] wordTemps = inputstring.Split(' ');// .Split(' '); foreach (string array2Filestring in array2File) { string[] word1Temps = array2Filestring.Split(' '); var result = word1Temps.Where(y => !string.IsNullOrEmpty(y) && wordTemps.Contains(y)).ToList(); if (result.Count > 0) { finalResultarray2File.AddRange(result); } } } if (finalResultarray1File.Count > 0) { Console.WriteLine("file array1.txt contians words: {0}", string.Join(";", finalResultarray1File)); } if (finalResultarray2File.Count > 0) { Console.WriteLine("file array2.txt contians words: {0}", string.Join(";", finalResultarray2File)); } Console.ReadLine(); } } 

此代码将基于Regex模式从文本文件中提取单词。 您可以尝试使用其他模式来查看最适合您的模式。

  StreamReader reader = new StreamReader(fileName); var pattern = new Regex( @"( [^\W_\d] # starting with a letter # followed by a run of either... ( [^\W_\d] | # more letters or [-'\d](?=[^\W_\d]) # ', -, or digit followed by a letter )* [^\W_\d] # and finishing with a letter )", RegexOptions.IgnorePatternWhitespace); string input = reader.ReadToEnd(); foreach (Match m in pattern.Matches(input)) Console.WriteLine("{0}", m.Groups[1].Value); reader.Close();