[英]Best approach for Cartesian product or 2 large text files
我想將 2 個大文本文件合並在一起並使用 2 個輸入文件的笛卡爾積生成新文件時遇到問題。 我確實知道代碼的外觀,但不確定用哪種語言來構建這樣的實用程序。 我有 Windows 服務器,並且熟悉 C#、Shell 腳本。
注意:File1 可以是大約 20 MB,File2 可以包含大約 6000 條記錄。 所以我想要實現的是在新文件中復制 20MB 數據 6000 次。
以下是我的文件外觀的較小示例
文件 1
Head-A-AA-AAA
Child-A1-AA1-AAA1
Child-A2-AA2-AAA2
Child-A3-AA3-AAA3
Head-B-BB-BBB
Child-B1-BB1-BBB1
Child-B2-BB2-BBB2
Child-B3-BB3-BBB3
文件 2
Store1
Store2
Store3
預期輸出文件
Store1
Head-A-AA-AAA
Child-A1-AA1-AAA1
Child-A2-AA2-AAA2
Child-A3-AA3-AAA3
Head-B-BB-BBB
Child-B1-BB1-BBB1
Child-B2-BB2-BBB2
Child-B3-BB3-BBB3
Store2
Head-A-AA-AAA
Child-A1-AA1-AAA1
Child-A2-AA2-AAA2
Child-A3-AA3-AAA3
Head-B-BB-BBB
Child-B1-BB1-BBB1
Child-B2-BB2-BBB2
Child-B3-BB3-BBB3
Store3
Head-A-AA-AAA
Child-A1-AA1-AAA1
Child-A2-AA2-AAA2
Child-A3-AA3-AAA3
Head-B-BB-BBB
Child-B1-BB1-BBB1
Child-B2-BB2-BBB2
Child-B3-BB3-BBB3
尋找帶有 Windows 服務的 C# 代碼是否有用或者我需要使用任何其他工具/實用程序/腳本的建議?
編輯:在 c# 代碼下創建。 但是生成 150 GB 的輸出文件需要幾個小時。 我正在尋找更快的方法。 我正在從文件 1 中獲取內容並為第二個文件中的每個記錄復制它
FileInfo[] fi;
List<FileInfo> TodaysFiles = new List<FileInfo>();
string PublishId;
DirectoryInfo di = new DirectoryInfo(@"\\InputPath");
fi = di.GetFiles().Where(file => file.FullName.Contains("TRANSMIT_MASS")).ToArray();
foreach (FileInfo f in fi)
{
string[] tokens = f.Name.Split('_');
if(tokens[2] == DateTime.Now.AddDays(1).ToString("MMddyyyy"))
{
PublishId = tokens[0];
string MACSFile = @"\\OutputPath\\" + PublishId + ".txt";
string path =f.FullName;
string StoreFile = di.GetFiles().Where(file => file.Name.StartsWith(PublishId) && file.Name.Contains("SUBS")).Single().FullName;
using (FileStream fs = File.Open(StoreFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (BufferedStream bs = new BufferedStream(fs))
using (StreamReader sr = new StreamReader(bs))
{
using (StreamWriter outfile = new StreamWriter(MACSFile))
{
String StoreNumber;
while ((StoreNumber = sr.ReadLine()) != null)
{
Console.WriteLine(StoreNumber);
if (StoreNumber.Length > 5)
{
using (FileStream fsProfile = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (BufferedStream bsProfile = new BufferedStream(fsProfile))
using (StreamReader srProfile = new StreamReader(bsProfile))
{
outfile.WriteLine(srProfile.ReadToEnd().TrimEnd());
}
}
}
}
}
}
}
你提到了shell腳本。 這是一個工作外殼示例:
while read line; do
echo "$line" >> Output
cat File1 >> Output
done < File2
這里File2
的行被循環並與整個File1
寫入任意輸出文件Output
。
通過將其保存在本地文件something.sh
並運行sh something.sh
輕松運行。
我們可以以內存為代價進一步優化代碼的性能。 全部重構它以使其更干凈。
文件 1:6000 行
文件 2 : 20Mb
作為文件 1,(較小的文件)只包含幾行,會將整個文件讀入內存並循環遍歷它。
foreach (string line in File.ReadAllLines(File1))
如果您還有內存容量,您也可以將整個第二個文件讀入內存
var file2 = File.ReadAllText(File2)
現在您要做的就是將所有內容附加到第三個文件中。 由於大小,我們不會將其存儲在內存中。
所以整個代碼將是
var file2 = File.ReadAllText(File2);
var destinationFile = "destination/file/path";
foreach (string line in File.ReadAllLines(File1)){
File.AppendAllText(destinationFile, line);
File.AppendAllText(destinationFile, file2);
}
進一步優化:跳過以保持代碼簡單
File.AppendAllText 被調用了兩次,因為我們不想在代碼中做 line + file2。 它將分配更多的內存。
要進一步優化,您可以使用 StringBuilder,將 file2 加載到其中。
var file2 = new StringBuilder(File.ReadAllText(File2));
並對其進行變異。 這應該可以防止對 File.AppendAllText 的 2 次調用並提供更高的性能。
很難減少 I/O 時間。 您可以嘗試使用大量讀/寫的情況(我認為它更有效,因為 I/O 操作需要分配/釋放操作系統的資源)。 因此,如果您閱讀所有內容,將結果匯總到內存中,然后寫入文件,那么它將在 I/O 上花費更少的時間。 內存操作可以達到更高的速度,因為與 IO 操作相比,RAM 和處理器操作的處理速度非常快。
PS:這里不需要緩沖流,因為文件流已經被緩沖了。 緩沖流對於網絡 IO 操作很有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.