NAudio code holds lock on input file - c#

My code below holds a lock on the input file preventing me from working with it later:
public static void ToWave_WMF(string source, string destination)
{
using (var reader = new MediaFoundationReader(source))
using (var rateSampler = new MediaFoundationResampler(reader, new WaveFormat(DefaultEncoding.SampleRate, reader.WaveFormat.Channels)))
using (var channelSampler = new MediaFoundationResampler(rateSampler, new WaveFormat(rateSampler.WaveFormat.SampleRate, DefaultEncoding.Channels)))
{
WaveFileWriter.CreateWaveFile(destination, channelSampler);
}
}
public static string BuildWavFile(string userFileLocation)
{
var sampleList = new List<ISampleProvider>();
try
{
// Add input file
var waveFile = AudioHelpers.ToWave_WMF(userFileLocation);
sampleList.Add(new AudioFileReader(waveFile));
WaveFileWriter.CreateWaveFile16(sirenWaveFile, new ConcatenatingSampleProvider(sampleList));
}
finally
{
foreach (var sample in sampleList)
{
((AudioFileReader)sample).Dispose();
}
}
return sirenWaveFile;
}
Am I using resources wrong? Why is this lock being held? If I delete the file after toWave_WMF() there is no issue. If I use sampleList.Add(new AudioFileReader(userFileLocation)); I also dont have any issues deleting the userFile.

Related

Import macro to excel using open xml c#

I am able to copy a vbaproject part from xlsm to another xlsm through memory stream and add it through addnew part. Is there any possibility to import/add only the bas file into the xlsm file using open xml.
Can some one assist.Below code helped to take a clone of vba part and update the same.
private static void cloneVbaPart(string src, string dst)
{
using (WordprocessingDocument srcDoc = WordprocessingDocument.Open(src, false))
{
var vbaPart = srcDoc.MainDocumentPart.VbaProjectPart;
using (WordprocessingDocument dstDoc = WordprocessingDocument.Open(dst, true))
{
var partsToRemove = new List<OpenXmlPart>();
foreach (var part in dstDoc.MainDocumentPart.GetPartsOfType<VbaProjectPart>())
{
partsToRemove.Add(part);
}
foreach (var part in dstDoc.MainDocumentPart.GetPartsOfType<CustomizationPart>())
{
partsToRemove.Add(part);
}
foreach (var part in partsToRemove)
{ dstDoc.MainDocumentPart.DeletePart(part); }
var vbaProjectPart = dstDoc.MainDocumentPart.AddNewPart<VbaProjectPart>();
var vbaDataPart = vbaProjectPart.AddNewPart<VbaDataPart>();
using (Stream data = vbaPart.GetStream())
{
vbaProjectPart.FeedData(data);
}
using (Stream data = vbaPart.VbaDataPart.GetStream())
{
vbaDataPart.FeedData(data);
}
}
}
}

Invalid Operation Exception Collection was modified C#

Hello i'm trying to implement Facebook friends tracker that can track who's online and who's offline using Selenium WebDriver.
Everything works fine except when a user goes offline and i remove him from the collection it throws an exception .
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Threading;
using OpenQA.Selenium;
using OpenQA.Selenium.Edge;
using OpenQA.Selenium.Support.Events;
using OpenQA.Selenium.Support.UI;
namespace FacebookFriendTracker
{
public delegate void StatusChangedEventHandler(object source, StatusChangedEventArgs e);
public class Watcher
{
private readonly IWebDriver _driver;
private HashSet<User> _tempUserOnline = new HashSet<User>();
public event StatusChangedEventHandler StatusChanged;
private bool run;
public Watcher()
{
//UsersOnline = new HashSet<User>();
_driver = new EdgeDriver();
_driver.Navigate().GoToUrl("https://mbasic.facebook.com");
var wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(20));
wait.Until(ExpectedConditions.ElementExists(By.PartialLinkText("Chat")));
var element = _driver.FindElement(By.PartialLinkText("Chat"));
element.Click();
run = false;
}
public void Tracker()
{
Thread.Sleep(5000);
//_usersOnline = _driver.FindElements(By.XPath(".//a[contains(#href,'fbid')]"));
var usersOnline = new HashSet<User>();
foreach (var userOnline in _driver.FindElements(By.XPath(".//a[contains(#href,'fbid')]")))
{
var extracedAttributeValue = userOnline.GetAttribute("href");
var regex = new Regex(#"\d+");
var id = long.Parse(regex.Match(extracedAttributeValue).Value);
var fullName = userOnline.Text;
usersOnline.Add(new User() {FullName = fullName, Id = id});
}
while (true)
{
Thread.Sleep(5000);
_driver.Navigate().Refresh();
var newUsersOnline = new HashSet<User>();
foreach (var user in _driver.FindElements(By.XPath(".//a[contains(#href,'fbid')]")))
{
var attirbute = user.GetAttribute("href");
var reg = new Regex(#"\d+");
var newId = long.Parse(reg.Match(attirbute).Value);
var newFullName = user.Text;
newUsersOnline.Add(new User() { FullName = newFullName, Id = newId });
}
_tempUserOnline = usersOnline;
foreach (var usrOnline in newUsersOnline.Except(_tempUserOnline))
{
OnStatusChanged(this , new StatusChangedEventArgs() {User = usrOnline,Status = Status.Online});
_tempUserOnline.Add(usrOnline);
}
// Here it throws and exception if the the user goes offline
foreach (var usroffline in usersOnline.Except(newUsersOnline))
{
OnStatusChanged(this, new StatusChangedEventArgs() { User = usroffline, Status = Status.Offline });
_tempUserOnline.Remove(usroffline);
}
}
}
protected virtual void OnStatusChanged(object source, StatusChangedEventArgs e)
{
if (StatusChanged !=null)
OnStatusChanged(source,e);
else
{
Console.WriteLine("User: {0} is {1} ",e.User.FullName,e.Status);
}
}
}
}
You cannot modify that collection while an emueration is in progress. A common fix is to ToList() it:
foreach (var usroffline in usersOnline.Except(newUsersOnline).ToList())
{
OnStatusChanged(this, new StatusChangedEventArgs() { User = usroffline, Status = Status.Offline });
_tempUserOnline.Remove(usroffline);
}
The problem is that you can't modify a collection while you're iterating through it with a foreach loop.
Here, you are setting _tempUserOnline to point to the same object as usersOnline:
_tempUserOnline = usersOnline;
Then further down, you have this loop, which modifies _tempUserOnline, thus modifying usersOnline also since they point to the same object. Since you are looping through usersOnline (and effectively _tempUserOnline too), you are getting the error when you do _tempUserOnline.Remove(usroffline).
foreach (var usroffline in usersOnline.Except(newUsersOnline))
{
OnStatusChanged(this, new StatusChangedEventArgs() { User = usroffline, Status = Status.Offline });
_tempUserOnline.Remove(usroffline);
}
Did you intend to copy usersOnline into tempUserOnline? If so, you should use .CopyTo() or something equivalent to make an actual copy:
User[] _tempUserOnline = new User[usersOnline.Count - 1];
usersOnline.CopyTo(_tempUserOnline);

Dynamic resource from MemoryStream with ResourceWriter

I'm developing an app with C# and WPF;
I'm creating a resource to a MemoryStream.
var ms = new MemoryStream();
var rWriter = new ResourceWriter(ms);
rWriter.AddResource("key1", "value1");
rWriter.AddResource("key2", "value2");
rWriter.AddResource("key3", "value3");
rWriter.Generate();
rWriter.Close();
Everything works fine untill here but, I don't know how to use this Resource?
Can you help me with using ?
Once you have read the resource into the stream you need to add it to the MergedDictionaries in order to make it available in the application. An example of this might look like this:
var resourceInfo = skinAssembly.GetManifestResourceInfo(resourceName);
if (resourceInfo.ResourceLocation != ResourceLocation.ContainedInAnotherAssembly)
{
var resourceStream = skinAssembly.GetManifestResourceStream(resourceName);
using (var resourceReader = new ResourceReader(resourceStream))
{
foreach (DictionaryEntry entry in resourceReader)
{
if (IsRelevantResource(entry, bamlResourceName))
{
skinBamlStreams.Add(entry.Value as Stream);
}
}
}
}
The code above was taken from my demo application which you can see the full source code for on GitHub.
protected override sealed void LoadResources()
{
var skinResolver = PreLoadResources();
try
{
var skinBamlStreams = skinResolver.GetSkinBamlStreams(_fullName, _resourceName);
foreach (var resourceStream in skinBamlStreams)
{
var skinResource = BamlHelper.LoadBaml<ResourceDictionary>(resourceStream);
if (skinResource != null)
{
Resources.Add(skinResource);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
PostLoadResources();
}
}

Modifying existing resource file programmatically

I am using the following code to generate resource file programmatically.
ResXResourceWriter resxWtr = new ResXResourceWriter(#"C:\CarResources.resx");
resxWtr.AddResource("Title", "Classic American Cars");
resxWtr.Generate();
resxWtr.Close();
Now, i want to modify the resource file crated from above code. If i use the same code, the existing resource file gets replaced. Please help me modify it without loosing the existing contents.
Best Regards,
Ankit
public static void AddOrUpdateResource(string key, string value)
{
var resx = new List<DictionaryEntry>();
using (var reader = new ResXResourceReader(resourceFilepath))
{
resx = reader.Cast<DictionaryEntry>().ToList();
var existingResource = resx.Where(r => r.Key.ToString() == key).FirstOrDefault();
if (existingResource.Key == null && existingResource.Value == null) // NEW!
{
resx.Add(new DictionaryEntry() { Key = key, Value = value });
}
else // MODIFIED RESOURCE!
{
var modifiedResx = new DictionaryEntry() { Key = existingResource.Key, Value = value };
resx.Remove(existingResource); // REMOVING RESOURCE!
resx.Add(modifiedResx); // AND THEN ADDING RESOURCE!
}
}
using (var writer = new ResXResourceWriter(ResxPathEn))
{
resx.ForEach(r =>
{
// Again Adding all resource to generate with final items
writer.AddResource(r.Key.ToString(), r.Value.ToString());
});
writer.Generate();
}
}
I had the same problem this resolve it:
This will append to your existing .resx file
var reader = new ResXResourceReader(#"C:\CarResources.resx");//same fileName
var node = reader.GetEnumerator();
var writer = new ResXResourceWriter(#"C:\CarResources.resx");//same fileName(not new)
while (node.MoveNext())
{
writer.AddResource(node.Key.ToString(), node.Value.ToString());
}
var newNode = new ResXDataNode("Title", "Classic American Cars");
writer.AddResource(newNode);
writer.Generate();
writer.Close();
Here is a function that would help you modify the resource file.
public static void UpdateResourceFile(Hashtable data, String path)
{
Hashtable resourceEntries = new Hashtable();
//Get existing resources
ResXResourceReader reader = new ResXResourceReader(path);
if (reader != null)
{
IDictionaryEnumerator id = reader.GetEnumerator();
foreach (DictionaryEntry d in reader)
{
if (d.Value == null)
resourceEntries.Add(d.Key.ToString(), "");
else
resourceEntries.Add(d.Key.ToString(), d.Value.ToString());
}
reader.Close();
}
//Modify resources here...
foreach (String key in data.Keys)
{
if (!resourceEntries.ContainsKey(key))
{
String value = data[key].ToString();
if (value == null) value = "";
resourceEntries.Add(key, value);
}
}
//Write the combined resource file
ResXResourceWriter resourceWriter = new ResXResourceWriter(path);
foreach (String key in resourceEntries.Keys)
{
resourceWriter.AddResource(key, resourceEntries[key]);
}
resourceWriter.Generate();
resourceWriter.Close();
}
Reference link here

How to delete a line having line number using c#?

My file named as test.txt contains
This document is divided into about 5 logical sections starting with a feature and structure overview, followed by an overview of built in column and cell types. Next is an overview of working with data, followed by an overview of specific major features. Lastly, a “best practice” section concludes the main part of this document.
Now i want to delete 2nd line of the file.
How to do it using c#?
Thanks in advance.
Naveenkumar
List<string> lines = File.ReadAllLines(#"filename.txt").ToList();
if(lines.Count>lineNum){
lines.RemoveAt(lineNum);
}
File.WriteAllLines(#"filename.txt",lines.ToArray());
You can acheive this by splitting the text by \n and then using LINQ to select the lines you want to keep, and re-joining them.
var lineNum=5;
var lines=File
.ReadAllText(#"src.txt")
.Split('\n');
var outTxt=String
.Join(
"\n",
lines
.Take(lineNum)
.Concat(lines.Skip(lineNum+1))
.ToArray()
);
Here's a pretty efficient way to do it.
FileInfo x = new FileInfo(#"path\to\original");
string xpath = x.FullName;
FileInfo y = new FileInfo(#"path\to\temporary\new\file");
using (var reader = x.OpenText())
using (var writer = y.AppendText())
{
// write 1st line
writer.WriteLine(reader.ReadLine());
reader.ReadLine(); // skip 2nd line
// write all remaining lines
while (!reader.EndOfStream)
{
writer.WriteLine(reader.ReadLine());
}
}
x.Delete();
y.MoveTo(xpath);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace rem2ndline
{
class Program
{
static void Main(string[] args)
{
string inPath = #"c:\rem2ndline.txt";
string outPath = #"c:\rem2ndlineresult.txt";
StringBuilder builder = new StringBuilder();
using (FileStream fso = new FileStream(inPath, FileMode.Open))
{
using (StreamReader rdr = new StreamReader(fso))
{
int lineCount = 0;
bool canRead = true;
while (canRead)
{
var line = rdr.ReadLine();
lineCount++;
if (line == null)
{
canRead = false;
}
else
{
if (lineCount != 2)
{
builder.AppendLine(line);
}
}
}
}
}
using(FileStream fso2 = new FileStream(outPath, FileMode.OpenOrCreate))
{
using (StreamWriter strw = new StreamWriter(fso2))
{
strw.Write(builder.ToString());
}
}
}
}
}
Here's what I'd do. The advantage is that you don't have to have the file in memory all at once, so memory requirements should be similar for files of varying sizes (as long as the lines contained in each of the files are of similar length). The drawback is that you can't pipe back to the same file - you have to mess around with a Delete and a Move afterwards.
The extension methods may be overkill for your simple example, but those are two extension methods I come to rely on again and again, as well as the ReadFile method, so I'd typically only have to write the code in Main().
class Program
{
static void Main()
{
var file = #"C:\myFile.txt";
var tempFile = Path.ChangeExtension(file, "tmp");
using (var writer = new StreamWriter(tempFile))
{
ReadFile(file)
.FilterI((i, line) => i != 1)
.ForEach(l => writer.WriteLine(l));
}
File.Delete(file);
File.Move(tempFile, file);
}
static IEnumerable<String> ReadFile(String file)
{
using (var reader = new StreamReader(file))
{
while (!reader.EndOfStream)
{
yield return reader.ReadLine();
}
}
}
}
static class IEnumerableExtensions
{
public static IEnumerable<T> FilterI<T>(
this IEnumerable<T> seq,
Func<Int32, T, Boolean> filter)
{
var index = 0;
foreach (var item in seq)
{
if (filter(index, item))
{
yield return item;
}
index++;
}
}
public static void ForEach<T>(
this IEnumerable<T> seq,
Action<T> action)
{
foreach (var item in seq)
{
action(item);
}
}
}

Categories

Resources