i am struggling with getting SHA256 sum of a file.
When program starts method GetSHA256FromStream is called.
The error occurs in method GetSHA256 when File.Open is called.
I am running Visual Studio as Administrator.
ERROR:
System.IO.IOException: 'The process cannot access the file 'C:\Users\WS1\AppData\Local\Temp\test.ttttt' because it is being
used by another process.'
I don't really know if i need to use async/await for working with files.
public static string GetSHA256FromStream(Stream s)
{
string _tpath = Helper.GetTEMPPath("test.ttttt"); // %TEMP%\\test.ttttt
Helper.WriteStreamToFile(s, _tpath);
return Checksum.GetSHA256(_tpath, true);
}
public async static void WriteStreamToFile(Stream s, string outpath)
{
try
{
FileStream fStream = File.Open(outpath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);
s.Seek(0, SeekOrigin.Begin);
await s.CopyToAsync(fStream);
fStream.Close();
}
catch (Exception e)
{
return;
}
}
public static string GetSHA256(string text, bool isFile = false)
{
SHA256 sha256 = SHA256.Create();
byte[] hash;
if (isFile)
{
FileStream stream = File.OpenRead(text);
hash = sha256.ComputeHash(stream);
}
else
{
byte[] textBytes = Encoding.Default.GetBytes(text);
hash = sha256.ComputeHash(textBytes);
}
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
The method WriteStreamToFile is async, but you are not awaiting it in GetSHA256FromStream. Thus, you are already calling GetSHA256() and trying to open the file, while WriteStreamToFile is still writing.
You could for instance make GetSHA256FromStream also async and then await writing to the file and then once that task is finished calculate the checksum
BTW, you should not return void on async methods but a Task
public static async Task<string> GetSHA256FromStream(Stream s)
{
try {
string _tpath = Helper.GetTEMPPath("test.ttttt"); // %TEMP%\\test.ttttt
await Helper.WriteStreamToFile(s, _tpath);
return Checksum.GetSHA256(_tpath, true);
}
catch (Exception e) {
//some error logging
}
}
public async static Task WriteStreamToFile(Stream s, string outpath)
{
try
{
FileStream fStream = File.Open(outpath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);
s.Seek(0, SeekOrigin.Begin);
await s.CopyToAsync(fStream);
fStream.Close();
}
catch (Exception e)
{
//Don't use empty catches but log some error here
}
}
Related
I have a problem downloading.
Download a file, but with an error when playing, I also notice that the size of the file is doubled.
On one side I have the controller and on the other the function that gets the file
[HttpGet(ApiRoutes.MohC.GetSound)]
public async Task<IActionResult> GetSound([FromRoute] string fileName) {
var memory = await _mohCorpService.GetAudioFile(fileName);
if (memory == null)
return NotFound();
return File(memory, "audio/wav", fileName);
}
/--------------------------------------------------------------------------/
public static async Task<MemoryStream> GetAudioFile(string fileName)
{
string completeFilePath = "/var/www/audio/"+fileName+".wav";
try
{
if (!File.Exists(completeFilePath))
return null;
var memory = new MemoryStream();
using (var stream = new FileStream(completeFilePath, FileMode.Open))
{
await stream.CopyToAsync(memory);
}
memory.Position = 0;
return memory;
}
catch (Exception e)
{
return null;
}
}
I am creating a program which takes passwords and applies an encoding on them onto a file which I have creatively labeled a PASSWORDFILE file. I am a self taught amateur programmer and this is my first time using streams => I'm sorry my code isn't cleaner. When I add a password to my file, the file refuses to open (giving me a "System.IO.IOException: The process cannot access the file '[file path here]' because it is being used by another process."). I have made sure I am closing all my streams yet this error still persists.
To add further confusion:
namespace PasswordSaver
{
[Serializable]
class Password
{
public string ID;
string baseWord;
public Password(string password, string ID)
{
this.ID = ID;
baseWord = password;
}
public virtual string GetPassword()
{
return baseWord;
}
}
[Serializable]
class EncodedPassword : Password
{
EncoderAndDecoder Encoder;
public EncodedPassword(string decodedBasePassword, string ID) : base(decodedBasePassword, ID)
{
Encoder = new EncoderAndDecoder();
}
public override string GetPassword()
{
return Encoder.Encode(base.GetPassword(), out _);
}
}
[Serializable]
class EncodedPasswordWithAddendum : EncodedPassword
{
string addendum;
public EncodedPasswordWithAddendum(string decodedBasePassword, string addendum, string ID) : base(decodedBasePassword, ID)
{
this.addendum = addendum;
}
public override string GetPassword()
{
return base.GetPassword() + addendum;
}
}
}
the error only occurs when I attempt to add an EncodedPassword or EncodedPasswordWithAddendum instances but not a Password instance.
My writing code is
namespace PasswordSaver
{
class PasswordWriter
{
public readonly string saveFilePath;
static string directory = Directory.GetCurrentDirectory();
#region Constructors
public PasswordWriter()
{
saveFilePath = directory + #"\PasswordSaver"
+ ".passwordfile";
}
public PasswordWriter(string saveFilePath)
{
this.saveFilePath = saveFilePath;
}
#endregion
#region Individual Writing Functions
private void WriteBinary(object objectToEncode)
{
WriteBinary(objectToEncode, out _);
}
private void WriteBinary(object objectToEncode, out Exception exception)
{
exception = null;
try
{
IFormatter binaryFormatter = new BinaryFormatter();
Stream fileStream = new FileStream(saveFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
Stream memoryStream = new MemoryStream();
memoryStream.Position = memoryStream.Length;
binaryFormatter.Serialize(memoryStream, objectToEncode);
EncodeFromStream(ref memoryStream, ref fileStream);
fileStream.Close();
memoryStream.Close();
}
catch (Exception e)
{
exception = e;
}
}
#endregion
#region File Read and Writing
public void WriteFile(Password[] passwords)
{
if (File.Exists(saveFilePath))
{
Stream stream = new FileStream(saveFilePath, FileMode.Truncate, FileAccess.Write);
stream.Close();
}
WriteBinary(passwords.Length);
foreach (Password password in passwords)
{
WriteBinary(password);
}
}
public void WriteToFile(Password password)
{
Password[] oldPasswords = ReadFile();
Password[] passwords = new Password[oldPasswords.Length + 1];
for (int i = 0; i < oldPasswords.Length; i++)
{
passwords[i] = oldPasswords[i];
}
passwords[oldPasswords.Length] = password;
WriteFile(passwords);
}
public bool ReplacePassword(string oldPasswordID, Password newPassword)
{
Password[] passwords = ReadFile();
for (int i = 0; i < passwords.Length; i++)
{
if (passwords[i].ID == oldPasswordID)
{
passwords[i] = newPassword;
return true;
}
}
return false;
}
public Password[] ReadFile()
{
Stream fileStream = new FileStream(saveFilePath, FileMode.OpenOrCreate, FileAccess.Read);
IFormatter binaryFormatter = new BinaryFormatter();
Stream memoryStream = new MemoryStream();
DecodeFromStream(ref fileStream, ref memoryStream);
fileStream.Close();
memoryStream.Position = 0;
int length = (int) binaryFormatter.Deserialize(memoryStream);
//Console.WriteLine(length + " is the length");//debug
Password[] passwords = new Password[length];
for (int i = 0; i < length; i++)
{
//Console.WriteLine(memoryStream.Position + " " + memoryStream.Length);//debug
//Console.WriteLine(i);//debug
passwords[i] = (Password)binaryFormatter.Deserialize(memoryStream);
}
memoryStream.Close();
return passwords;
}
#endregion
#region Encode and Decode
private void EncodeFromStream(ref Stream stream, ref Stream newStream)
{
stream.Position = 0;
newStream.Position = newStream.Length;
for (int i = 0; i < stream.Length; i++)
{
int integer = stream.ReadByte();
byte originalByte = (byte)integer;// get a byte off of the line
//Encode byte here
newStream.WriteByte(setOfBits1);
newStream.WriteByte(setOfBits2);
}
}
private void DecodeFromStream(ref Stream stream, ref Stream newStream)
{
newStream.Position = newStream.Length;
stream.Position = 0;
for (int i = 0; i < (stream.Length / 2); i++)// stream.Length / 2 because the program reads two bytes per iteration of the for loop
{
//I decode the bytes here
newStream.WriteByte(originalByte);
}
}
#endregion
public void WriteContentsToFile()
{
Stream stream = new FileStream(saveFilePath + "1", FileMode.OpenOrCreate, FileAccess.ReadWrite);
Stream stream1 = new FileStream(saveFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
this.DecodeFromStream(ref stream1, ref stream);
stream.Close();
stream1.Close();
}
}
}
I have removed the code that encoded and decoded the streams in EncodeFromStream and DecodeFromStream.
any occurrence of new FileStream(saveFilePath + "1", FileMode.OpenOrCreate, FileAccess.ReadWrite) is a where I was writing to a seperate file in a decoded format. To distinguish the two files I changed the file type from PASSWORDFILE to PASSWORDFILE1.
In Conclusion:
I am using the WriteFile or WriteToFile methods with a Password[] that contains an EncodedPassword or EncodedPasswordWithAddendum. then when I try to open the file through a FileStream (usually through the method ReadFile) I get the Exception "System.IO.IOException: The process cannot access the file '[file path here]' because it is being used by another process".
Thank you for your help.
Streams usually contain unamanged resources (the OS Filehandles), so they implement IDisposeable.
While you can always be certain that the GC will clean up disposeable stuff eventually (latest at application closing), usually that is way to late. You have to do it explicitly. And for that I have a one rule regarding IDisposeable stuff:
"Never split up the creation and disposing of a disposeable resource. Create. Use. Dispose. All in the same piece of code, ideally using a using block."
The only exception I ever encountered a logfiles. Nothing else is remotely worth the trouble and headaches of keeping something disposeable open. Especially not performance.
As the using block uses a try...finally, you can be certain it will run. Compiler and runtime make certain finally blocks always run, even on function return, jump via goto or Exception cases.
I need to pass a stream to a couple of functions in another class, but its throwing an error
Cannot access a closed stream
Here's the code:
first method:
Here it opens a file with File.Open method and then creates a memorystream object and it copies FileStream to MemoryStream. then sets Position to 0 (i set position to 0, because i was that in a solution, but not helping tho). Then it creates an object of class DocxConvert and call the Converto method by passing MemoryStream to it.
using (var stream = File.Open(tempPath2, FileMode.Open))
{
using(var ms = new MemoryStream())
{
stream.CopyTo(ms);
ms.Position = 0;
using (var docx = new DocxConvert())
{
return docx.Converto(ms);
}
}
}
DocxConvert Class:
It takes stream and then calls copyStream method by passing the accepted stream.
copyStream method in DocxConvert Class: it should copy the accepted stream to another stream called _memoryStream which is a class property.
public class DocxConvert
{
private MemoryStream _memoryStream = new MemoryStream();
public bool Converto(Stream stream)
{
try
{
copyStream(stream);
//more code
}
catch (IOException ex)
{
Debug.WriteLine(ex);
}
return true;
}
private void copyStream(Stream stream)
{
stream.CopyTo(_memoryStream); //here it throws the error
}
}
p.s. I search for this error here before posting, but non of the topics helped me.
SOLVED by restarting PC, the code it ok.
I am not aware about your question .But here in the code bellow no excepion
private void button1_Click(object sender, EventArgs e)
{
string tempPath2 = Application.StartupPath + "//" + "test.txt";
using (var stream = File.Open(tempPath2, FileMode.Open))
{
using (var ms = new MemoryStream())
{
stream.CopyTo(ms);
ms.Position = 0;
var docx = new DocxConvert();
var isok = docx.Converto(ms);
}
}
}
The bellow is the calss defined where _memorystream is defined at top
MemoryStream _memoryStream = new MemoryStream();
public bool Converto(Stream stream)
{
try
{
copyStream(stream);
//more code
}
catch (IOException ex)
{
// Debug.WriteLine(ex);
}
return true;
}
private void copyStream(Stream stream)
{
try
{
stream.CopyTo(_memoryStream);
}
catch (Exception)
{
}
}
I am trying to write some json text. But I get an Exception like
The process cannot access the file C:\blah blah\SystemInActivity.json because it is being used by an other process. But then second time when I run the app after json file is created and then when I write I dont get an exception. Please help.
class ApplicationSettingsViewModel
{
ApplicationSettingsModel model;
MemoryMappedFile mmf = null;
public string FullPath = string.Empty;
//This is not a singleton class but I guess it has to be one but its ok for demonstration.
public ApplicationSettingsViewModel()
{
model = new ApplicationSettingsModel();
CreateFileWithoutMemoryMap();
//MemoryMapped();
}
public string GetDriectory()
{
return Path.GetDirectoryName(FullPath);
}
private void CreateFileWithoutMemoryMap()
{
var info = Directory.CreateDirectory(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "/" + model.Data.Settings.OrcaUISpecificSettings.TimeOutFolder);
string path = Path.Combine(info.FullName + #"\" + model.Data.Settings.OrcaUISpecificSettings.File);
//mmf = MemoryMappedFile.CreateFromFile(path, FileMode.CreateNew, "MyMemoryFile", 1024 * 1024, MemoryMappedFileAccess.ReadWrite);
FullPath = path;
if (!File.Exists(path))
{
File.Create(path);
}
}
public void WriteToFile(string json)
{
try
{
FileStream fileStream = File.Open(FullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); //This line giving Exception
fileStream.SetLength(0);
fileStream.Close(); // This flushes the content, too.
using (StreamWriter sw = new StreamWriter(FullPath))
{
sw.Write(json);
}
}
catch (Exception ex)
{
}
}
In the constructor of the MainWindow I am calling the write method
private ApplicationSettingsViewModel AppViewModel;
public MainWindow()
{
InitializeComponent();
//MessageBox.Show("App Started");
AppViewModel = new ApplicationSettingsViewModel();
WriteToFile("Active");
}
public void WriteToFile(string status)
{
var root = new Root();
string jsonString = string.Empty;
root.AllApplications.Add(new DataToWrite() { AppName = "DevOrca", Status = status });
try
{
jsonString = JsonConvert.SerializeObject(root, Formatting.Indented);
}
catch (Exception ex)
{
MessageBox.Show(jsonString);
MessageBox.Show("Exception");
}
mutex.WaitOne();
//Serialize Contents and write
AppViewModel.WriteToFile(jsonString);
//var access = AppViewModel.GetAccessor();
//byte[] bytes = Encoding.ASCII.GetBytes(jsonString);
//access.Write(bytes, 0, bytes.Length);
mutex.ReleaseMutex();
}
File.Create() method opens FileStream to create a file and you need to close it, something like this:
File.Create(path).Close();
Is there any way to write an asynchronous function that writes to data to a file repeatedly.
I am getting the following error when I write asynchronous function
The process cannot access the file 'c:\Temp\Data.txt' because it is being used by another process
public void GoButton_Click(object sender, System.EventArgs e)
{
IAsyncResult ar = DoSomethingAsync(strURL, strInput);
Session["result"] = ar;
Response.Redirect("wait1.aspx");
}
private IAsyncResult DoSomethingAsync(string strURL, string strInput)
{
DoSomethingDelegate doSomethingDelegate = new DoSomethingDelegate(DoSomething);
IAsyncResult ar = doSomethingDelegate.BeginInvoke(strURL, strInput, new AsyncCallback(MyCallback), null);
return ar;
}
private delegate void DoSomethingDelegate(string strURL, string strInput);
private void MyCallback(IAsyncResult ar)
{
AsyncResult aResult = (AsyncResult)ar;
DoSomethingDelegate doSomethingDelegate = (DoSomethingDelegate)aResult.AsyncDelegate;
doSomethingDelegate.EndInvoke(ar);
}
private void DoSomething(string strURL, string strInput)
{
int i = 0;
for (i = 0; i < 1000; i++)
{
m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
m_streamWriter.WriteLine("{0} ", MethodCall(strURL, strInput));
m_streamWriter.Flush();
m_streamWriter.Close();
}
}
Well I had the same problem. And solved it now. It is kind of late suggestion but may be help for others.
Include the following using statements in the console examples below.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
Use of the FileStream Class
The examples below use the FileStream class, which has an option that causes asynchronous I/O to occur at the operating system level. In many cases, this will avoid blocking a ThreadPool thread. To enable this option, you must specify the useAsync=true or options=FileOptions.Asynchronous argument in the constructor call.
StreamReader and StreamWriter do not have this option if you open them directly by specifying a file path. StreamReader/Writer do have this option if you provide them a Stream that was opened by the FileStream class. Note that asynchrony provides a responsiveness advantage in UI apps even if a thread pool thread is blocked, since the UI thread is not blocked during the wait.
Writing Text
The following example writes text to a file. At each await statement, the method immediately exits. When the file I/O is complete, the method resumes at the statement following the await statement. Note that the async modifier is in the definition of methods that use the await statement.
static void Main(string[] args)
{
ProcessWrite().Wait();
Console.Write("Done ");
Console.ReadKey();
}
static Task ProcessWrite()
{
string filePath = #"c:\temp2\temp2.txt";
string text = "Hello World\r\n";
return WriteTextAsync(filePath, text);
}
static async Task WriteTextAsync(string filePath, string text)
{
byte[] encodedText = Encoding.Unicode.GetBytes(text);
using (FileStream sourceStream = new FileStream(filePath,
FileMode.Append, FileAccess.Write, FileShare.None,
bufferSize: 4096, useAsync: true))
{
await sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
};
}
Reading Text
The following example reads text from a file. The text is buffered and, in this case, placed into a StringBuilder. Unlike in the previous example, the evaluation of the await produces a value. The ReadAsync method returns a Task, so the evaluation of the await produces an Int32 value (numRead) that is returned after the operation completes..
static void Main(string[] args)
{
ProcessRead().Wait();
Console.Write("Done ");
Console.ReadKey();
}
static async Task ProcessRead()
{
string filePath = #"c:\temp2\temp2.txt";
if (File.Exists(filePath) == false)
{
Console.WriteLine("file not found: " + filePath);
}
else {
try {
string text = await ReadTextAsync(filePath);
Console.WriteLine(text);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
static async Task<string> ReadTextAsync(string filePath)
{
using (FileStream sourceStream = new FileStream(filePath,
FileMode.Open, FileAccess.Read, FileShare.Read,
bufferSize: 4096, useAsync: true))
{
StringBuilder sb = new StringBuilder();
byte[] buffer = new byte[0x1000];
int numRead;
while ((numRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
string text = Encoding.Unicode.GetString(buffer, 0, numRead);
sb.Append(text);
}
return sb.ToString();
}
}
Original source was here but unfortunately the link seems dead now.
New source can be found here.
Hope that helps...
Example of a helper method to handle async writing to a file.
public async Task FileWriteAsync(string filePath, string messaage, bool append = true)
{
using (FileStream stream = new FileStream(filePath, append ? FileMode.Append : FileMode.Create, FileAccess.Write, FileShare.None, 4096, true))
using (StreamWriter sw = new StreamWriter(stream))
{
await sw.WriteLineAsync(messaage);
}
}
Writing asynchronously to the file will not solve this issue. You'll need to wait for the file to be available.
If you use a simple StreamWriter, you could replace it with a simple class. No need for async/await. This is an example of writing a text file.
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Threading.Tasks;
class LogWriter : IDisposable
{
private BlockingCollection<string> blockingCollection = new BlockingCollection<string>();
private StreamWriter log = null;
bool run = true;
Task task = null;
public LogWriter(string logFilePath)
{
log = new StreamWriter(logFilePath);
task = Task.Run(() =>
{
while (run)
{
log.WriteLine(blockingCollection.Take());
}
});
}
public void WriteLine(string value)
{
blockingCollection.Add(value);
}
public void Dispose()
{
run = false;
task.Dispose();
log.Close();
log.Dispose();
}
}
To use it, do just like you would do with a StreamWriter:
using (var log = new LogWriter(logFileName))
{
log.WriteLine("Hello world");
// Code here that should not be blocked by writing to the file
}
Simple and straightforward solution:
using var file = new StreamWriter(path);
await file.WriteAsync(content);
The accepted answer has the common async pitfall - the buffers are not flushed async-ly. Check this out: https://github.com/davidfowl/AspNetCoreDiagnosticScenarios/blob/master/AsyncGuidance.md#always-call-flushasync-on-streamwriters-or-streams-before-calling-dispose
Either use the new await using or flush the buffer manually before disposing
await using (var file = new StreamWriter(path)) //mind the "await using"
{
await file.WriteAsync(content);
}
or
using (var streamWriter = new StreamWriter(context.Response.Body))
{
await streamWriter.WriteAsync("Hello World");
await streamWriter.FlushAsync();
}
Ultimately it depends why you're trying to do it.
If you aren't going to be writing too much data to the file, you can constantly open and close it.
Alternatively, if you know when you want the file open and when you want it closed, you can open it when it's needed, then keep it open for writing until the point you know it's no longer needed.