This is what I did to create and write on my file:
Create_Directory = #"" + path;
Create_Name = file_name;
private void Create_File(string Create_Directory, string Create_Name )
{
string pathString = Create_Directory;
if (!System.IO.Directory.Exists(pathString)) { System.IO.Directory.CreateDirectory(pathString); }
string fileName = Create_Name + ".txt";
pathString = System.IO.Path.Combine(pathString, fileName);
if (!System.IO.File.Exists(pathString)) { System.IO.File.Create(pathString); }
///ERROR BE HERE:
System.IO.StreamWriter file = new System.IO.StreamWriter(pathString);
file.WriteLine(Some_Method(MP.Mwidth, MP.Mheight, MP.Mtype, "" ));
file.Close();
}
The problem here, which I have battled the entire day, is writing the file after I create it. So, my program creates a file just fine, then gives out an error before writing:
"An unhandled exception of type 'System.IO.IOException' occurred in mscorlib.dll"
"Additional information: The process cannot access the file 'D:\Projects\Project 15\Project 15\world\world maps\A.txt' because it is being used by another process."
Funny thing though, when I run the program again and try to create an already existing file, as you can see, it skips file creating, goes to writing and works fine, and I would really want my program to create the file and write without having to rerun it... What am I not seeing here?? :S
The problem is that File.Create returns an opened Stream, and you're never closing it. The file is "in use" (by you) at the point in time when you create your StreamWriter.
That being said, you don't need to "create" the file. StreamWriter will automatically do it for you. Just remove this line:
if (!System.IO.File.Exists(pathString)) { System.IO.File.Create(pathString); }
And everything should work as written.
Note that I would rewrite this slightly, however, to make it safer:
private void Create_File(string directory, string filenameWithoutExtension )
{
// You can just call it - it won't matter if it exists
System.IO.Directory.CreateDirectory(directory);
string fileName = filenameWithoutExtension + ".txt";
string pathString = System.IO.Path.Combine(directory, fileName);
using(System.IO.StreamWriter file = new System.IO.StreamWriter(pathString))
{
file.WriteLine(Some_Method(MP.Mwidth, MP.Mheight, MP.Mtype, "" ));
}
}
You can also just use File.WriteAllText or similar methods to avoid creating the file this way. Using the using block guarantees the file will be closed, even if Some_Method raises an exception.
You can use the File class as it wraps up a lot of the work for you
Example:
private void Create_File(string Create_Directory, string Create_Name)
{
string pathString = Create_Directory;
if (!System.IO.Directory.Exists(pathString)) { System.IO.Directory.CreateDirectory(pathString); }
pathString = System.IO.Path.Combine(pathString, Create_Name + ".txt");
File.WriteAllText(fileName, Some_Method(MP.Mwidth, MP.Mheight, MP.Mtype, ""));
}
static void Main(string[] args)
{
FileStream fs = new FileStream("D:\\niit\\deep.docx", FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(fs);
sr.BaseStream.Seek(0, SeekOrigin.Begin);
string str = sr.ReadLine();
Console.WriteLine(str);
Console.ReadLine();
}
Related
I am trying to create a console app on network version 5.0 using visual studio. The purpose is to read all the PNG files in a directory, and make a JSON file with the code:
{
"format_version": "1.16.100",
"minecraft:texture_set": {
"color": "*Filename*",
"metalness_emissive_roughness": "*Filename_mer*"
}
}
In it. And yes this is for Minecraft. The filename and the filename_mer are automatically filled in by code, but that isn't my issue.
static void Main(string[] args)
{
Console.WriteLine("Goto " + Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Packages\\Microsoft.MinecraftUWP_8wekyb3d8bbwe\\LocalState\\games\\com.mojang\\resource_packs" + " And find the resource pack you want to generate files into");
string pathname = Console.ReadLine();
#region Message
Console.WriteLine();
Console.WriteLine("Looking for folder...");
#endregion
string path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Packages\\Microsoft.MinecraftUWP_8wekyb3d8bbwe\\LocalState\\games\\com.mojang\\resource_packs\\" + pathname + "\\textures";
#region Message
Console.WriteLine();
Console.WriteLine("Folder found in");
Console.WriteLine(path);
#endregion
string[] directories = Directory.GetDirectories(path);
foreach (string paths in directories)
{
string[] files = Directory.GetFiles(paths);
foreach (string file in files)
{
string filenameWithType = file.Substring(file.LastIndexOf("\\") + 1);
string filename = filenameWithType.Substring(0, filenameWithType.LastIndexOf("."));
string thisPath = file.Substring(0, file.LastIndexOf("\\"));
if (filenameWithType.Substring(filenameWithType.LastIndexOf(".") + 1) == "png")
{
string newPath = thisPath + "\\" + filename + ".texture_set.json";
File.Create(newPath);
List<string> codeInFile = new List<string>();
codeInFile.Clear();
codeInFile.Add("{");
codeInFile.Add("\"format_version\": \"1.16.100\",");
codeInFile.Add("\"minecraft:texture_set\": {");
codeInFile.Add("\"color\": \"" + filename + "\",");
codeInFile.Add("\"metalness_emissive_roughness\": \"" + filename + "_mer\"");
codeInFile.Add("}");
codeInFile.Add("}");
TextWriter tw = new StreamWriter(newPath, false);
foreach (string line in codeInFile)
{
tw.WriteLine(line);
Console.WriteLine(line);
}
tw.Close();
string newPathtxt = thisPath + "\\" + filename + "_mer.png";
Bitmap bitmap = new Bitmap(file);
using (Bitmap b = new Bitmap(bitmap.Width, bitmap.Height))
{
using (Graphics g = Graphics.FromImage(b))
{
g.Clear(Color.Green);
}
b.Save(newPathtxt, ImageFormat.Png);
}
}
}
}
#region Message
Console.WriteLine("");
Console.WriteLine("All done, Your good to go!");
#endregion
Console.Read();
}
This is all my code, on the file. It reads a directory which you enter, looks through the textures file, and for each PNG file in there it creates a JSON file with the code specified earlier. Although when run the code gives me this error.
System.IO.IOException: 'The process cannot access the file 'C:\Users\https\AppData\Local\Packages\Microsoft.MinecraftUWP_8wekyb3d8bbwe\LocalState\games\com.mojang\resource_packs\Vanilla_Resource_Pack_1.17.10\textures\blocks\acacia_trapdoor.texture_set.json' because it is being used by another process.'
I cannot find any answers which fit my issue, I would appreciate any help.
This is a Minecraft Bedrock edition resource pack btw, not sure if that helps.
Don't do this File.Create(newPath); or rethink your problem. It looks like a typo.
In short File.Create(newPath) is creating a FileStream and discarding it, leaving the file open and with a share lock. If you are trying to pre-create the file, at least use the using statement:
using (File.Create(newPath));
or Close
File.Create(newPath).Close();
or
File.WriteAllText(newPath, String.Empty);
or
File.WriteAllBytes(newPath, Array.Empty<byte>());
If you are just trying to create or overwrite the file StreamWriter(newPath, false) is good enough.
This is what I did to create and write on my file:
Create_Directory = #"" + path;
Create_Name = file_name;
private void Create_File(string Create_Directory, string Create_Name )
{
string pathString = Create_Directory;
if (!System.IO.Directory.Exists(pathString)) { System.IO.Directory.CreateDirectory(pathString); }
string fileName = Create_Name + ".txt";
pathString = System.IO.Path.Combine(pathString, fileName);
if (!System.IO.File.Exists(pathString)) { System.IO.File.Create(pathString); }
///ERROR BE HERE:
System.IO.StreamWriter file = new System.IO.StreamWriter(pathString);
file.WriteLine(Some_Method(MP.Mwidth, MP.Mheight, MP.Mtype, "" ));
file.Close();
}
The problem here, which I have battled the entire day, is writing the file after I create it. So, my program creates a file just fine, then gives out an error before writing:
"An unhandled exception of type 'System.IO.IOException' occurred in mscorlib.dll"
"Additional information: The process cannot access the file 'D:\Projects\Project 15\Project 15\world\world maps\A.txt' because it is being used by another process."
Funny thing though, when I run the program again and try to create an already existing file, as you can see, it skips file creating, goes to writing and works fine, and I would really want my program to create the file and write without having to rerun it... What am I not seeing here?? :S
The problem is that File.Create returns an opened Stream, and you're never closing it. The file is "in use" (by you) at the point in time when you create your StreamWriter.
That being said, you don't need to "create" the file. StreamWriter will automatically do it for you. Just remove this line:
if (!System.IO.File.Exists(pathString)) { System.IO.File.Create(pathString); }
And everything should work as written.
Note that I would rewrite this slightly, however, to make it safer:
private void Create_File(string directory, string filenameWithoutExtension )
{
// You can just call it - it won't matter if it exists
System.IO.Directory.CreateDirectory(directory);
string fileName = filenameWithoutExtension + ".txt";
string pathString = System.IO.Path.Combine(directory, fileName);
using(System.IO.StreamWriter file = new System.IO.StreamWriter(pathString))
{
file.WriteLine(Some_Method(MP.Mwidth, MP.Mheight, MP.Mtype, "" ));
}
}
You can also just use File.WriteAllText or similar methods to avoid creating the file this way. Using the using block guarantees the file will be closed, even if Some_Method raises an exception.
You can use the File class as it wraps up a lot of the work for you
Example:
private void Create_File(string Create_Directory, string Create_Name)
{
string pathString = Create_Directory;
if (!System.IO.Directory.Exists(pathString)) { System.IO.Directory.CreateDirectory(pathString); }
pathString = System.IO.Path.Combine(pathString, Create_Name + ".txt");
File.WriteAllText(fileName, Some_Method(MP.Mwidth, MP.Mheight, MP.Mtype, ""));
}
static void Main(string[] args)
{
FileStream fs = new FileStream("D:\\niit\\deep.docx", FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(fs);
sr.BaseStream.Seek(0, SeekOrigin.Begin);
string str = sr.ReadLine();
Console.WriteLine(str);
Console.ReadLine();
}
My program goes through all files in a folder, reads them, and without altering their information moves them to another location under a different name. However I cannot use the File.Move method because I get the following IOException:
The process cannot access the file because it is being used by another
process.
This is how I am reading the file and adding all its lines to a List<string>:
List<string> lines = null;
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var sr = new StreamReader(fs, Encoding.Default))
{
lines = new List<string>();
while (!sr.EndOfStream)
lines.Add(sr.ReadLine());
}
And this is the function with which I move the file:
public static bool ArchiveFile(string filePath, string archiveFolderLocation)
{
if (!Directory.Exists(archiveFolderLocation))
Directory.CreateDirectory(archiveFolderLocation);
try
{
string timestamp = string.Format("{0:yyyy-MM-dd HHmmss}", DateTime.Now);
string newFileName = Path.GetFileNameWithoutExtension(filePath) + " " + timestamp;
string destination = string.Format("{0}\\{1}{2}", archiveFolderLocation, newFileName, Path.GetExtension(filePath));
File.Move(filePath, destination);
return true;
}
catch (Exception ex)
{
return false;
}
}
I thought using the using statement is supposed to garbage-collect and release the file after being used. How can I release the file so I can move it and why my file stays locked?
Solved:
Got it. Somewhere between these two calls I was opening a TextReaderobject without disposing it.
I thought using the using statement is supposed to garbage-collect and
release the file after being used. How can I release the file so I can
move it and why my file stays locked?
Not really. Using statement is nothing but :
try { var resource = new SomeResource(); }
finally { resource.Dispose(); // which is not GC.Collect(); }
It works fine so it looks like your file is opened from some other place in your code...
P.S.
By the way you can just do:
List<string> lines = File.ReadAllLines().ToList();
You could use:
string dpath = "D:\\Destination\\";
string spath = "D:\\Source";
string[] flist = Directory.GetFiles(spath);
foreach (string item in flist)
{
File.Move(item, dpath + new FileInfo(item).Name);
}
Replace D:\\Source & D:\\Destination\\ with the required source and destination paths, respectively.
I have a program that employs a simple logging process. The idea is that every day a new file gets created that corresponds with the date unless the file already exists, in which case it's just appended to. The problem is, File.Create is throwing an error every time it runs. I found a solution to the problem that says File.Create is opening a FileStream and you just need to call it with a .close(); but that solution didn't work for me, I'm still getting the IO exception saying that the file is in use by another process, which is impossible since it doesn't exist until File.Create creates it, and nothing else uses these files.
Here's the code:
public static void logResults(System.Reflection.MethodBase method, Results result, string message)
{
string date = DateTime.Now.ToString();
int index = date.IndexOf(" ");
string subString = date.Substring(0, index);
string nwDate = Regex.Replace(subString, "/", "");
logFileName = "WebsiteRegressionProduction_TestCycle." + nwDate;
string currentLogFile = logFileLocation + #"\" + logFileName;
StringBuilder sb = new StringBuilder();
if (!File.Exists(currentLogFile))
{
File.Create(currentLogFile).Close();
sb.Append("DATE-TIME\tACTION\tTEST CLASS\tTEST NAME\tTEST STATUS\tERROR MESSAGES");
sb.Append("\n");
}
else
{
string previousLogs = File.ReadAllText(currentLogFile);
sb.Append(previousLogs);
}
sb.Append(DateTime.Now.ToString());
sb.Append(" : ");
sb.Append("Text Executed: ");
sb.Append(method.ReflectedType.Name + " : ");
sb.Append(method + " : ");
sb.Append(result.ToString());
sb.Append(" : ");
sb.Append(message);
sb.Append("\n");
sb.Append("\n");
File.WriteAllText(currentLogFile, sb.ToString());
File.AppendText is probably a much better option for what you are trying to accomplish. It will create the file if it is missing and add the text to the end. If you want to add the header to the start of the file, you'll just have to do a quick manual check to see if the file exists first.
Using suggestions from the answers, I've changed my code. It doesn't throw an exception anymore when first creating the file, but I'll mark an answer as Accepted when someone can explain why File.Create was throwing an IOException saying that the file was already in use and could not be accessed.
public static void logResults(System.Reflection.MethodBase method, Results result, string message)
{
string date = DateTime.Now.ToString();
int index = date.IndexOf(" ");
string subString = date.Substring(0, index);
string nwDate = Regex.Replace(subString, "/", "");
logFileName = "WebsiteRegressionProduction_TestCycle." + nwDate;
string currentLogFile = logFileLocation + #"\" + logFileName;
if (!File.Exists(currentLogFile))
{
File.WriteAllText(currentLogFile,
"DATE-TIME\tACTION\tTEST CLASS\tTEST NAME\tTEST STATUS\tERROR MESSAGES\n\n", Encoding.ASCII);
}
var sb = new StringBuilder();
sb.Append(String.Format("{0} : Test Executed: {1} : {2} : {3}\n\n", DateTime.Now.ToString(),
method.ReflectedType.Name, method, message));
using (var stream = File.AppendText(currentLogFile))
{
stream.Write(sb.ToString());
}
}
1) Why do you read all previous content to append?
2) You can simply use log4net that do all that work for "free"
However, I suggest you to use a stream to have more control over the operation
FileStream fs = new FileStream(filePath, FileMode.Append);
byte[] data = Encoding.ASCII.GetBytes("The string you wanna append");
fs.Write(data, 0, data.Length);
fs.Flush();
fs.Close();
The FileMode.Append open the specified (filePath) in Append if exists or create it if not.
File.Create returns FileStream, so you should be using a FileStream object like so:
FileStream fs = File.Create(currentLogFile);
Then do all your read/writes with the fs object.
I am trying to remove the space at the end of line and then that line will be written in another file.
But when the program reaches to FileWriter then it gives me the following error
Process can't be accessed because it is being used by another process.
The Code is as below.
private void FrmCounter_Load(object sender, EventArgs e)
{
string[] filePaths = Directory.GetFiles(#"D:\abc", "*.txt", SearchOption.AllDirectories);
string activeDir = #"D:\dest";
System.IO.StreamWriter fw;
string result;
foreach (string file in filePaths)
{
result = Path.GetFileName(file);
System.IO.StreamReader f = new StreamReader(file);
string newFileName = result;
// Combine the new file name with the path
string newPath = System.IO.Path.Combine(activeDir, newFileName);
File.Create(newPath);
fw = new StreamWriter(newPath);
int counter = 0;
int spaceAtEnd = 0;
string line;
// Read the file and display it line by line.
while ((line = f.ReadLine()) != null)
{
if (line.EndsWith(" "))
{
spaceAtEnd++;
line = line.Substring(0, line.Length - 1);
}
fw.WriteLine(line);
fw.Flush();
counter++;
}
MessageBox.Show("File Name : " + result);
MessageBox.Show("Total Space at end : " + spaceAtEnd.ToString());
f.Close();
fw.Close();
}
}
File.Create itself returns a stream.
Use that stream to write file. Reason you are receiving this error is because Stream returned by File.Create is open and you are trying to open that file again for write.
Either close the stream returned by File.Create or better use that stream for file write or use
Stream newFile = File.Create(newPath);
fw = new StreamWriter(newFile);
Even though you solved your initial problem, if you want to write everything into a new file in the original location, you can try to read all of the data into an array and close the original StreamReader. Performance note: If your file is sufficiently large though, this option is not going to be the best for performance.
And you don't need File.Create as the StreamWriter will create a file if it doesn't exist, or overwrite it by default or if you specify the append parameter as false.
result = Path.GetFileName(file);
String[] f = File.ReadAllLines(file); // major change here...
// now f is an array containing all lines
// instead of a stream reader
using(var fw = new StreamWriter(result, false))
{
int counter = f.Length; // you aren't using counter anywhere, so I don't know if
// it is needed, but now you can just access the `Length`
// property of the array and get the length without a
// counter
int spaceAtEnd = 0;
// Read the file and display it line by line.
foreach (var item in f)
{
var line = item;
if (line.EndsWith(" "))
{
spaceAtEnd++;
line = line.Substring(0, line.Length - 1);
}
fw.WriteLine(line);
fw.Flush();
}
}
MessageBox.Show("File Name : " + result);
MessageBox.Show("Total Space at end : " + spaceAtEnd.ToString());
Also, you will not remove multiple spaces from the end of the line using this method. If you need to do that, consider replacing line = line.Substring(0, line.Length - 1); with line = line.TrimEnd(' ');
You have to close any files you are reading before you attempt to write to them in your case.
Write stream in using statement like:
using (System.IO.StreamReader f = new StreamReader(file))
{
//your code goes here
}
EDIT:
Zafar is correct, however, maybe this will clear things up.
Because File.Create returns a stream.. that stream has opened your destination file. This will make things clearer:
File.Create(newPath).Close();
Using the above line, makes it work, however, I would suggest re-writing that properly. This is just for illustrative purposes.