Trouble with file paths in C# (home - c#

I'm trying to test this Program using a test.txt file in my Documents folder. I'm having trouble getting the paths right. can some one give me some ideas? its a homework assignment and I'm almost done with it!!
using System;
using System.IO;
class Program
{
// declare constants to use in wind chill factor equation - no magic numbers
const double EQUATION_NUMBER_ONE = 35.74;
const double EQUATION_NUMBER_TWO = 0.6215;
const double EQUATION_NUMBER_THREE = 35.75;
const double EQUATION_NUMBER_FOUR = 0.4275;
const double EQUATION_EXPONENT = 0.16;
const int DEGREE_SYMBOL = 176;
static void Main()
{
// declare some variables for the main method
string fileName = "";
string line = "";
double t = 0.0;
double v = 0.0;
double wchillf = 0.0;
char degreeSymbol = (char)DEGREE_SYMBOL;
string environment = System.Environment.GetFolderPath
(System.Environment.SpecialFolder.Personal) + "c:\\";
// Give student Info and ask user for a file name.
// we will read this file and use the info for our input.
Console.WriteLine("Wind Chill Calculator Braught to you by Teancum");
Console.WriteLine("for CS 1400 01X");
Console.WriteLine("11/11/2012");
Console.WriteLine("Project 8");
Console.Write("Please enter the file name in your My Documents folder: ");
fileName = Console.ReadLine();
string path = environment + fileName;
//we will create a new instance of the StreamReader class
//as well find the file in the documents folder
//this will read the Info and orginise it.
StreamReader windChillinfo = new StreamReader(path);
// start the do loop to keep readding the file untill there is no more information
do
{
// read in a line and save it as a string variable
line = windChillinfo.ReadLine();
//this if is to make sure there is no invalid info for example if the file is empty.
if (line != null)
{
string[] values = line.Split();
t = double.Parse(values[0]);
v = double.Parse(values[1]);
//here we call the windchillmagic Method
wchillf = WindChillMagic(t, v);
//here will be the Results of the windchillmagic method
Console.WriteLine("\nFor a temperature {0:f2} F{1}", t, degreeSymbol);
Console.WriteLine("\nand a wind speed of {0:f2}mph", v);
Console.WriteLine("\nThe wind chill factor would be = {0:f2}{1}\n", wchillf, degreeSymbol);
}
} while (line != null);
windChillinfo.Close();
Console.WriteLine("\nThank you for and keep Warm! Press enter to EXIT");
Console.ReadLine();
}//End Main()
static double WindChillMagic(double t, double v)
{
double wci = 0.0;
wci = EQUATION_NUMBER_ONE + (EQUATION_NUMBER_TWO * t) - (EQUATION_NUMBER_THREE * (Math.Pow(v, EQUATION_EXPONENT))) + (EQUATION_NUMBER_FOUR * t * (Math.Pow(v, EQUATION_EXPONENT)));
return wci;
}
}//End class Program

How about you do something along the lines of following:
String path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "filename.txt");
using (StreamWriter sw = new StreamWriter(path, false))
{
sw.WriteLine("Hello, file.");
}
This worked for me - now I have the file "filename.txt" in my Documents folder, with text "Hello, file." inside.
Your version doesn't work as you're doing this:
string environment = System.Environment.GetFolderPath
(System.Environment.SpecialFolder.Personal) + "c:\\";
This means, if your personal folder was "C:\Users\Username\Documents", the environment string will now contain the value `C:\Users\Username\Documentsc:\", and after you combine it into the path with
fileName = Console.ReadLine();
string path = environment + fileName;
if you entered "test.txt", the path will now contain C:\Users\Username\Documentsc:\test.txt. You should use a debugger to find these kinds of errors.

This looks backwards:
System.Environment.GetFolderPath
(System.Environment.SpecialFolder.Personal) + "c:\\";
If GetFolderPath returns "SomeFolder\SomeOtherFolder" then what you produced is "SomeFolder\SomeOtherFolderc:\"
If you put a breakpoint here and stepped pass the line and then mouse over the environment variable, you'd see this problem.
1) It is backwards.
2) You should probably use Path.Combine instead.
string path = environment + fileName;
Should probably use Path.Combine instead so a slash is added between. What if environment doesn't end in a slash? Then you'd get "C:\SomeFolder\SomeOtherFoldersomeUsersFilename"

Related

C#: System.IO.Exception. Why can the process not access the file? How do I allow the StreamWriter to access the file after it gets created?

using System;
using System.IO;
namespace File_Dumping_Script
{
class Program
{
static void Main(string[] args)
{
Random rn = new Random();
string fileName = Convert.ToString(rn.Next(1000));
string path = ("C:\\Users\\taylo\\OneDrive\\Desktop\\FileTesting\\" + fileName);
if (File.Exists(path))
{
fileName = Convert.ToString(rn.Next(1000));
path = ("C:\\Users\\taylo\\OneDrive\\Desktop\\FileTesting\\" + fileName + ".txt");
}
File.CreateText(path);
StreamWriter sw = new StreamWriter(path);
Console.Write("Please enter a seed for the random numbers: ");
int seed = Convert.ToInt32(Console.ReadLine());
int written = 0;
while (written != seed-1)
{
written = rn.Next(seed);
sw.Write(" "+written);
Console.WriteLine(written);
}
sw.Write("\n Process ended.");
Console.WriteLine("Process complete.");
Console.ReadLine();
}
}
}
I want this program to create a file with a random number for a name, and then write a bunch of random numbers to that file. I am currently facing a problem that the File.CreateText(); is using the path, which means that the StreamWriter cannot create an object based off that path. Is there any way I can stop the File.CreateText(); from using the file so the StreamWriter can access it instead?
Also, as a secondary, less important, problem, the files created are not text files, and the way I have tried to fix that with the path = ("C:\\Users\\taylo\\OneDrive\\Desktop\\FileTesting\\" + fileName); doesn't make it a text file and nor does the File.CreateText(); How do I make it a text file instead of a 'file'?
Thank you in advance,
Taylor

Get one period only before a file extension

I am trying to make a small program to read a URLs from a DB and attach them to SAP B1 Deliveries.
Example source URL :
http://xxxx/xx/xxx/xxx/xxx/x/xxxx.pdf
Code:
oAttDelv.Lines.SourcePath = Path.GetDirectoryName(row.AttachURL);
oAttDelv.Lines.FileName = Path.GetFileNameWithoutExtension(row.AttachURL);
oAttDelv.Lines.FileExtension = Path.GetExtension(row.AttachURL);
int iErr = oAttDelv.Add();
int AttEntry = 0;
int temp_int = lErrorCode;
string temp_string = sErrorMsg;
oCompany.GetLastError(out temp_int, out temp_string);
The error shown in temp_string is as in the image. How do I resolve the two periods before pdf and get just one?
Errors:
temp_int = -5002
temp_string = "Source file does not exist , 'http:\\*****************\\jspui\\bitstream\\123456789\\2444\\1\\500393..pdf'"
Try this:
var temp_string = #"Source file does not exist , 'http:\*****************\jspui\bitstream\123456789\2444\1\500393..pdf'";
var file_name = temp_string.Substring(temp_string.LastIndexOf(#"\") + 1).Replace("..", ".");

Having trouble understanding reading text files in C#

So i'm in my 1st year of college, C# in Visual Studio is one of six modules.
Basically my problem is, i need to read in a value that's in a .txt file and calculate commission from that value.
The .txt file consists of:
1,Pat Ryan,280
2,Mary Smith,300
3,Tom Lynch,20
The 3rd value on each line is what i need to calculate the commission but i can't wrap my head around getting that value since you can't just pick out a value with the code we are currently using, you need to go through each line to get to the next.
This is what i've done so far. I tried doing the calculations this way:
if (columns [0] < 1000) {commission = column[0] * .05}
But get an error:
"Operator '<' cannot be applied to operands of type 'string[]' and 'int'"
Any help would be greatly appreciated!
static void salesReport()
{
string path = "sales.txt";
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
StreamReader salesReport = new StreamReader(fs);
string inputText = salesReport.ReadLine();
Console.WriteLine("{0,-15}{1,-30}{2,-20}\n", "Number","Name","Sales");
while (inputText != null)
{
string[] columns = new string [3];
columns = inputText.Split(',');
Console.WriteLine("{0,-15}{1,-30}{2,-10}\n", columns[0], columns[1], columns[2]);
inputText = salesReport.ReadLine();
}
}
You cannot perform a comparison operation between a string and int as specified in your error. You will need to cast the value you get from the text file to int and then do a comparison.
if (Convert.ToInt32(columns[2]) < 1000)
{
commission = Convert.ToInt32(columns[2]) / .05;
}
Looks like you want the 3rd column, I have changed the index to 2.
here is a quick example of trying to parse a file and do what you want. This has a lot of bad practices, such has the way I am concatenating the output string, but you should get the idea.
static void Main(string[] args)
{
using (StreamReader reader = new StreamReader(#"C:\Path\To\File.txt"))
{
string line;
while ((line = reader.ReadLine()) != null)
{
string[] stuff = line.Split(',');
int id = Convert.ToInt32(stuff[0]);
string name = stuff[1];
int val = Convert.ToInt32(stuff[2]);
double commission = (double)val * 0.05;
Console.WriteLine(name + "'s Commission: " + commission.ToString());
}
}
}
Your issue is that you are not evaluating an integer. You are attempting to apply your comparison operator to the string representation after the split operation.
I added a method safeToInt which will prevent pesky exceptions if the string is not an int. Of course, if you want to be aware of those errors, you should just use Int32.TryParse directly and evaluate the boolean result.
I did not change your code to use the method I added for you :-) You should be able to figure that out.
static void salesReport() {
string path = "sales.txt";
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
StreamReader salesReport = new StreamReader(fs);
string inputText = salesReport.ReadLine();
Console.WriteLine("{0,-15}{1,-30}{2,-20}\n", "Number","Name","Sales");
while (inputText != null) {
string[] columns = new string [3];
columns = inputText.Split(',');
Console.WriteLine("{0,-15}{1,-30}{2,-10}\n", columns[0], columns[1], columns[2]);
inputText = salesReport.ReadLine();
}
}
static int safeToInt(string input, int defaultValue = 0){
int result = 0;
if(Int32.TryParse(input, out result)){
return result;
}
return defaultValue;
}
Try this
if (int.Parse(columns[0]) < 1000) {commission = int.Parse(columns[0]) * .05}​

c# service renaming files!

I have a windows service , that takes files with metadata(FIDEF) and corresponding video file and , translates the XML(FIDEF) using XSLT .
I get the file directory listing for FIDEF's and if a video file of the same name exists it translates it. That works ok , but it is on a timer to search every minute. I am trying to handle situations where the same file name enters the input directory but is already in the output directory. I just have it changing the output name to (copy) thus if another file enters i should get (copy)(copy).mov but the service won't start with filenames of the same directory already in the output , it works once and then does not seem to pick up any new files.
Any Help would be great as I have tried a few things with no good results. I believe its the renaming methods, but I've put most of the code up in case its a clean up issue or something else.
(forgive some of the names just trying different things).
private void getFileList()
{
//Get FILE LIST FROM Directory
try
{
// Process Each String/File In Directory
string result;
//string filename;
filepaths = null;
filepaths = Directory.GetFiles(path, Filetype);
foreach (string s in filepaths)
{
for (int i = 0; i < filepaths.Length; i++)
{
//Result Returns Video Name
result = Path.GetFileNameWithoutExtension(filepaths[i]);
FileInfo f = new FileInfo(filepaths[i]);
PreformTranslation(f, outputPath + result , result);
}
}
}
catch (Exception e)
{
EventLog.WriteEntry("Error " + e);
}
}
private void MoveVideoFiles(String Input, String Output)
{
File.Move(Input, Output);
}
private string GetUniqueName(string name)
{
//Original Filename
String ValidName = name;
//remove FIDEF from filename
String Justname1 = Path.GetFileNameWithoutExtension(name);
//get .mov extension
String Extension2 = Path.GetExtension(Justname1);
//get filename with NO extensions
String Justname = Path.GetFileNameWithoutExtension(Justname1);
//get .Fidef
String Extension = Path.GetExtension(name);
int cnt = 0;
//string[] FileName = Justname.Split('(');
//string Name = FileName[0];
while (File.Exists(ValidName)==true)
{
ValidName = outputPath + Justname + "(Copy)" + Extension2 + Extension;
cnt++;
}
return ValidName;
}
private string getMovFile(string name)
{
String ValidName = name;
String Ext = Path.GetExtension(name);
String JustName = Path.GetFileNameWithoutExtension(name);
while(File.Exists(ValidName))
{
ValidName = outputPath + JustName + "(Copy)" + Ext;
}
return ValidName;
}
//Preforms the translation requires XSL & FIDEF name.
private void PreformTranslation(FileInfo FileName, String OutputFileName , String result)
{
string FidefName = OutputFileName + ".FIDEF";
String CopyName;
String copyVidName = outputPath + result;
XslCompiledTransform myXslTransform;
myXslTransform = new XslCompiledTransform();
try
{
myXslTransform.Load(XSLname);
}
catch
{
EventLog.WriteEntry("Error in loading XSL");
}
try
{ //only process FIDEF's with corresponding Video file
if (AllFidef == "no")
{
//Check if video exists if yes,
if (File.Exists(path + result))
{
//Check for FIDEF File Already Existing in the Output Directory.
if (File.Exists(FidefName))
{
//Get unique name
CopyName = GetUniqueName(FidefName);
copyVidName= getMovFile(copyVidName);
//Translate and create new FIDEF.
//double checking the file is here
if (File.Exists(outputPath + result))
{
myXslTransform.Transform(FileName.ToString(), CopyName);
File.Delete(FileName.ToString());
MoveVideoFiles(path + result, copyVidName);
}
////Move Video file with Corresponding Name.
}
else
{ //If no duplicate file exsists in Directory just move.
myXslTransform.Transform(FileName.ToString(), OutputFileName + ".FIDEF");
MoveVideoFiles(path + result, outputPath + result);
}
}
}
else
{
//Must have FIDEF extension
//Processes All FIDEFS and moves any video files if found.
myXslTransform.Transform(FileName.ToString(), OutputFileName + ".FIDEF");
if (File.Exists(path + result))
{
MoveVideoFiles(path + result, outputPath + result);
}
}
}
catch (Exception e)
{
EventLog.WriteEntry("Error Transforming " + "FILENAME = " + FileName.ToString()
+ " OUTPUT_FILENAME = " + OutputFileName + "\r\n" +"\r\n"+ e);
}
}
There is a lot wrong with your code. getFileList has the unneeded inner for loop for starters. Get rid of it. Your foreach loop has s, which can replace filepaths[i] from your for loop. Also, don't do outputPath + result to make file paths. Use Path.Combine(outputPath, result) instead, since Path.Combine handles directory characters for you. Also, you need to come up with a better name for getFileList, since that is not what the method does at all. Do not make your method names liars.
I would simply get rid of MoveVideoFiles. The compiler just might too.
GetUniqueName only works if your file name is of the form name.mov.fidef, which I'm assuming it is. You really need better variable names though, otherwise it will be a maintenance nightware later on. I would get rid of the == true in the while loop condition, but that is optional. The assignment inside the while is why your files get overwritten. You always generate the same name (something(Copy).mov.fidef), and as far as I can see, if the file exists, I think you blow the stack looping forever. You need to fix that loop to generate a new name (and don't forget Path.Combine). Maybe something like this (note this is untested):
int copyCount = 0;
while (File.Exists(ValidName))
{
const string CopyName = "(Copy)";
string copyString = copyCount == 0 ? CopyName : (CopyName + "(" + copyCount + ")");
string tempName = Justname + copyString + Extension2 + Extension;
ValidName = Path.Combine(outputPath, tempName);
copyCount++;
}
This generates something(Copy).mov.fidef for the first copy, something(Copy)(2).mov.fidef for the second, and so on. Maybe not what you want, but you can make adjustments.
At this point you have a lot to do. getMovFile looks as though it could use work in the same manner as GetUniqueName. You'll figure it out. Good luck.

Extracting text from a file where date -time is the index

I have got around 800 files of maximum 55KB-100KB each where the data is in this format
Date,Time,Float1,Float2,Float3,Float4,Integer
Date is in DD/MM/YYYY format and Time is in the format of HH:MM
Here the date ranges from say 1st May to 1June and each day, the Time varies from 09:00 to 15:30.
I want to run a program so that, for each file, it extracts the data pertaining to a particular given date and writes to a file.
I am trying to get around, to form a to do a search and extract operation. I dont know, how to do it, would like to have some idea.
I have written the code below:
static void Main(string[] args)
{
string destpath = Directory.GetCurrentDirectory();
destpath += "\\DIR";
DirectoryInfo Dest = Directory.CreateDirectory(destpath);
DirectoryInfo Source = new DirectoryInfo(Directory.GetCurrentDirectory() + "\\IEOD");
FileInfo[] fiArr = Source.GetFiles("*.csv");
Console.WriteLine("Search Date:");
string srchdate = Console.ReadLine();
String FileNewLine;
String FileNewdt;
FileInfo r;
foreach (FileInfo f in fiArr)
{
r = new FileInfo(destpath + "\\" + f.Name);
r.Create();
StreamWriter Sw = r.AppendText();
StreamReader Sr = new StreamReader(f.FullName);
while (Sr.Peek() >= 0)
{
FileNewLine = Sr.ReadLine();
FileNewdt = FileNewLine.Substring(0,10);
if (String.Compare(FileNewdt, srchdate, true) == 0)
{
//write it to a file;
Console.WriteLine(FileNewLine);
}
}
}
Console.ReadKey();
}
As of now, it should write into the Console. The writing with the help of StreamWriter will be done later, but I am facing a runtime error. It says, " 'C:\Documents and Settings\Soham Das\Desktop\Test\DIR\ABAN.csv' because it is being used by another process."
Here ABAN is a newly created file, by the code. The problem is faced at StreamWriter Sw = r.AppendText()
Help appreciated.
Thanks
Soham
Now that you have edited the question to show that the delimiter is actually a comma instead of a slash (which would have conflicted with the date format) this becomes a lot easier. I've re-posted the answer from last night below.
// This would come from Stream.ReadLine() or something
string line = "02/06/2010,10:05,1.0,2.0,3.0,4.0,5";
string[] parts = line.Split(',');
DateTime date = DateTime.ParseExact(parts[0], "dd/MM/yyyy", null);
TimeSpan time = TimeSpan.Parse(parts[1]);
date = date.Add(time); // adds the time to the date
float float1 = Single.Parse(parts[2]);
float float2 = Single.Parse(parts[3]);
float float3 = Single.Parse(parts[4]);
float float4 = Single.Parse(parts[5]);
int integer = Int32.Parse(parts[6]);
Console.WriteLine("Date: {0:d}", date);
Console.WriteLine("Time: {0:t}", date);
Console.WriteLine("Float1: {0}", float1);
Console.WriteLine("Float2: {0}", float2);
Console.WriteLine("Float3: {0}", float3);
Console.WriteLine("Float4: {0}", float4);
Console.WriteLine("Integer: {0}", integer);
Obviously you can make it more resilient by adding error handling, using TryParse, etc. But this should give you a basic idea of how to manipulate strings in .NET.
So 800 files with around 100KB sums up to 80 KBytes. So why don't built up a little class like
public class Entry
{
public DateTime Date {get; set;}
public float Float1 {get; set;}
public int Integer1 {get; set;}
public Entry(string values)
{
//ToDo: Parse single line into properties
// e.g. use String.Split, RegEx, etc.
}
}
Also you should take care about implementing GetHashCode() and Equals() (there is a good explanation in the book Essential C#). And you should add the interface IComparable to that class which just makes somethine like
public int CompareTo(Entry rhs)
{
return this.Date.CompareTo(rhs.Date);
}
If you got this you can easily do the following:
var allEntries = new SortedList<Entry>();
string currentLine = null;
using (var streamReader = new StreamReader("C:\\MyFile.txt"))
while ((currentLine = streamReader.ReadLine()) != null)
{
try
{
var entry = new Entry(currentLine);
allEntries.Add(entry);
}
catch (Exception ex)
{
//Do whatever you like
//maybe just
continue;
//or
throw;
}
}
So what's missing is to read in all the files (instead of a single one). But this can be done by another loop on Directory.GetFiles() which maybe itself is looped through a Directory.GetDirectories().
After reading all the files into your List you can do whatever LINQ query comes to your mind.

Categories