I have a method to get the folder path of a particular file:
string filePath = Path.Combine(Environment.GetFolderPath(
Environment.SpecialFolder.MyDocuments), "file.txt");
And later, I use this to read the text in the file:
StreamReader rdr = new StreamReader(filePath); // "C:\Users\<user>\Documents\file.txt"
string myString = rdr.ReadToEnd();
Trouble is, if the file doesn't exist, it throws a FileNotFoundException (obviously). I want to hopefully use an if/else to catch the error, in which the user can browse to find the file directly, but I'm not sure what to use to verify if filePath is valid or not.
For example, I can't use:
if (filePath == null)
because the top method to retrieve the string will always return a value, whether or not it is valid. How can I solve this?
While File.Exists() is appropriate as a start, please note that ignoring the exception can still lead to an error condition if the file becomes inaccessible (dropped network drive, file opened by another program, deleted, etc.) in the time between the call to File.Exists() and new StreamReader().
You can use File.Exists:-
if(File.Exists(filePath))
{
//Do something
}
else
{
}
string filePath = Path.Combine(Environment.GetFolderPath(
Environment.SpecialFolder.MyDocuments), "file.txt");
if(!File.Exists(filePath))
{
/* browse your file */
}
else
{
StreamReader rdr = new StreamReader(filePath); // "C:\Users\<user>\Documents\file.txt"
string myString = rdr.ReadToEnd();
}
Related
I am trying to create a program that checks if the following file exists and if not, create one and write name to it. But the program doesn't create a file and doesn't throw any exceptions.
string verify;
string name = textBox1.Text;
string path = Path.Combine(#"C:\assets\"+ name + ".txt");
if (!File.Exists(path))
{
File.Create(path);
File.WriteAllText(path, name);
}
else if (File.Exists(path))
{
verify = File.ReadAllText(path);
if (verify == name)
{
return;
}
}
Make sure that the folder C:\assets exists, otherwise your program will throw an exception.
File.Create(path) will create the file, but when you call File.WriteAllText(path, name) it would throw an exception because your file may still be opened. Therefore you should remove File.Create(path), File.WriteAllText(path, name); will create a file and then close it after writing to it.
I would eliminate File.Create(path); from your code and see what happens. File.WriteAllText(path, name); will Create the file for you so it is unnecessary, and you may be getting an IO exception that is being swallowed up elsewhere in your code that is throwing you off the scent.
I'm using Xamarin, and according to previous answers, this shall work:
string path = Path.Combine(Android.OS.Environment.DirectoryDownloads, "families.txt");
File.WriteAllText(path, "Write this text into a file!");
But it doesn't, I get and unhandled exception. I have set the permissions to read and write to external storage (even though this is internal).
I also tried it with this:
string content;
using (var streamReader = new StreamReader(#"file://" + path )) // with and without file://
{
content = streamReader.ReadToEnd();
}
But I got the same unhandled exception.
UPDATE: The path is the problem, since I get the else part here:
Java.IO.File file = new Java.IO.File(path);
if (file.CanRead())
testText.Text = "The file is there";
else
testText.Text = "The file is NOT there\n" + path;
Which is weird, because the path seems to be correct. The exceptions: Could not find a part of the path: /Download/families.txt
UPDATE2: On external storage, it works, with the same code... Might it be my device's problem? That would be great, cause I tested the external storage version on my friend's phone, but mine doesn't have external storage (OnePlus One), so I'm still looking for a solution (if there's any).
Finally found a solution.
var path = global::Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
var filename = Path.Combine(path.ToString(), "myfile.txt");
The path was the problem, now with a simple streamwriter it works like magic.
try
{
using (var streamWriter = new StreamWriter(filename, true))
{
streamWriter.WriteLine("I am working!");
}
}
catch { ... }
I have a rich text editor that I have created in C#. One of the features I am now trying to add is templates. I do not want the user to have to use an OpenFileDialog to navigate to the template and open the file. I would like to specify the filepath myself so that the user only has to click one button in order to open the template.
Currently, I am trying to achieve this using the following code:
private void formalLetterToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
FileStream fileStream = new FileStream(#".\templates\tmp1.rtf", FileMode.Open);
String str;
str = fileStream.ToString();
string fileContents = File.ReadAllText(filepath);
fileContents = fileStream.ToString();
try
{
if (richTextBoxPrintCtrl1.Modified == true);
{
NewFile();
}
richTextBoxPrintCtrl1.Rtf = fileContents;
}
catch (Exception exception)
{
MessageBox.Show("There was an error opening the template. " + exception, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
catch (Exception exception)
{
MessageBox.Show("There was an error opening the template. " + exception, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
However, whenever I try to open the template, I get an exception that is as follows:
System.ArgumentsException: File format is not valid.
However, I have tried to open the file using my OpenFileDialog and that works fine. Could somebody assist me in getting this working correctly?
Your problem is that you're trying to convert the file to a string using str = fileStream.ToString(); however, this converts the filestream to a string which is not the same thing.
Instead just do string fileContents = File.ReadAllText(filepath); to get all of the files contents into a string. You only need to use a FileStream/StreamReader if you're going to do some type of processing on the file.
Also, your use of the FileStream is a little off. I think what you really want is a StreamReader with something like this (example from msdn);
using (StreamReader sr = new StreamReader("TestFile.txt"))
{
string line;
// Read and display lines from the file until the end of
// the file is reached.
while ((line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
A FileStream cannot be used to read a file. It must be passed to a StreamReader in order to actually read the file and in this case there is no point in doing that because there is an overload of the constructor which takes a filepath. It's only useful if you don't know what kind of stream the reader is going to be reading.
Where you have;
FileStream fileStream = new FileStream(#".\templates\tmp1.rtf", FileMode.Open);
String str;
str = fileStream.ToString();
string fileContents = File.ReadAllText(filepath);
fileContents = fileStream.ToString();
You actually just want thins line; string fileContents = File.ReadAllText(filepath); , nothing else. There is no need for a FileStream when you're just reading all the text into a string.
You are making very heavy weather of loading RTF. Your code to read a file into a string will never work, as #evanmcdonnal explained. Did your file dialog based code that succeeded really do it like that? Remember that a file dialog is just UI that generates a file name in a string. If your code with a file dialog works, then it will work when the file dialog is replaced with a hard coded string.
I suspect that some part of your problem is that you are using a relative path. Perhaps the working directory is not what you expect it to be. You should specify the full path to the file.
In any case, to load RTF simply call the LoadFile method of the control. But I strongly recommend passing the full path to the file.
richTextBoxPrintCtrl1.LoadFile(fullPathToRtfFile);
I have an application that crunches a bunch of text files. Currently, I have code like this (snipped-together excerpt):
FileInfo info = new FileInfo(...)
if (info.Length > 0) {
string content = getFileContents(...);
// uses a StreamReader
// returns reader.ReadToEnd();
Debug.Assert(!string.IsNullOrEmpty(contents)); // FAIL
}
private string getFileContents(string filename)
{
TextReader reader = null;
string text = "";
try
{
reader = new StreamReader(filename);
text = reader.ReadToEnd();
}
catch (IOException e)
{
// File is concurrently accessed. Come back later.
text = "";
}
finally
{
if (reader != null)
{
reader.Close();
}
}
return text;
}
Why am I getting a failed assert? The FileInfo.Length attribute was already used to validate that the file is non-empty.
Edit: This appears to be a bug -- I'm catching IO exceptions and returning empty-string. But, because of the discussion around fileInfo.Length(), here's something interesting: fileInfo.Length returns 2 for an empty, only-BOM-marker text file (created in Notepad).
You might have a file which is empty apart from a byte-order mark. I think TextReader.ReadToEnd() would remove the byte-order mark, giving you an empty string.
Alternatively, the file could have been truncated between checking the length and reading it.
For diagnostic purposes, I suggest you log the file length when you get an empty string.
See that catch (IOException) block you have? That's what returns an empty string and triggers the assert even when the file is not empty.
If I remember well, a file ends with end of file, which won't be included when you call ReadToEnd.
Therefore, the file size is not 0, but it's content size is.
What's in the getFileContents method?
It may be repositioning the stream's pointer to the end of the stream before ReadToEnd() is called.
Why would the code below throw a io.system.directorynotfound exception? I can't recreate the problem myself but another user of my code does see it, any ideas why?
Thanks
try
{
//create path
string strAppData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData).ToString() + "\\MyApp\\Data\\logs";
//check path exists
if (!System.IO.File.Exists(strAppData))
{
System.IO.Directory.CreateDirectory(strAppData);
}
System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(strAppData);
int count = dir.GetFiles().Length;
if (count > 100)
{
string[] files = System.IO.Directory.GetFiles(strAppData);
foreach (string file in files)
{
System.IO.File.Delete(file);
}
}
this.fileName = fileName;
// delete the file if it exists
if (File.Exists(fileName))
{
//delete the file
File.Delete(fileName);
}
// write the data to the file
fs = File.OpenWrite(fileName);
sWriter = new StreamWriter(fs);
sWriter.WriteLine(headerText);
sWriter.Flush();
sWriter.Close();
}
catch (Exception exp)
{
throw new Exception(exp.Message);
}
Have you tried using System.IO.Directory.Exists rather than System.IO.File.Exists when checking to see if the path exists?
You're checking for the existence of a directory using System.IO.File rather than System.IO.Directory. It probably works on your machine because that directory already exists, and so the check doesn't matter.
Either way, you need to remember that the file system is volatile. Rather than checking existence, try to open the resource and handle the exception when it fails.
Check that the directory exists, not the file...
Although you're checking it, and creating it if it doesn't exist. You don't know if they have privelages to create the directory. So your Directory.CreateDirectory call may well be failing too and then sub-sequently the rest of the code will fail
http://msdn.microsoft.com/en-us/library/system.io.file.exists.aspx
"Remarks
The Exists method should not be used for path validation, this method merely checks if the file specified in path exists. Passing an invalid path to Existsl returns false. "
That is your error right there. Your validation does not ensure that the path to the file exists