我有一个文本文件,只包含小写字母,除空格外没有标点符号。我想知道通过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循环中直到文件结束。这种方法是否有意义,或者有更好的方法来实现这一目标吗?
答案 0 :(得分:17)
有一种更好的方法:string.Split()
:如果你读完整个字符串,C#可以在每个空间自动拆分它:
string[] words = reader.ReadToEnd().Split(' ');
words
数组现在包含文件中的所有单词,您可以随意使用它们。
此外,您可能需要调查File.ReadAllText
命名空间中的System.IO
方法 - 它可能会让您的文章导入文本变得更加轻松。
编辑:我想这假设您的文件不是很大;只要整个事物可以合理地读入内存,这将最容易。如果你有数千兆字节的数据要读,你可能会想回避这一点。我建议尽可能使用这种方法:它可以更好地利用您拥有的框架。
答案 1 :(得分:6)
如果您对即使在非常大的文件上的良好性能感兴趣,也应该查看新的(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方法从a创建内存映射文件 指定的路径或磁盘上现有文件的FileStream。变化 在取消映射文件时会自动传播到磁盘。
CreateNew方法创建未映射的内存映射文件 到磁盘上的现有文件;并适合创建共享 进程间通信(IPC)的内存。
内存映射文件与名称相关联。
您可以创建内存映射文件的多个视图,包括 文件部分的视图。您可以将文件的相同部分映射到 多个地址来创建并发内存。对于两个视图 保持并发,它们必须从相同的内存映射创建 文件。使用两个视图创建同一文件的两个文件映射 不提供并发性。
答案 2 :(得分:3)
首先:StringReader
从已经在内存中的字符串中读取。这意味着您必须完整地加载输入文件才能从中读取,这种方法一次性读取几个字符的目的;如果输入非常大,它也可能是不可取的,甚至是不可能的。
从文本 stream (这是对数据源的抽象)中读取的类是StreamReader
,您可能希望使用该类。现在StreamReader
和StringReader
共享一个抽象基类TextReader
,这意味着如果您针对TextReader
进行编码,那么您可以充分利用这两个世界。
TextReader
的公共接口确实会支持你的示例代码,所以我认为这是一个合理的起点。您只需修复一个明显的错误:没有检查Read
返回-1(表示可用数据的结束)。
答案 3 :(得分:1)
所有在一行中,你去(假设ASCII,也许不是2gb文件):
var file = File.ReadAllText(@"C:\myfile.txt", Encoding.ASCII).Split(new[] { ' ' });
这将返回一个字符串数组,您可以迭代它并执行您需要的任何操作。
答案 4 :(得分:1)
如果你想在不拆分字符串的情况下阅读它 - 例如行太长,所以你可能会遇到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;
答案 5 :(得分:0)
这是将你的单词分开的方法,当它们被空格或超过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);
}
答案 6 :(得分:0)
我会做这样的事情:
IEnumerable<string> 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和许多其他问题。
答案 7 :(得分:0)
我根据您提到的文件创建了一个简单的控制台程序,它应该很容易运行和检查。请查找随附的代码。希望这有帮助
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<string> finalResultarray1File = new List<string>();
List<string> finalResultarray2File = new List<string>();
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();
}
}
答案 8 :(得分:0)
此代码将根据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();