[英]Reading a text file word by word
我有一個文本文件,只包含小寫字母,除空格外沒有標點符號。 我想知道通過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
,您可能希望使用該類。 現在, StreamReader
和StringReader
共享一個抽象基類TextReader
,這意味着如果您針對TextReader
進行編碼,那么您可以充分利用這兩個世界。
TextReader
的公共接口確實會支持你的示例代碼,所以我認為這是一個合理的起點。 你只需要修復一個明顯的錯誤:沒有檢查Read
returns -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;
所有在一行中,你去(假設ASCII,也許不是2GB文件):
var file = File.ReadAllText(@"C:\myfile.txt", Encoding.ASCII).Split(new[] { ' ' });
這將返回一個字符串數組,您可以迭代它並執行您需要的任何操作。
我根據您提到的文件創建了一個簡單的控制台程序,它應該很容易運行和檢查。 請查找隨附的代碼。 希望這可以幫助
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();
}
}
此代碼將根據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();
這是分割你的單詞的方法,當它們被空格或超過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<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和許多其他問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.