Stream using behavior - c#

I got simple code, which basically copies file from one dir to another.
string fileName = "kur.csv";
var path = #"D:\" + fileName;
Stream stream = File.OpenRead(fileName);
using Stream s = File.Create(path); // remove "using" from this line
stream.CopyTo(s);
But if I remove "using" (from 4th line start) - code doesn't work on *.csv or *.txt files. But works on *.jpg, *.docx files.
Why it works on some and why it doesn't work on others?

If I had to write a method that copies a file, I'd do something like this:
static void CopyFile(string fileName)
{
var scourceFilePath = Path.Combine(#"D:", fileName);
var destinationFilePath = Path.Combine(#"D:", "destination", fileName);
File.Copy(scourceFilePath, destinationFilePath);
}
This works for all filetypes. You could also check if the directory exists (Directory.Exists(directoryPath)) before referencing it which prevents the program from crashing if the directory does in fact not exist.
I use Path.Combine since by using it I don't have to keep track of the backslashes used.
Every method I mentioned and used is contained in the System.IO namespace.
I hope, that's what you were looking for.

Related

Write lines in file when the file exists c#

i try to write line in file when this exists:
My code is next:
string strRuta = "C:\File.txt"
if (!Directory.Exists(strRuta))
Directory.CreateDirectory(strRuta);
string psContenido = "Hola";
if (!(File.Exists(strRuta + strNombreArchivo)))
{
swArchivo = File.CreateText(strRuta + strNombreArchivo);
}
if (!psContenido.ToLower().Contains("error"))
{
swArchivo.WriteLine(psContenido);
swArchivo.Flush();
swArchivo.Close();
swArchivo.Dispose();
File.SetCreationTime(strRuta + strNombreArchivo, DateTime.Now);
}
but when run this program i have a error in WriteLine, i donĀ“t undertand which is the reason, could you help me?
I would like to know how to write in the file(in the next line the word)
There are a couple of problems, I think. First, you're specifying what looks like a file name and creating a directory with that name (not sure if this is intentional or not). Second, you can use the static helper method AppendAllText of the File class to both create the file if it doesn't exist, and to write the contents to the end of the file. It handles all the streamwriter stuff for you, so you don't have to worry about calling close and dispose.
private static void Main(string[] args)
{
string directory = #"C:\private\temp";
string fileName = "MyFile.txt";
string filePath = Path.Combine(directory, fileName);
string fileContents = "This will be written to the end of the file\r\n";
// This will create the directory if it doesn't exist
Directory.CreateDirectory(directory);
// This will create the file if it doesn't exist, and then write the text at the end.
File.AppendAllText(filePath, fileContents);
File.SetCreationTime(filePath, DateTime.Now);
}

Enumerate zipped contents of unzipped folder

I am trying to enumerate the zipped folders that are inside an unzipped folder using Directory.GetDirectories(folderPath).
The problem I have is that it does not seem to be finding the zipped folders, when I come to iterate over the string[], it is empty.
Is Directory.GetDirectories() the wrong way to go about this and if so what method serves this purpose?
Filepath example: C:\...\...\daily\daily\{series of zipped folder}
public void CheckZippedDailyFolder(string folderPath)
{
if(folderPath.IsNullOrEmpty())
throw new Exception("Folder path required");
foreach (var folder in Directory.GetDirectories(folderPath))
{
var unzippedFolder = Compression.Unzip(folder + ".zip", folderPath);
using (TextReader reader = File.OpenText(unzippedFolder + #"\" + new DirectoryInfo(folderPath).Name))
{
var csv = new CsvReader(reader);
var field = csv.GetField(0);
Console.WriteLine(field);
}
}
}
GetDirectories is the wrong thing to use. Explorer lies to you; zip files are actually files with an extension .zip, not real directories on the file system level.
Look at:
https://msdn.microsoft.com/en-us/library/system.io.compression.ziparchive.entries%28v=vs.110%29.aspx (ZipArchive.Entries) and/or
https://msdn.microsoft.com/en-us/library/system.io.compression.zipfile%28v=vs.110%29.aspx (ZipFile) to see how to deal with them.

C# absolute path with streamReader

I have an issue with the reading a file in C#
I have two different locations for .exe (both different) and reading the same .xml file. So when I give the path like this:
TextReader textReader = new StreamReader(#"../../../TrajectoryGen/obstacleList.xml");
it is able to read from one location ( which is 3 folders behind as used in the path) but not from another location (which is only 2 folders behind)
How do I fix this problem so that it works from both folders?
First way, this relies on you knowing one of the parent folder's names.
const string FILENAME = "obstacleList.xml";
const string FOLDER = "TrajectoryGen";
string path = Path.GetFullPath(System.Reflection.Assembly.GetExecutingAssembly().Location);
do
{
path = Path.GetDirectoryName(path);
} while (!Path.GetFileName(path).Equals(FOLDER, StringComparison.OrdinalIgnoreCase));
string filepath = String.Format("{0}{1}{2}", path, Path.DirectorySeparatorChar, FILENAME);
^^ You can also use a partial path in the FILENAME like the example below incase you need to into directories once you are at your "base" folder that you know the name of.
Second way blindly continues up directories
const string FILENAME = #"TrajectoryGen\obstacleList.xml";
string path = Path.GetFullPath(System.Reflection.Assembly.GetExecutingAssembly().Location);
string filepath;
do
{
path = Path.GetDirectoryName(path);
//pump
filepath = String.Format("{0}{1}{2}", path, Path.DirectorySeparatorChar, FILENAME);
} while (!File.Exists(filepath));
Both require "using System.IO;" and both have no error handling implemented and will throw NullReferenceException if the file/folder is not found.
I purposely used the do-while loop because the definition of path will included the executable name.

Streamreader to a relative filepath

I was wondering, if anyone could tell me how to point a StreamReader to a file inside the current working directory of the program.
E.g.: say I have program Prog saved in the directory "C:\ProgDir\". I commit "\ProgDir" to a shared folder. Inside ProgDir is another directory containing files I'd like to import into Prog (e.g. "\ProgDir\TestDir\TestFile.txt") I'd like to make it so that the StreamReader could read those TestFiles, even when the path to the directory has changed;
(E.G., on my computer, the path to the Testfiles is
C:\ProgDir\TestDir\TestFile.txt
but on the other person's computer, the directory is
C:\dev_code\ProgDir\TestDir\TestFile.txt
).
How would I get a StreamReader to be ale to read from TestFile.txt on the other person's computer? (to clarify, the filenames do not change, the only change is the path ProgDir)
I tried the following:
string currentDir = Environment.CurrentDirectory;
DirectoryInfo directory = new DirectoryInfo(currentDir);
FileInfo file = new FileInfo("TestFile.txt");
string fullDirectory = directory.FullName;
string fullFile = file.FullName;
StreamReader sr = new StreamReader(#fullDirectory + fullFile);
( pulled this from : Getting path relative to the current working directory?)
But I'm getting "TestFile does not exist in the current context". Anyone have any idea as to how I should approach this?
Thank you.
Is the Folder "TestDir" always in the executable directory?
if so, try this
string dir =System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().Location);
string file = dir + #"\TestDir\TestFile.txt";
This will give you the path of the exe plus the folder inside it and the textfile
You can use the GetFullPath() method. Try this:
string filePath = System.IO.Path.GetFullPath("TestFile.txt");
StreamReader sr = new StreamReader(filePath);
A few things:
First, FileInfo.FullName gives the absolute path for the file, so you don't need to prepend the full directory path before the file in the StreamReader instance.
Second, FileInfo file = new FileInfo(TestFile.txt); should fail unless you actually have a class called TestFile with a txt property.
Finally, with almost every File method, they use relative paths already. So you SHOULD be able to use the stream reader on JUST the relative path.
Give those few things a try and let us know.
Edit: Here's what you should try:
FileInfo file = new FileInfo("TestFile.txt");
StreamReader sr = new StreamReader(fullFile.FullName);
//OR
StreamReader sr = new StreamReader("TestFile.txt");
However, one thing I noticed is that the TestFile is located in TestDir. If your executable is located in ProgDir as you're stating, then this will still fail because your relative path isn't right.
Try changing it to TestDir\TestFile.txt instead. IE: StreamReader sr = new StreamReader("TestDir\TestFile.txt");
The FileInfo constructor takes a single parameter of type string. Try putting quotes around TestFile.txt.
Change
FileInfo file = new FileInfo(TestFile.txt);
to
FileInfo file = new FileInfo("TestFile.txt");
Unless TestFile is an object with a property named txt of type string, in which case you have to create the object before trying to use it.
The easiest way would be to just use the file name (not the full path) and "TestDir" and give the StreamReader a relative path.
var relativePath = Path.Combine(".","TestDir",fileName);
using (var sr = new StreamReader(relativePath))
{
//...
}
I had a similar issue and resolved it by using this method:
StreamReader sr = File.OpenText(MapPath("~/your_path/filename.txt"))
This could be a good option if you need a more relative path to the file for working with different environments.
You can use path.combine to get the current directory to build and then combine the file path you need
new StreamReader(Path.Combine(Environment.CurrentDirectory, "storage"));
System.IO.Path.GetDirectoryName(new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath)

Create a temporary file from stream object in c#

Given a stream object which contains an xlsx file, I want to save it as a temporary file and delete it when not using the file anymore.
I thought of creating a class that implementing IDisposable and using it with the using code block in order to delete the temp file at the end.
Any idea of how to save the stream to a temp file and delete it on the end of use?
Thanks
You could use the TempFileCollection class:
using (var tempFiles = new TempFileCollection())
{
string file = tempFiles.AddExtension("xlsx");
// do something with the file here
}
What's nice about this is that even if an exception is thrown the temporary file is guaranteed to be removed thanks to the using block. By default this will generate the file into the temporary folder configured on the system but you could also specify a custom folder when invoking the TempFileCollection constructor.
You can get a temporary file name with Path.GetTempFileName(), create a FileStream to write to it and use Stream.CopyTo to copy all data from your input stream into the text file:
var stream = /* your stream */
var fileName = Path.GetTempFileName();
try
{
using (FileStream fs = File.OpenWrite(fileName))
{
stream.CopyTo(fs);
}
// Do whatever you want with the file here
}
finally
{
File.Delete(fileName);
}
Another approach here would be:
string fileName = "file.xslx";
int bufferSize = 4096;
var fileStream = System.IO.File.Create(fileName, bufferSize, System.IO.FileOptions.DeleteOnClose)
// now use that fileStream to save the xslx stream
This way the file will get removed after closing.
Edit:
If you don't need the stream to live too long (eg: only a single write operation or a single loop to write...), you can, as suggested, wrap this stream into a using block. With that you won't have to dispose it manually.
Code would be like:
string fileName = "file.xslx";
int bufferSize = 4096;
using(var fileStream = System.IO.File.Create(fileName, bufferSize, System.IO.FileOptions.DeleteOnClose))
{
// now use that fileStream to save the xslx stream
}
// Get a random temporary file name w/ path:
string tempFile = Path.GetTempFileName();
// Open a FileStream to write to the file:
using (Stream fileStream = File.OpenWrite(tempFile)) { ... }
// Delete the file when you're done:
File.Delete(tempFile);
EDIT:
Sorry, maybe it's just me, but I could have sworn that when you initially posted the question you didn't have all that detail about a class implementing IDisposable, etc... anyways, I'm not really sure what you're asking in your (edited?) question. But this question: Any idea of how to save the stream to temp file and delete it on the end of use? is pretty straight-forward. Any number of google results will come back for ".NET C# Stream to File" or such.
I just suggest for creating file use Path.GetTempFileName(). but others depends on your usage senario, for example if you want to create it in your temp creator class and use it just there, it's good to use using keyword.

Categories