i'm trying to convert a DataTable to an excel-file but at the time of creation of file it gives me error: could not find part of path.
string strDirectorypath = HttpContext.Current.Server.MapPath("~/ExcelUpload/");
DateTime dtbatchtime = Convert.ToDateTime(strBatchProcesstime);
strBatchProcesstime = dtbatchtime.ToString("MM-dd-yyyy_hh_mm_ss");
string strFilename = "FailedExcel_" + strBatchProcesstime + ".csv";
string csvdownloadPath = Path.Combine(strDirectorypath, strFilename);
using (FileStream File_Stream = new FileStream(csvdownloadPath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
{
using (StreamWriter FileWriter = new StreamWriter(File_Stream))
{
FileWriter.BaseStream.Seek(0, SeekOrigin.End);
string[] columns = { "Opportunity Name", "Property Id", "Error Type", "Error Message", "Time" };//set columns here as in the Excel Sheet.
CreateColumns(FileWriter, columns);
FileWriter.WriteLine();
if (dtRecords.Rows.Count > 0)
{
for (int i = 0; i < dtRecords.Rows.Count; i++)
{
string[] values = {
dtRecords.Rows[i]["OpportunityName"].ToString(),
dtRecords.Rows[i]["PropertyId"].ToString(),
dtRecords.Rows[i]["ErrorType"].ToString(),
dtRecords.Rows[i]["ErrorMessage"].ToString(),
dtRecords.Rows[i]["TimeStamp"].ToString()
};
CreateColumns(FileWriter, values);
FileWriter.WriteLine();
}
}
}
}
If the directory does not exist, it won't be created, so you should check and create:
if (!Directory.Exists(strDirectorypath)) {
Directory.Create(strDirectorypath);
}
Expand that with degrees of checks for your own reliability/sanity.
Related
I would like to ask some tips and help on a reading/writing part of my C#.
Situation:
I have to read a CSV file; - OK
If the CSV file name starts with "Load_", I want to write on another CSV the data from line 2 to the last one;
If the CSV file name starts with "RO_", I want to write on 2 different CSVs, 1 with the line 1 to 4 and the other 4 to the last one;
What I have so far is:
public static void ProcessFile(string[] ProcessFile)
{
// Keeps track of your current position within a record
int wCurrLine = 0;
// Number of rows in the file that constitute a record
const int LINES_PER_ROW = 1;
int ctr = 0;
foreach (string filename in ProcessFile)
{
var sbText = new System.Text.StringBuilder(100000);
int stop_line = 0;
int start_line = 0;
// Used for the output name of the file
var dir = Path.GetDirectoryName(filename);
var fileName = Path.GetFileNameWithoutExtension(filename);
var ext = Path.GetExtension(filename);
var folderbefore = Path.GetFullPath(Path.Combine(dir, #"..\"));
var lineCount = File.ReadAllLines(#filename).Length;
string outputname = folderbefore + "output\\" + fileName;
using (StreamReader Reader = new StreamReader(#filename))
{
if (filename.Contains("RO_"))
{
start_line = 1;
stop_line = 5;
}
else
{
start_line = 2;
stop_line = lineCount;
}
ctr = 0;
while (!Reader.EndOfStream && ctr < stop_line)
{
// Add the text
sbText.Append(Reader.ReadLine());
// Increment our current record row counter
wCurrLine++;
// If we have read all of the rows for this record
if (wCurrLine == LINES_PER_ROW)
{
// Add a line to our buffer
sbText.AppendLine();
// And reset our record row count
wCurrLine = 0;
}
ctr++;
} // end of the while
}
int total_lenght = sbText.Length
// When all of the data has been loaded, write it to the text box in one fell swoop
using (StreamWriter Writer = new StreamWriter(dir + "\\" + "output\\" + fileName + "_out" + ext))
{
Writer.Write.(sbText.);
}
} // end of the foreach
} // end of ProcessFile
I was thinking about using the IF/ELSE: "using (StreamWriter Writer = new StreamWriter(dir + "\" + "output\" + fileName + "_out" + ext))" part. However, I am not sure how to pass, to StreamWriter, to only write from/to a specific line number.
Any Help is welcome! If I am missing some information, please, let me know (I am pretty new on stackoverflow).
Thank you.
Code is way too complicated
using System.Collections.ObjectModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication57
{
class Program
{
static void Main(string[] args)
{
}
public static void ProcessFile(string[] ProcessFile)
{
foreach (string filename in ProcessFile)
{
// Used for the output name of the file
var dir = Path.GetDirectoryName(filename);
var fileName = Path.GetFileNameWithoutExtension(filename);
var ext = Path.GetExtension(filename);
var folderbefore = Path.GetFullPath(Path.Combine(dir, #"..\"));
var lineCount = File.ReadAllLines(#filename).Length;
string outputname = folderbefore + "output\\" + fileName;
using (StreamWriter Writer = new StreamWriter(dir + "\\" + "output\\" + fileName + "_out" + ext))
{
int rowCount = 0;
using (StreamReader Reader = new StreamReader(#filename))
{
rowCount++;
string inputLine = "";
while ((inputLine = Reader.ReadLine()) != null)
{
if (filename.Contains("RO_"))
{
if (rowCount <= 4)
{
Writer.WriteLine(inputLine);
}
if (rowCount == 4) break;
}
else
{
if (rowCount >= 2)
{
Writer.WriteLine(inputLine);
}
}
} // end of the while
Writer.Flush();
}
}
} // end of the foreach
} // end of ProcessFile
}
}
You can use LINQ to Take and Skip lines.
public abstract class CsvProcessor
{
private readonly IEnumerable<string> processFiles;
public CsvProcessor(IEnumerable<string> processFiles)
{
this.processFiles = processFiles;
}
protected virtual IEnumerable<string> GetAllLinesFromFile(string fileName)
{
using(var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
using(var reader = new StreamReader(stream))
{
var line = String.Empty;
while((line = reader.ReadLine()) != null)
{
yield return line;
}
}
}
protected virtual void ProcessFiles()
{
var sb1 = new StringBuilder();
var sb2 = new StringBuilder();
foreach(var file in this.processFiles)
{
var fileName = Path.GetFileNameWithoutExtension(file);
var lines = GetAllLinesFromFile(file);
if(fileName.StartsWith("RO_", StringComparison.InvariantCultureIgnoreCase))
{
sb1.AppendLine(lines.Take(4)); //take only the first four lines
sb2.AppendLine(lines.Skip(4).TakeWhile(s => !String.IsNullOrEmpty(s))); //skip the first four lines, take everything else
}
else if(fileName.StartsWith("Load_", StringComparison.InvariantCultureIgnoreCase)
{
sb2.AppendLine(lines.Skip(1).TakeWhile(s => !String.IsNullOrEmpty(s)));
}
}
// now write your StringBuilder objects to file...
}
protected virtual void WriteFile(StringBuilder sb1, StringBuilder sb2)
{
// ... etc..
}
}
I have a csv file, and I need to add a unique ID based on the first two characters of the file. I have the following code:
using (StreamReader sr = new StreamReader(f))
{
string currentLine;
int id = 0;
while ((currentLine = sr.ReadLine()) != null)
{
string row = currentLine.ToString();
string FirstTwoCharacters = currentLine.Substring(0, 2);
if (FirstTwoCharacters == "01")
{
id = id + 1;
row += "*" + id.ToString();
using (StreamWriter files = File.AppendText(dir + newfilename))
{
files.WriteLine(row);
}
}
else
{
row += "*" + id.ToString();
using (StreamWriter files = File.AppendText(dir + newfilename))
{
files.WriteLine(row);
}
}
}
}
The csv files can be huge, 1Gb in size, around 6 million rows. Just wanted advice, if there is a quicker way to handling this, as it currently can take 3+ hours to process a file, and multiple files can be received in one go.
Instead of opening new file for appending line for each line of input file you can keep stream writer opened:
using (StreamReader sr = new StreamReader(f))
using (StreamWriter files = File.AppendText(dir + newfilename))
{
string currentLine;
int id = 0;
while ((currentLine = sr.ReadLine()) != null)
{
string firstTwoCharacters = currentLine.Substring(0, 2);
if (firstTwoCharacters == "01")
id++;
files.WriteLine(currentLine + "*" + id);
}
}
You can also use File.ReadLines to enumerate source lines:
using (StreamWriter writer = File.AppendText(dir + newfilename))
{
int id = 0;
foreach(var line in File.ReadLines(f))
{
if (line.Substring(0,2) == "01")
id++;
writer.WriteLine($"{line}*{id}");
}
}
Or even LINQ approach
int id = 0;
var newLines = from line in File.ReadLines(f)
let incrementId = line.Substring(0,2) == "01"
select $"{line}*{incrementId ? (++id) : id}";
File.WriteAllLines(dir + newfilename, newLines);
opening the (File.AppendText) inside the while loop is costly, move this to outside the while
using (StreamReader sr = new StreamReader(f))
{
string currentLine;
int id = 0;
using (StreamWriter files = File.AppendText(dir + newfilename))
{
while ((currentLine = sr.ReadLine()) != null)
{
string row = currentLine.ToString();
string FirstTwoCharacters = currentLine.Substring(0, 2);
if (FirstTwoCharacters == "01")
{
id = id + 1;
row += "*" + id.ToString();
files.WriteLine(row);
}
else
{
row += "*" + id.ToString();
files.WriteLine(row);
}
}
}
}
I have for like 40 rows on My DataTable Displayed in a DataGridView
i'm confused why my method Saves Only One Row in the TextFile :
private void SaveBtn_Click(object sender, EventArgs e)
{
String outputFile;
List<String> ListData = new List<String>();
using (SaveFileDialog sfd = new SaveFileDialog())
{
sfd.Filter = "Txt File|*.Txt";
if (sfd.ShowDialog() != DialogResult.OK)
return;
outputFile = sfd.FileName;
}
DataTable tb = pw.SavedInfo(User_info.UserID);
for (int i = 0; i < tb.Rows.Count; i++)
{
ListData.Add("Name==> " + tb.Rows[i][1].ToString() + " LastName ==> " + tb.Rows[i][2].ToString() + " Email ==> " + tb.Rows[i][3].ToString() );
}
foreach (String s in ListData)
{
using (TextWriter Tw = new StreamWriter(outputFile))
{
Tw.WriteLine(s);
}
}
}
Did i missed something ? cause it was a really long day to keep being focused
Use the same StreamWriter:
using (TextWriter Tw = new StreamWriter(outputFile))
{
foreach (String s in ListData)
{
Tw.WriteLine(s);
}
}
or use the constructor that takes a bool for "append":
foreach (String s in ListData)
{
using (TextWriter Tw = new StreamWriter(outputFile, true))
{
Tw.WriteLine(s);
}
}
File.WriteAllLines(outputFile, lisData);
Use this to write in the file. File.WriteAllLines Documentation
I have a page where I want to upload a CSV file from my computer to database on the server and I have my opentext that looks like the following
using (StreamReader sr = File.OpenText(#"c:\users\workstationUsername\FileName.csv"))
This works fine on my local machine but when I push this to the server it tries to read the server's C Drive and I want it to read the physical file location that is sitting on the desktop of the user's computer not the server, when they click browse and upload..
Thank you
below is the complete code:
if (IsPostBack)
{
// SetDefaultDates();
Boolean fileOK = false;
String dateString = DateTime.Now.ToString("MMddyyyy");
String UserName = User.Identity.Name;
String path = Server.MapPath("~/Uploads/CSVs/");
string stringpath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
String fileName = System.IO.Path.GetFileName(FileUpload1.PostedFile.FileName);
stringpath = stringpath + fileName;
String LocationToSave = path + "\\" + fileName;
if (FileUpload1.HasFile)
{
String fileExtension =
System.IO.Path.GetExtension(FileUpload1.FileName).ToLower();
String[] allowedExtensions = { ".csv" };
for (int i = 0; i < allowedExtensions.Length; i++)
{
if (fileExtension == allowedExtensions[i])
{
fileOK = true;
}
}
}
if (fileOK)
{
try
{
//FileUpload1.PostedFile.SaveAs(LocationToSave + dateString + "-" + FileUpload1.FileName);
FileUpload1.PostedFile.SaveAs(LocationToSave);
Label1.Text = "File " + FileUpload1.FileName + " uploaded!";
DataTable dt = new DataTable();
string line = null;
int i = 0;
using (StreamReader sr = File.OpenText(stringpath))
{
while ((line = sr.ReadLine()) != null)
{
string[] data = line.Split(',');
if (data.Length > 0)
{
if (i == 0)
{
foreach (var item in data)
{
dt.Columns.Add(new DataColumn());
}
i++;
}
DataRow row = dt.NewRow();
row.ItemArray = data;
dt.Rows.Add(row);
}
}
}
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["Myconnection"].ConnectionString))
{
cn.Open();
using (SqlBulkCopy copy = new SqlBulkCopy(cn))
{
copy.WriteToServer(dt);
}
}
}
catch (Exception ex)
{
Label1.Text = "File " + FileUpload1.FileName + " could not be uploaded." + ex.Message;
}
}
else
{
Label1.Text = "Cannot accept files of this type. " + FileUpload1.FileName;
}
}
SetDefaultDates();
}
If you have a FileUpload control, then instead of using (StreamReader sr = File.OpenText(#"c:\users\workstationUsername\FileName.csv")) which obvously is pointing to the server's hard drive you can do this:
(StreamReader sr = new StreamReader(fileUploadControl.FileContent))
//Do your stuff
You can't access the client's hard drive. That's a major security concern. You'll need to upload the file to your server, and read it from there.
It doesnt make sense to have a static read to the local machine, rather get user to upload it then update the database, this code is very limiting and has a high security risk. Rather create a steamreader object get the user to upload it then use the steam reader to process the csv.
I want to open a text file, append a single line to it, then close it.
You can use File.AppendAllText for that:
File.AppendAllText(#"c:\path\file.txt", "text content" + Environment.NewLine);
using (StreamWriter w = File.AppendText("myFile.txt"))
{
w.WriteLine("hello");
}
Choice one! But the first is very simple. The last maybe util for file manipulation:
//Method 1 (I like this)
File.AppendAllLines(
"FileAppendAllLines.txt",
new string[] { "line1", "line2", "line3" });
//Method 2
File.AppendAllText(
"FileAppendAllText.txt",
"line1" + Environment.NewLine +
"line2" + Environment.NewLine +
"line3" + Environment.NewLine);
//Method 3
using (StreamWriter stream = File.AppendText("FileAppendText.txt"))
{
stream.WriteLine("line1");
stream.WriteLine("line2");
stream.WriteLine("line3");
}
//Method 4
using (StreamWriter stream = new StreamWriter("StreamWriter.txt", true))
{
stream.WriteLine("line1");
stream.WriteLine("line2");
stream.WriteLine("line3");
}
//Method 5
using (StreamWriter stream = new FileInfo("FileInfo.txt").AppendText())
{
stream.WriteLine("line1");
stream.WriteLine("line2");
stream.WriteLine("line3");
}
Or you could use File.AppendAllLines(string, IEnumerable<string>)
File.AppendAllLines(#"C:\Path\file.txt", new[] { "my text content" });
Might want to check out the TextWriter class.
//Open File
TextWriter tw = new StreamWriter("file.txt");
//Write to file
tw.WriteLine("test info");
//Close File
tw.Close();
The technically best way is probably this here:
private static async Task AppendLineToFileAsync([NotNull] string path, string line)
{
if (string.IsNullOrWhiteSpace(path))
throw new ArgumentOutOfRangeException(nameof(path), path, "Was null or whitepsace.");
if (!File.Exists(path))
throw new FileNotFoundException("File not found.", nameof(path));
using (var file = File.Open(path, FileMode.Append, FileAccess.Write))
using (var writer = new StreamWriter(file))
{
await writer.WriteLineAsync(line);
await writer.FlushAsync();
}
}
File.AppendText will do it:
using (StreamWriter w = File.AppendText("textFile.txt"))
{
w.WriteLine ("-------HURRAY----------");
w.Flush();
}
//display sample reg form in notepad.txt
using (StreamWriter stream = new FileInfo("D:\\tt.txt").AppendText())//ur file location//.AppendText())
{
stream.WriteLine("Name :" + textBox1.Text);//display textbox data in notepad
stream.WriteLine("DOB : " + dateTimePicker1.Text);//display datepicker data in notepad
stream.WriteLine("DEP:" + comboBox1.SelectedItem.ToString());
stream.WriteLine("EXM :" + listBox1.SelectedItem.ToString());
}
We can use
public StreamWriter(string path, bool append);
while opening the file
string path="C:\\MyFolder\\Notes.txt"
StreamWriter writer = new StreamWriter(path, true);
First parameter is a string to hold a full file path
Second parameter is Append Mode, that in this case is made true
Writing to the file can be done with:
writer.Write(string)
or
writer.WriteLine(string)
Sample Code
private void WriteAndAppend()
{
string Path = Application.StartupPath + "\\notes.txt";
FileInfo fi = new FileInfo(Path);
StreamWriter SW;
StreamReader SR;
if (fi.Exists)
{
SR = new StreamReader(Path);
string Line = "";
while (!SR.EndOfStream) // Till the last line
{
Line = SR.ReadLine();
}
SR.Close();
int x = 0;
if (Line.Trim().Length <= 0)
{
x = 0;
}
else
{
x = Convert.ToInt32(Line.Substring(0, Line.IndexOf('.')));
}
x++;
SW = new StreamWriter(Path, true);
SW.WriteLine("-----"+string.Format("{0:dd-MMM-yyyy hh:mm:ss tt}", DateTime.Now));
SW.WriteLine(x.ToString() + "." + textBox1.Text);
}
else
{
SW = new StreamWriter(Path);
SW.WriteLine("-----" + string.Format("{0:dd-MMM-yyyy hh:mm:ss tt}", DateTime.Now));
SW.WriteLine("1." + textBox1.Text);
}
SW.Flush();
SW.Close();
}