StreamReader Could not find file (Because it is not being created) - c#

I am trying to create a file for the further write to and read from.
I use Directory.CreateDirectory and File.Create but neither path nor file are being created.
On the Page which part I show here below I check if File exists, and if not, I create a File. On Second Page (that I dont show here) I add new lines to the file using StreamWrite. When saved, first Page comes to focus again and lists the content of the File(only one row in this study).
Here is my code for the part in question:
public async Task ReadFileAsync()
{
string directoryName = Path.GetDirectoryName(#"C:\Users\...\DataBase\");
Task.Run(async() => Directory.CreateDirectory(directoryName));
Task.Run(async() => File.Create(directoryName + "ProductsDatabase.txt"));
//code for reading from file
string path = (directoryName + "ProductsDatabase.txt");
using (StreamReader ProductsDatabaseRead = new StreamReader(File.OpenRead(path)))
{
ProductOneTextBlock.Text = ProductsDatabaseRead.ReadLine();
}
if (ProductOneTextBlock.Text == "")
{
ProductOneTextBlock.Text = "Nothing to show";
}
}
The file and folder are not being created.
I don't get any error.
I tried also different folders on the drive in case if there was READ ONLY folder in solution folder. No difference.
Anyone could help?
(I found many threads about this problem but here I cannot resolve it with none of the solutions.
Physical file is not being created.
When I attempt to write to it (from another page) I get error that the file could not be found(because it is not there indeed).
It seems that program loses itself somewhere between
Task.Run(async() => Directory.CreateDirectory(directoryName));
Task.Run(async() => File.Create(directoryName + "ProductsDatabase.txt"));
and:
using (StreamReader ProductsDatabaseRead = new StreamReader(File.OpenRead(path)))
{
ProductOneTextBlock.Text = ProductsDatabaseRead.ReadLine();
}
, as TextBlock is not being updated even if ProductsDatabaseRead is null.
If I put
ProductOneTextBlock.Text = "Nothing to show";
a the begining of the method, TextBlock gets updated.
SO, why the
using (StreamReader ProductsDatabaseRead = new StreamReader(File.OpenRead(path)))
does not work?

You're not waiting for Task.Run to complete. Your directory creation, file creation and attempt to open a "as you think newly created file" are out of order. That's why you're probably not able to open a file (it still does not exist at this point).
Task.Run returns a task that will be completed when the work is done. You need to wait for completion.

public void ReadFile()
{
string folderPath = #"C:\Users\patri\source\repos\DietMate\";
string fileName = "ProductsDatabase.txt";
string fullPath = Path.Combine(folderPath, fileName);
//insert code to check whether file exists.
// use Exists()
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
File.Create(fullPath);
}
//if yes, follow with code below
//insert code for reading from file
using (StreamReader ProductsDatabaseRead = new StreamReader(fullPath))
{
ProductTest.Text = ProductsDatabaseRead.ReadLine();
}
}

Related

XML file from ZIP Archive is incomplete in C#

I've work with large XML Files (~1000000 lines, 34mb) that are stored in a ZIP archive. The XML file is used at runtime to store and load app settings and measurements. The gets loadeted with this function:
public static void LoadFile(string path, string name)
{
using (var file = File.OpenRead(path))
{
using (var zip = new ZipArchive(file, ZipArchiveMode.Read))
{
var foundConfigurationFile = zip.Entries.First(x => x.FullName == ConfigurationFileName);
using (var stream = new StreamReader(foundConfigurationFile.Open()))
{
var xmlSerializer = new XmlSerializer(typeof(ProjectConfiguration));
var newObject = xmlSerializer.Deserialize(stream);
CurrentConfiguration = null;
CurrentConfiguration = newObject as ProjectConfiguration;
AddRecentFiles(name, path);
}
}
}
}
This works for most of the time.
However, some files don't get read to the end and i get an error that the file contains non valid XML. I used
foundConfigurationFile.ExtractToFile();
and fount that the readed file stops at line ~800000. But this only happens inside this code. When i open the file via editor everything is there.
It looks like the zip doesnt get loaded correctly, or for that matter, completly.
Am i running in some limitations? Or is there an error in my code i don't find?
The file is saved via:
using (var file = File.OpenWrite(Path.Combine(dirInfo.ToString(), fileName.ToString()) + ".pwe"))
{
var zip = new ZipArchive(file, ZipArchiveMode.Create);
var configurationEntry = zip.CreateEntry(ConfigurationFileName, CompressionLevel.Optimal);
var stream = configurationEntry.Open();
var xmlSerializer = new XmlSerializer(typeof(ProjectConfiguration));
xmlSerializer.Serialize(stream, CurrentConfiguration);
stream.Close();
zip.Dispose();
}
Update:
The problem was the File.OpenWrite() method.
If you try to override a file with this method it will result in a mix between the old file and the new file, if the new file is shorter than the old file.
File.OpenWrite() doenst truncate the old file first as stated in the docs
In order to do it correctly it was neccesary to use the File.Create() method. Because this method truncates the old file first.

How to close an access made by unknown proccess to a file through WPF, C#?

I'm trying to access a file with my WPF project and I get an exception saying it couldn't access the file because another process is using it.
I don't see any reason because the only process which used it was syncronized and it should close the file after it used it. I tried the "client.Dispose();" below, but it didn't help.
Any advice may be a help! Thanks.
I'm trying to access "currentQr" file in local url. Here's my code:
private void BtnScanQR(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
if (openFileDialog.ShowDialog() == true)
{
currentQr= System.IO.Path.GetFullPath(openFileDialog.FileName).Replace(#"\\", #"\");
if (!bL.IsQRExist(currentQr))
{
/////// some code
}
}
}
It calls "bL.IsQRExist(currentQr)" which calls "dal" :
public bool IsQRExist(string currentQr)
{
return Dal.IsQRExist(currentQr);
}
Here's my Dal.IsQRExist function, Which calls directly to "DecodeQR" function:
public bool IsQRExist(string currentQr)
{
Product p = Tools.ConvertQRToProduct(currentQr);
if (GetProductID(p) == -1)
return false;
return true; }
And in "Tools.DecodeQR" there's the Actual access to the file:
public static string DecodeQR(string downloadUrl) //'unzip' qrCode from url and interperts its meaning
{
string imageUrl = downloadUrl;
// Install-Package ZXing.Net -Version 0.16.5
var client = new WebClient();
var stream = client.OpenRead(imageUrl);
if (stream == null) return "";
var bitmap = new Bitmap(stream);
IBarcodeReader reader = new BarcodeReader();
var result = reader.Decode(bitmap);
client.Dispose();
return result.Text;
}
After this only access to the file, I'm trying to access the file again in another proccess but it says that another proccess (must be this one i descibed here, cause when i cancled this it didn't throw the exception).
So how can I make sure the file isn't being accessed anymore after this code above?
And I also thinks maybe is there a way to close all accesses to a file, whether they were made in this code or any other code.
Thanks
Since Bitmap is an IDisposable, you have to make sure that you properly dispose of it after usage, which is usually done by creating it in a using statement.
In addition, when you load a Bitmap from a local file, you would not have to deal with Streams at all.
This should be sufficient:
public static string DecodeQR(string imageFilePath)
{
using (var bitmap = new Bitmap(imageFilePath))
{
return new BarcodeReader().Decode(bitmap).Text;
}
}
I think the file handle, that isn't closed, is held by the variable stream which receives the file opened by WebClient.OpenRead. You will need to dispose the stream resource as well.
With a using block it's disposed automatically when the block is exited - where using guarantees to invoke Dispose even in case of exceptions thrown inside the using block. Which is quite good, when you want to open that same file later again.
Also I think you don't need a WebClient if you deal with a local file. Just opening that file as a FileStream seems more straight forward.
using System.IO;
...
public static string DecodeQR(string localImageFile)
{
using (var stream = new FileStream(localImageFile,
FileMode.Open, FileMode.Read))
{
if (stream == null) return "";
var bitmap = new Bitmap(stream);
// Install-Package ZXing.Net -Version 0.16.5
var reader = new BarcodeReader();
var result = reader.Decode(bitmap);
return result.Text;
}
}

Problem in overwriting Application.persistentDataPath

I have a JSON file which contains data for my Localization in my game. The file is stored in Application.persistentDataPath . I read in the documentation that the file is not deleted or overwritten when updating the game. Currently I launch the app and the file is there but when I add more content and send an update to save again, it only has the original content.
But is there a way to update this file when I update the game?
What if in the future I want to add more content to this JSON file, I would have to delete it and upload it again?
Any way to update and overwrite it?
private static void Request(string file)
{
var loadingRequest = UnityWebRequest.Get(Path.Combine(Application.streamingAssetsPath, file));
loadingRequest.SendWebRequest();
while (!loadingRequest.isDone)
{
if (loadingRequest.isNetworkError || loadingRequest.isHttpError)
{
break;
}
}
if (loadingRequest.isNetworkError || loadingRequest.isHttpError)
{
// Some error happened.
}
else
{
File.WriteAllBytes(Path.Combine(Application.persistentDataPath, file), loadingRequest.downloadHandler.data);
}
}
// Loads key from "StreamingAssets/language_data.json" file.
public static string LoadJson(string key)
{
Request("data.json");
var jsonPath = Path.Combine(Application.persistentDataPath, jsonFileName);
using (StreamReader r = new StreamReader(jsonPath))
{
var N = JSON.Parse(r.ReadToEnd());
string result = N[GetLanguage()][key];
return result;
}
}
I think the issue is the following:
You are only creating a file named data.json NOT languages_data.json!
In Request (you pass in "data.json") you copy
Application.streamingAssetsPath, file
to
Application.persistentDataPath, file
where file = "data.json"
Then in LoadJson you are trying to load values from
Application.persistentDataPath, jsonFileName
where - as to your comments - jsonFileName = "languages_data.json"
=> It is a different path!
In the Editor/on your PC you probably still have an old languages_data.json in the persistent data from some time ago. Therefore there is no error but it is also never updated. Delete the persistent/languages_data.json on your PC and it will throw a FileNotFoundException.
To solve this make 100% sure the file names are the same everywhere. The simplest fix code wise would be to simply rather use
Request(jsonFileName);
and make sure that jsonFileName matches the name of your existing file in StreamingAssets.

IOException when trying to delete an image

I have a profile page where the user can change their profile picture, When the user clicks submit their old profile picture is delete and replace with a the new one. However, when I try and delete the image it gives the error below:
IOException: The process cannot access the file
'C:\Users\Shayan\source\repos\RestaurantWeb\RestaurantWeb\wwwroot\Images\Users\92487709-5b2f-417c-a64f-4661962693cf_imb5ohqzqr511.jpg'
because it is being used by another process.
Here is my snippet of code where I add and delete the images:
if (accountDetailsViewModel.ProfilePicture != null)
{
string fileName = FileUploadHelper.GetUniqueFileName(accountDetailsViewModel.ProfilePicture.FileName);
string filePath = FileUploadHelper.GetProfileFilePath(fileName, _webHostEnvironment);
await accountDetailsViewModel.ProfilePicture.CopyToAsync(new FileStream(filePath, FileMode.Create));
user.ProfileImagePath = fileName;
string previousImageFilePath = FileUploadHelper.GetProfileFilePath(accountDetailsViewModel.PreviousPicturePath, _webHostEnvironment);
if (System.IO.File.Exists(previousImageFilePath) && accountDetailsViewModel.PreviousPicturePath != "noprofilepic.jpeg")
{
System.IO.File.Delete(previousImageFilePath);
}
}
Why is this happening? Am I meant to be closing the file? I'm not using File.Create() so I can't really close it like:
var img = File.Create(filePath);
img.Close();
Try closing the FileStream that you're creating.
Edit: Check out this.

IO Exception - File being used by another process (Can't open file following directory creation)

I have got a project on the go that monitors patients for a vet while they are being operated on and writes the result to a text file. While I was experimenting with the outputting I just let the files save in the Debug folder, which worked fine. However, I've now created a full directory that creates or opens a main folder, and then a sub folder (based on input text from the program), to save the text file into.
private void createDirectory()
{ //create output file in this folder using owner name and current date
//main folder path (contains all files output from system)
string rootDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Horse Monitoring Records";
//sub folder path (each patient has individual subfolder)
string subDirectory = rootDirectory + "\\" + txtPatName.Text + "-" + txtOwnerName.Text;
//file name (patient has file created for each operation)
fileName = subDirectory + "\\" + txtOwnerName.Text + "-" + DateTime.Now.Date.ToString("ddMMyyyy") + ".txt";
if (!Directory.Exists(rootDirectory)) //if main folder does not exist...
{
Directory.CreateDirectory(rootDirectory); //create it in My Documents
}
if (!Directory.Exists(subDirectory)) //if patient sub folder does not exist...
{
Directory.CreateDirectory(subDirectory); //create it in Patient-Owner format
}
if (!File.Exists(fileName)) //if monitoring file does not exist...
{
File.Create(fileName); //create it in Owner-Date format
}
}
This stage works fine, but as soon as you try to save some data to the text file, it throws to a run time error stating that
The file cannot be accessed because it is being used by another process.
The exception is brought up here:
private void saveFileDetails()
{
//Once case details have been entered, create new file using these details and add data input structure
StreamWriter consoleFile = new StreamWriter(fileName);
...
}
When I went and checked out the folder, the relevant sub-folder and file had been created but the text file was blank.
I'm guessing it's something to do with closing the text file after creating the directory, which means it's already open when the system tries to open it. I can't figure out how to sort this issue out though!
The two functions shown above are called like this:
private void btnStart_Click(object sender, EventArgs e)
{
...
//file details entered upon load written to new file - according to PatID
createDirectory();
saveFileDetails();
}
Any suggestions on where to go from here would be very much appreciated!
Thanks,
Mark
The issue here is that you do
if (!File.Exists(fileName)) //if monitoring file does not exist...
{
File.Create(fileName); //create it in Owner-Date format
}
Right before you try to write to the file. Because you've just created it (if it didn't exist), chances are that the operating system hasn't released the file yet.
Like #Jauch mentioned in the comments, you could skip this check completely and use the StreamWriter overload which will create file if it doesn't exist, or append to it if it does.
private void saveFileDetails()
{
//Once case details have been entered, create new file using these details and add data input structure
using (StreamWriter consoleFile = new StreamWriter(fileName, true))
{
// ...
}
}
Alternatively you can use the following to write all of your text at once:
File.AppendAllText(textToWrite, fileName);
File.Create(fileName) returns an open stream to the file which is never closed.
To create an empty file use File.WriteAllBytes(fileName, new byte[0]);
Otherwise the 2 methods can be shortend
private void SaveFileDetails()
{
string subDirectory = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
"Horse Monitoring Records");
// create the folder hierarchy if not exists. does nothing if already there
Directory.CreateDirectory(subDirectory);
// each patient has individual file
var filepath = Path.Combine(subDirectory,
txtPatName.Text + "-" + txtOwnerName.Text + "-" + DateTime.Now.Date.ToString("yyyyMMdd") + ".txt");
// creates the file if not exists
using (var writer = new StreamWriter(filepath, append: true, encoding: Encoding.UTF8))
{
// write details
}
}
Note:
merged 2 methods
.NET naming conventions applied
changed dateformat to better sort by name in explorer
StreamWriter implements IDisposable, so wrapping it in a using block can manage closing and disposing the writer and ensuring it is available the next time you want to touch that file. It can also manage creating the text file if it doesn't exist, removing the need to explicitly call File.Create.
StreamWriter consoleFile = new StreamWriter(fileName);
becomes
using (StreamWriter writer = File.AppendText("log.txt"))
{
// writing, etc.
}
or
using (StreamWriter writer = new StreamWriter(fileName, true))
{ // true says "append to file if it exists, create if it doesn't"
// writing, etc.
}
Whatever seems more readable to you will work fine.

Categories