I have a small application that checks all of the logs in a directory named after domain usernames and generates a results file with each username and the relevant first and surname for that user.
The console is outputting the full list successfully but it seems that the StreamWriter is stopping halfway through an entry.
The number of characters it writes before stopping is consistent - to some extent. If I set the outputstring to include more characters between the two variables filename and the result from FindNameFromUsername then the character count with or without spaces changes so I've ruled that out.
Any ideas as to why the console outputs the line but the streamwriter doesn't?
Code below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading.Tasks;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using System.DirectoryServices.ActiveDirectory;
namespace Filename_Finder
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Please insert the full directory path. All filenames in the root of this folder will be logged to one file.");
string outputFilename = "results.txt";
string userPath = Console.ReadLine();
string domain = "ou=users,dc=domain,dc=local";
try
{
string outputFilepath = userPath + outputFilename;
string[] filepaths = Directory.GetFiles(userPath);
using (StreamWriter file = new StreamWriter(outputFilepath, false))
{
for (int i = 0; i < filepaths.Length; i++)
{
string filepath = filepaths[i];
char split = '.';
string filename = filepath.Remove(0, userPath.Count());
if (filename != outputFilename)
{
int extensionBegins = filename.LastIndexOf(split);
filename = filename.Remove(extensionBegins);
string outputstring = (filename + " -- " + FindNameFromUsername(filename, domain));
Console.WriteLine(outputstring);
file.WriteLine(outputstring);
}
}
Console.ReadLine();
}
}
catch (Exception e) { Console.WriteLine(e); Console.ReadLine(); }
}
public static string FindNameFromUsername(string username, string domainScope)
{
string connectionPrefix = "LDAP://" + domainScope;
DirectoryEntry entry = new DirectoryEntry(connectionPrefix);
DirectorySearcher searcher = new DirectorySearcher(entry);
string filter = "(&(objectClass=user)";
filter += "(|(sAMAccountName=" + username + ")))";
searcher.Filter = filter;
SearchResult result = searcher.FindOne();
string resultValue = string.Empty;
DirectoryEntry obj = result.GetDirectoryEntry();
resultValue = "" + obj.Properties["givenName"].Value + " " + obj.Properties["sn"].Value;
if (resultValue == " ") { resultValue = username; }
entry.Close(); entry.Dispose();
obj.Close(); obj.Dispose();
searcher.Dispose();
return resultValue;
}
}
}
Your Console.ReadLine() will pause the execution and I'm guessing that's where you are checking the content of your file.
However, the file won't be flushed and closed until the StreamWriter is being disposed. That happens at the end of the using block, i.e. after your ReadLine() statement.
Take a look at this question.
You might find useful setting your StreamWriter.AutoFlush property to true in order to get similar behavior to the corresponding Console method, like this:
using (var file = new StreamWriter(outputFilepath, false) { AutoFlush = true })
Related
I am making a program that reads a .tyd file and tries to translate all the text between the " from English to Italian.
GoToDesk translate-> "Looking for computer"
The problem is that I am still getting "Out of memory".
The code is:
using System.Collections;
using System.Net;
using MiscUtil.IO;
namespace Soft_inc
{
class MyProject
{
public static string TranslateText(string input, string languagePair)
{
string url = String.Format("http://translate.google.it/?hl=en&ie=UTF8&text={0}&langpair={1}", input, languagePair);
WebClient webClient = new WebClient();
webClient.Encoding = System.Text.Encoding.UTF8;
string result = webClient.DownloadString(url);
result = result.Substring(result.IndexOf("<span title=\"") + "<span title=\"".Length);
result = result.Substring(result.IndexOf(">") + 1);
result = result.Substring(0, result.IndexOf("</span>"));
return result.Trim();
}
public static void Main()
{
string path_file = #"H:\Games\Software.In.v11.7.62\Software.In.v11.7.62\Localization\Italiano\idk\UI.tyd";
string Ftext = System.IO.File.ReadAllText(path_file);
ArrayList ar = new ArrayList();
Console.WriteLine("This may require some time.");
foreach (string line in new LineReader(() => new StringReader(Ftext)))
{
if(line.IndexOf("\"") == -1) continue;
string text = line.Substring(line.IndexOf("\""));
text = text.Replace("\"","");
if(text.Length == 0) continue;
ar.Add(text);
}
int idk = 0;
while(true)
{
idk++;
if(idk == ar.Count) break;
string oldT = (string)ar[idk];
Ftext = Ftext.Replace(oldT, TranslateText(oldT,"en|it"));
}
System.IO.File.WriteAllText("UI.tyd",Ftext);
}
}
}
Maybe it is because the file has 2535 lines of text?
How I can fix this?
You need to use StreamReader class. It is not necessary to read all file content into RAM. Open one StreamReader and one StreamWriter. Reed file line by line and write translated data into a temporary file. When all content is translated just move temp file to needed destination. Don't forget to close source and destination handles before moving.
I have a c# script that is running as a part of a larger code. It's supposed to execute a sql script and then send the resultant .csv file through an SFTP connection.
The issue is that the query seems to be sending the data before the query is done executing. Is there a way to make sure the query is done before my program takes the next step?
Code for the SQL piece of this below.
using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
namespace SQLtoCSV
{
static class SQL
{
public static DataTable GetData(string strQuery)
{
var cmd = new SqlCommand(strQuery);
var dt = new DataTable();
var strConnString = ConfigurationManager.ConnectionStrings["RSConString"].ConnectionString;
Logger.WriteLog("Used RS connection string: {0}", strConnString);
var con = new SqlConnection(strConnString);
var sda = new SqlDataAdapter();
cmd.CommandType = CommandType.Text;
cmd.CommandTimeout = Convert.ToInt32(ConfigurationManager.AppSettings["RSTimeout"]);
cmd.Connection = con;
try
{
con.Open();
sda.SelectCommand = cmd;
sda.Fill(dt);
return dt;
}
catch (Exception ex)
{
Logger.WriteLog("SQL GetData trown exception, see next entry.");
Logger.WriteLog(ex);
return null;
}
finally
{
con.Close();
sda.Dispose();
con.Dispose();
}
}
}
}
Here is the main control flow.
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.IO;
namespace SQLtoCSV
{
class Program
{
static void Main(string[] args)
{
try
{
string sourceDirectory = ConfigurationManager.AppSettings["LocalSQLdirectory"].ToString();
List<string> txtFiles = Directory.EnumerateFiles(sourceDirectory, "*.sql", SearchOption.AllDirectories).ToList();
Logger.WriteLog("Found {0} SQL files in local dir '{1}'.", txtFiles.Count, sourceDirectory);
foreach (string currentFile in txtFiles)
{
string strSql = File.ReadAllText(currentFile);
Logger.WriteLog("Executing '{0}'...", currentFile);
var dtTable = SQL.GetData(strSql);
Logger.WriteLog("Done.");
var tmpFile = currentFile + ".tmp";
TableToCSV.ConvertDtTableToCSV(dtTable, tmpFile);
var name = Path.GetFileNameWithoutExtension(currentFile);
SFTP.upload(tmpFile, name);
File.Delete(tmpFile);
}
}
catch (Exception ex)
{
Exception exMail = null;
Logger.WriteLog("The main app trown exception, see next entry");
try
{
var msg = "CSV to SQL application thrown exception: \r\n" +
"\tSource: " + ex.Source + "\r\n" +
"\tMessage: " + ex.Message + "\r\n" +
"Stack: \r\n" + ex.StackTrace + "\r\n";
if (ex.InnerException != null)
{
msg += "Inner exception: \r\n" +
"\tSource: " + ex.InnerException.Source + "\r\n" +
"\tMessage: " + ex.InnerException.Message + "\r\n" +
"\tStack: " + ex.InnerException.StackTrace + "\r\n";
}
MailHelper.Send_Mail(msg, "SQL to CSV error");
}
catch(Exception ex2) {
exMail = ex2;
}
Logger.WriteLog(ex);
if (exMail != null)
{
Logger.WriteLog("Cannot send a mail, see next entry");
Logger.WriteLog(exMail);
}
}
}
}
}
TableToCSV section
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.Text;
using System.IO;
namespace SQLtoCSV
{
static class TableToCSV
{
public static void ConvertDtTableToCSV(DataTable dt, string filePath)
{
string tempPath = System.IO.Path.GetTempPath();
using (var sw = new StreamWriter(filePath, false, Encoding.UTF8))
{
var columnNames = dt.Columns.Cast<DataColumn>().Select(column => column.ColumnName);
sw.WriteLine(string.Join(",", columnNames));
foreach (DataRow row in dt.Rows)
{
IEnumerable<string> fields = row.ItemArray.Select(field => /*string.Concat("\"", */field.ToString()/*.Replace("\"", "\"\""), "\"")*/);
sw.WriteLine(string.Join(",", fields));
}
}
}
}
}
SFTP section
using System;
using System.Configuration;
using Renci.SshNet;
using System.IO;
namespace SQLtoCSV
{
static class SFTP
{
public static void upload(string tmpFile, string fileName)
{
try
{
var host = ConfigurationManager.AppSettings["SFTPhost"].ToString();
var port = Convert.ToInt32(ConfigurationManager.AppSettings["SFTPport"]);
var username = ConfigurationManager.AppSettings["SFTPuser"].ToString();
var password = ConfigurationManager.AppSettings["SFTPpassword"].ToString();
var workingdirectory = ConfigurationManager.AppSettings["SFTPdirectory"].ToString();
var fileExtension = ConfigurationManager.AppSettings["UploadedFileExtension"].ToString();
var timeout = Convert.ToInt32(ConfigurationManager.AppSettings["SFTPtimeout"]);
var timestamp = ConfigurationManager.AppSettings["SFTPtimestamp"].ToString();
fileName += DateTime.Now.ToString(timestamp) + ".csv";
using (var client = new SftpClient(host, port, username, password))
{
client.ConnectionInfo.Timeout = TimeSpan.FromSeconds(timeout);
client.Connect();
Logger.WriteLog("Connected to {0}", host);
client.ChangeDirectory(workingdirectory);
Logger.WriteLog("Changed directory to {0}", workingdirectory);
using (var fileStream = new FileStream(tmpFile, FileMode.Open))
{
Logger.WriteLog("Uploading {0} ({1:N0} bytes)", fileName, fileStream.Length);
// bypass Payload error large files
client.BufferSize = 4 * 1024;
client.UploadFile(fileStream, fileName);
}
}
Logger.WriteLog("The file '{0}' is uploaded");
}
catch(Exception ex)
{
Logger.WriteLog("The SFTP.upload function trown exception, see next entry");
Logger.WriteLog(ex);
throw;
}
}
private static Stream StreamFromString(string s)
{
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
}
}
Ok, the CSV portion is your issue. StreamWriter's are buffered by default so your last chunk of data isn't getting written to disk most likely. Add sw.Flush(); before you end your using statement like this:
public static void ConvertDtTableToCSV(DataTable dt, string filePath)
{
string tempPath = System.IO.Path.GetTempPath();
using (var sw = new StreamWriter(filePath, false, Encoding.UTF8))
{
var columnNames = dt.Columns.Cast<DataColumn>().Select(column => column.ColumnName);
sw.WriteLine(string.Join(",", columnNames));
foreach (DataRow row in dt.Rows)
{
IEnumerable<string> fields = row.ItemArray.Select(field => /*string.Concat("\"", */field.ToString()/*.Replace("\"", "\"\""), "\"")*/);
sw.WriteLine(string.Join(",", fields));
}
sw.Flush();
}
}
Hate to say it, but the code itself was right although missing the flush sections. That said the issue turned out to be with a configuration file, causing the data to pull from a test environment as opposed to production.
Since the result sets from the two are often mirrored it was a subtle difference to find. I guess the moral of the story here is that if you are seeing really bizarre results that don't fit in with the theoretical picture of what you are seeing, it pays to step back a bit and make sure the basics are right.
Thanks to everyone that helped out!
I have following code:
using System;
using System.Collections.Generic;
using System.IO;
using VirusTotalNET;
using VirusTotalNET.Objects;
using System.Linq;
using System.Security.Permissions;
namespace VirusTotalNETClient
{
class Program
{
private const string ScanUrl = "http://www.google.com/";
static void Main(string[] args)
{
VirusTotal virusTotal = new VirusTotal("5d8684f50946c2bdeaf5c4fd966f61f3661de808e9d7324b99788d6f4fb7ad57");
//Use HTTPS instead of HTTP
virusTotal.UseTLS = true;
//creating folder for programs reliqies and output log
string folderName = "C:\\OnlineScanner";
System.IO.Directory.CreateDirectory(folderName);
//get list of files to analyse
var paths = Traverse("C:\test");
File.WriteAllLines("C:\\OnlineScanner\\test.txt", paths);
foreach (string line in File.ReadLines("C:\\test.txt"))
{
//Define what file you want to analyse
FileInfo fileInfo = new FileInfo(line);
//Check if the file has been scanned before.
FileReport fileReport = virusTotal.GetFileReport(fileInfo);
bool hasFileBeenScannedBefore = fileReport.ResponseCode == ReportResponseCode.Present;
//If the file has been scanned before, the results are embedded inside the report.
if (hasFileBeenScannedBefore)
{
int detekce = fileReport.Positives;
if (detekce >= 1)
{
using (var writer = new StreamWriter("C:\\OnlineScanner\\OnlineScannerLog.txt"))
{
writer.WriteLine(line);
writer.WriteLine("URL to test: " + fileReport.Permalink);
writer.WriteLine("Detect ratio: " + fileReport.Positives + "/54");
writer.WriteLine("Message: " + fileReport.VerboseMsg);
writer.WriteLine();
writer.WriteLine();
}
}
System.Threading.Thread.Sleep(16000);
}
else
{
ScanResult fileResult = virusTotal.ScanFile(fileInfo);
int detekce = fileReport.Positives;
if (detekce >= 1)
{
using (var writer = new StreamWriter("C:\\OnlineScanner\\OnlineScannerLog.txt"))
{
writer.WriteLine(line);
writer.WriteLine("URL to test: " + fileReport.Permalink);
writer.WriteLine("Detect ratio: " + fileReport.Positives + "/54");
writer.WriteLine("Message: " + fileReport.VerboseMsg);
writer.WriteLine();
writer.WriteLine();
}
}
System.Threading.Thread.Sleep(16000);
}
}
}
private static IEnumerable<string> Traverse(string rootDirectory)
{
IEnumerable<string> files = Enumerable.Empty<string>();
IEnumerable<string> directories = Enumerable.Empty<string>();
try
{
// The test for UnauthorizedAccessException.
var permission = new FileIOPermission(FileIOPermissionAccess.PathDiscovery, rootDirectory);
permission.Demand();
files = Directory.GetFiles(rootDirectory);
directories = Directory.GetDirectories(rootDirectory);
}
catch
{
// Ignore folder (access denied).
rootDirectory = null;
}
foreach (var file in files)
{
yield return file;
}
// Recursive call for SelectMany.
var subdirectoryItems = directories.SelectMany(Traverse);
foreach (var result in subdirectoryItems)
{
yield return result;
}
}
}
}
This code run some time (arround 15secs) but then program crashs.
The error is
System.IO.IOException, process can't access to file C:\hiberfil.sys.
http://upnisito.cz/images/2016_12/319crasherrror.png
Do you have any idea how to solve it?
How would I write a log file in c#?
Currently i have a timer with this statement which ticks every 20 secs:
File.WriteAllText(filePath+"log.txt", log);
For everything that i want logged i do this:
log += "stringToBeLogged";
As you can assume the string log just grows and grows as the program runs. (I don't even know if there is a maximum chars per string?)
I assume that there must be better ways of doing this. i just thought that it would be heavy to write the whole file again and again for every time something is added to the log.
From the performance point of view your solution is not optimal. Every time you add another log entry with +=, the whole string is copied to another place in memory. I would recommend using StringBuilder instead:
StringBuilder sb = new StringBuilder();
...
sb.Append("log something");
...
// flush every 20 seconds as you do it
File.AppendAllText(filePath+"log.txt", sb.ToString());
sb.Clear();
By the way your timer event is probably executed on another thread. So you may want to use a mutex when accessing your sb object.
Another thing to consider is what happens to the log entries that were added within the last 20 seconds of the execution. You probably want to flush your string to the file right before the app exits.
create a class create a object globally and call this
using System.IO;
using System.Reflection;
public class LogWriter
{
private string m_exePath = string.Empty;
public LogWriter(string logMessage)
{
LogWrite(logMessage);
}
public void LogWrite(string logMessage)
{
m_exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
try
{
using (StreamWriter w = File.AppendText(m_exePath + "\\" + "log.txt"))
{
Log(logMessage, w);
}
}
catch (Exception ex)
{
}
}
public void Log(string logMessage, TextWriter txtWriter)
{
try
{
txtWriter.Write("\r\nLog Entry : ");
txtWriter.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
DateTime.Now.ToLongDateString());
txtWriter.WriteLine(" :");
txtWriter.WriteLine(" :{0}", logMessage);
txtWriter.WriteLine("-------------------------------");
}
catch (Exception ex)
{
}
}
}
Use File.AppendAllText instead:
File.AppendAllText(filePath + "log.txt", log);
public static void WriteLog(string strLog)
{
StreamWriter log;
FileStream fileStream = null;
DirectoryInfo logDirInfo = null;
FileInfo logFileInfo;
string logFilePath = "C:\\Logs\\";
logFilePath = logFilePath + "Log-" + System.DateTime.Today.ToString("MM-dd-yyyy") + "." + "txt";
logFileInfo = new FileInfo(logFilePath);
logDirInfo = new DirectoryInfo(logFileInfo.DirectoryName);
if (!logDirInfo.Exists) logDirInfo.Create();
if (!logFileInfo.Exists)
{
fileStream = logFileInfo.Create();
}
else
{
fileStream = new FileStream(logFilePath, FileMode.Append);
}
log = new StreamWriter(fileStream);
log.WriteLine(strLog);
log.Close();
}
Refer Link:
blogspot.in
as posted by #randymohan, with using statements instead
public static void WriteLog(string strLog)
{
string logFilePath = #"C:\Logs\Log-" + System.DateTime.Today.ToString("MM-dd-yyyy") + "." + "txt";
FileInfo logFileInfo = new FileInfo(logFilePath);
DirectoryInfo logDirInfo = new DirectoryInfo(logFileInfo.DirectoryName);
if (!logDirInfo.Exists) logDirInfo.Create();
using (FileStream fileStream = new FileStream(logFilePath, FileMode.Append))
{
using (StreamWriter log = new StreamWriter(fileStream))
{
log.WriteLine(strLog);
}
}
}
Very convenient tool for logging is http://logging.apache.org/log4net/
You can also make something of themselves less (more) powerful. You can use http://msdn.microsoft.com/ru-ru/library/system.io.filestream (v = vs.110). Aspx
Add log to file with Static Class
public static class LogWriter
{
private static string m_exePath = string.Empty;
public static void LogWrite(string logMessage)
{
m_exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (!File.Exists(m_exePath + "\\" + "log.txt"))
File.Create(m_exePath + "\\" + "log.txt");
try
{
using (StreamWriter w = File.AppendText(m_exePath + "\\" + "log.txt"))
AppendLog(logMessage, w);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private static void AppendLog(string logMessage, TextWriter txtWriter)
{
try
{
txtWriter.Write("\r\nLog Entry : ");
txtWriter.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),DateTime.Now.ToLongDateString());
txtWriter.WriteLine(" :");
txtWriter.WriteLine(" :{0}", logMessage);
txtWriter.WriteLine("-------------------------------");
}
catch (Exception ex)
{
}
}
}
if(!File.Exists(filename)) //No File? Create
{
fs = File.Create(filename);
fs.Close();
}
if(File.ReadAllBytes().Length >= 100*1024*1024) // (100mB) File to big? Create new
{
string filenamebase = "myLogFile"; //Insert the base form of the log file, the same as the 1st filename without .log at the end
if(filename.contains("-")) //Check if older log contained -x
{
int lognumber = Int32.Parse(filename.substring(filename.lastIndexOf("-")+1, filename.Length-4); //Get old number, Can cause exception if the last digits aren't numbers
lognumber++; //Increment lognumber by 1
filename = filenamebase + "-" + lognumber + ".log"; //Override filename
}
else
{
filename = filenamebase + "-1.log"; //Override filename
}
fs = File.Create(filename);
fs.Close();
}
Refer link:
http://www.codeproject.com/Questions/163337/How-to-write-in-log-Files-in-C
This is add new string in the file
using (var file = new StreamWriter(filePath + "log.txt", true))
{
file.WriteLine(log);
file.Close();
}
There are 2 easy ways
StreamWriter - http://www.dotnetperls.com/streamwriter
Log4Net like Log4j(Java) - http://www.codeproject.com/Articles/140911/log4net-Tutorial
If your application is multithreaded then in some environments file.appendalltext could give error like file already in use and if you skip that then you could lose important logs .
For that you can use
Lock object technique with file.append.. in that case it will wait for existing process to close and the write your log
This can also save you from adding other libraries in your source
Above code will throw: Process can't access the file because it is being used by another process error because of File.Create(m_exePath + "\" + "log.txt"); if you will comment out this it will work as expected
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace SolutionLogWriter
{
public static class LogWriterClass
{
private static string m_exePath = string.Empty;
public static void LogWrite(string logMessage)
{
m_exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string fullpath = m_exePath + "\\" + "log.txt";
if (File.Exists(fullpath))
{
File.Delete(fullpath);
}
// File.Create(fullpath);
try
{
FileStream fs = new FileStream(fullpath, FileMode.OpenOrCreate);
using (StreamWriter w = new StreamWriter(fs))
AppendLog(logMessage, w);
}
catch (Exception ex)
{
AppendLog(ex.ToString());
}
}
private static void AppendLog(string logMessage, TextWriter txtWriter=null)
{
try
{
txtWriter.Write("\r\nLog Entry : ");
txtWriter.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(), DateTime.Now.ToLongDateString());
txtWriter.WriteLine(" :");
txtWriter.WriteLine(" :{0}", logMessage);
txtWriter.WriteLine("-------------------------------");
}
catch (Exception ex)
{
txtWriter.Write(ex.Message);
}
}
}
}
I would really appreciate if somebody could help me/offer advice on this.
I have a file, probably about 50000 lines long, these files are generated on a weekly basis. each line is identical in terms of type of content.
original file:
address^name^notes
but i need to perform a switch. i need to be able to switch (on each and every line) the address with the name. so after the switch has been done, the names will be first, and then addresses and then notes, like so:
result file:
name^address^notes
50,000 isn't that much these days, so simply reading in the whole file and outputting the wanted format should work fine for you:
string[] lines = File.ReadAllLines(fileName);
string newLine = string.Empty;
foreach (string line in lines)
{
string[] items = line.Split(myItemDelimiter);
newLine = string.Format("{0},{1},{2}", items[1], items[0], items[2]);
// Append to new file here...
}
How about this?
StreamWriter sw = new StreamWriter("c:\\output.txt");
StreamReader sr = new StreamReader("c:\\input.txt");
string inputLine = "";
while ((inputLine = sr.ReadLine()) != null)
{
String[] values = null;
values = inputLine.Split('^');
sw.WriteLine("{0}^{1}^{2}", values[1], values[0], values[2]);
}
sr.Close();
sw.Close();
Go go gadget REGEX!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static string Switcheroo(string input)
{
return System.Text.RegularExpressions.Regex.Replace
(input,
#"^([^^]+)\^([^^]+)\^(.+)$",
"$2^$1^$3",
System.Text.RegularExpressions.RegexOptions.Multiline);
}
static void Main(string[] args)
{
string input = "address 1^name 1^notes1\n" +
"another address^another name^more notes\n" +
"last address^last name^last set of notes";
string output = Switcheroo(input);
Console.WriteLine(output);
Console.ReadKey(true);
}
}
}