I try to make app which will load and edit id3 tags. I decided to use taglib for that. Everything works fine, but when i try to save edited tag it falls on IOException "The process cannot access the file ...". Heres code:
TagLib.File f = TagLib.File.Create(cesta);
f.Tag.Year = 1999;//uint.Parse(textBox1.Text);
f.Save();
Previously i just have load procedure:
TagLib.File f = TagLib.File.Create(path);
string rok = f.Tag.Year.ToString();
textBox1.Text = rok;
string album = f.Tag.Album;
textBox2.Text = album;
string[] artist = f.Tag.Performers;
string autor = "";
for (int i = 0; i < artist.Length; i++)
{
autor = autor + artist[i];
}
textBox3.Text = autor;
Does anyone know, that I did wrong?
If you're trying to edit an existing file by reopening it, make sure that you have previously closed it. Also, see if you can enclose all of your file access code with using blocks. For example:
using(TagLib.File f = TagLib.File.Create(path))
{
// do work
}
Related
I have 10 txt files in Debug\Tests\Text\ (10 txt files). I need to write a program to open all 10 files and updated every single file. I'm not sure how to do it. Now, I'm actually reading the folder and getting the file name and storing the file name in an array. Below is my code:
private void getFilesName()
{
string[] fileArray = Directory.GetFiles(#"Tests\Text");
//looping through the folder and get the fileNames
for (int i = 0; i<fileArray.Length; i++)
{
MessageBox.Show(fileArray[i]); // I'm doing this is to double check i manage to get the file name.
}
}
After doing this, it do read all the text file name, but the challenge now is for me to access the filename and updating every file in it. I have also created another method just for updating the values in the txt files, below is the code:
private bool modifySQLFile()
{
string destFileName = #"Tests\Text\" // I need the fileName?
string[] fileTexts = File.ReadAllLines(destFileName);
int counter = 0;
//Processing the File
foreach(string line in fileTexts)
{
//only read those non-comments line
if(line.StartsWith("--") == false)
{
//Start to replace instances of Access ID
if(line.Contains(Variable) == true)
{
fileTexts[counter] = fileTexts[counter].Replace(Variable, textBox2.Text);
}
}
counter++;
}
//check if file exists in the backup folder
if(File.Exists("Tests\\Text\\file name "+ textBox1.Text +".sql") == true)
{
MessageBox.Show("This file already exist in the backup folder");
return false;
}
else
{
//update the file
File.WriteAllLines(destFileName, fileTexts);
File.Move(destFileName, "Tests\\Text\\file name"+ textBox1.Text +".sql");
MessageBox.Show("Completed");
return true;
}
}
Your problem seems to be passing the filename variable from the loop to the method.
In order to do what you want, add a parameter to the method:
private bool ModifySQLFile(string filename)
{
string[] fileTexts = File.ReadAllLines(filename);
// ...
}
Then call the method with this parameter:
for (int i = 0; i<fileArray.Length; i++)
{
ModifySQLFile(fileArray[i]);
}
But in general you really don't want to treat a formal language as plaintext like you do. It's very easy to break the SQL like that. What if the user wanted to replace the text "insert", or replaces something with "foo'bar"?
First, implement one (file) modification:
private bool modifySQLFile(String file) {
// given source file, let´s elaborate target file name
String targetFile = Path.Combine(
Path.GetDirectoryName(file),
String.Format("{0}{1}.sql",
Path.GetFileNameWithoutExtension(file),
textBox1.Text));
// In case you want a back up
//TODO: given source file name, elaborate back up file name
//String backUpFile = Path.Combine(...);
// Check (validate) before processing: do not override existing files
if (File.Exists(targetFile))
return false;
//TODO: what if back up file exists? Should we override it? skip?
// if line doesn't start with SQL commentary --
// and contains a variable, substitute the variable with its value
var target = File
.ReadLines(file)
.Select(line => (!line.StartsWith("--") && line.Contains(Variable))
? line.Replace(Variable, textBox2.Text)
: line);
// write modified above lines into file
File.WriteAllLines(targetFile, target);
// In case you want a back up
// Move file to backup
//File.Move(file, backUpFile);
return true;
}
Then call it in the loop:
// enumerate all the text files in the directory
var files = Directory
.EnumerateFiles("#"Tests\Text", "*.txt");
//TODO: you may want filter out some files with .Where
//.Where(file => ...);
// update all the files found above
foreach (var file in files) {
if (!modifySQLFile(file))
MessageBox.Show(String.Format("{0} already exist in the backup folder", file));
}
Please, do not do:
Use Magic values: what is #"Tests\Text\" within your modifySQLFile
Mix UI MessageBox.Show(...) and logic: modifySQLFile returns true or false and it's caller who can display message box.
Materialize when it's not required (Directory.GetFiles, File.ReadAllLines)
If you would like to edit the files in parallel. With threads you can parallelize work.
for (int i = 0; i < fileArray.Length; i++)
new Thread(UpdateFileThread).Start(fileArray[i]);
private void UpdateFileThread(object path)
{
string filePath = (string)path;
//ToDo: Edit file
}
In your case you would create 10 Threads. That solution works, but is a bad pattern if you have to deal with more than 10 files.
Below i have posted the real time code ,which i have used project
protected void btnSqlfinder_Click(object sender, EventArgs e)
{
//Defining the path of directory where all files saved
string filepath = # "D:\TPMS\App_Code\";
//get the all file names inside the directory
string[] files = Directory.GetFiles(filepath);
//loop through the files to search file one by one
for (int i = 0; i < files.Length; i++)
{
string sourcefilename = files[i];
StreamReader sr = File.OpenText(sourcefilename);
string sourceline = "";
int lineno = 0;
while ((sourceline = sr.ReadLine()) != null)
{
lineno++;
//defining the Keyword for search
if (sourceline.Contains("from"))
{
//append the result to multiline text box
TxtResult.Text += sourcefilename + lineno.ToString() + sourceline + System.Environment.NewLine;
}
if (sourceline.Contains("into"))
{
TxtResult.Text += sourcefilename + lineno.ToString() + sourceline + System.Environment.NewLine;
}
if (sourceline.Contains("set"))
{
TxtResult.Text += sourcefilename + lineno.ToString() + sourceline + System.Environment.NewLine;
}
if (sourceline.Contains("delete"))
{
TxtResult.Text += sourcefilename + lineno.ToString() + sourceline + System.Environment.NewLine;
}
}
}
}
This code will fetch the multiple files in the given directory,and show the lines as per the keyword in a separate text.
But you can easily change as per your requirement,Kindly let me know your thoughts.
Thanks
Following the code in this MSDN blog, i have come up with the following code in C#
using Shell32; //Browse to C:\Windows\System32\shell32.dll
private void GetInstalledPrograms()
{
Shell shell = new Shell();
Shell objShell = shell.Application;
string folderName = #"::{26EE0668-A00A-44D7-9371-BEB064C98683}\8\" +
"::{7B81BE6A-CE2B-4676-A29E-EB907A5126C5}";
var objProgramList = objShell.NameSpace(folderName);
if (objProgramList != null)
{
MessageBox.Show(objProgramList.Items().ToString());
}
else
{
MessageBox.Show("Null");
}
}
For what ever reason, objProgramList is null. The odd thing is, with the following powershell code, I get exactly what I'm looking for! I don't know what I'm doing wrong. To me, both examples of my code are identical...
$Shell = New-Object -ComObject Shell.Application
$folderName = "::{26EE0668-A00A-44D7-9371-BEB064C98683}\8\::{7B81BE6A-CE2B-4676-A29E- EB907A5126C5}"
$folder = $Shell.NameSpace($folderName)
if($folder)
{
$folder.Items()
}
Any chance you are using Window 8? According to this answer, creating a shell like that doesn't work in Window 8.
This answer is too late but it might help others with the same problem.
Basically, the problem on your code was the shell command:
string folderName = #"::{26EE0668-A00A-44D7-9371-BEB064C98683}\8\" +
"::{7B81BE6A-CE2B-4676-A29E-EB907A5126C5}";
It should contain "shell:" in the beginning of the command, it should look like this:
string folderName = #"shell:::{26EE0668-A00A-44D7-9371-BEB064C98683}\8\::{7B81BE6A-CE2B-4676-A29E-EB907A5126C5}"
And to get info about the programs like the Name, Publisher, Installed On and etc, try this code that will enumerate all the available fields:
List<string> arrHeaders = new List<string>();
for (int i = 0; i < short.MaxValue; i++)
{
string header = list.GetDetailsOf(null, i);
if (String.IsNullOrEmpty(header))
break;
arrHeaders.Add(header);
}
foreach (Shell32.FolderItem2 item in list.Items())
{
for (int i = 0; i < arrHeaders.Count; i++)
{
//I used listbox to show the fields
listBox1.Items.Add(string.Format("{0}\t{1}: {2}", i, arrHeaders[i], list.GetDetailsOf(item, i)));
}
}
I am trying to Edit a text file which is consist in resources folder of window form project. C#.
I am using this code but it is not writing over text file. No errors come from this
using (System.IO.StreamWriter file = new System.IO.StreamWriter(Namespace.Properties.Resources.textfile))
{
for (int i = 0; i < res2.Count(); i++)
{
label3.Text = "Updating ... ";
label3.Visible = true;
label3.Refresh();
file.WriteLine("asdasD");
}
file.Close();
}
As #LarsTech states in this answer, what you are trying to do is not recommended. Resource files are not meant to be written to--they should only be read from. If you want a place to put files, put them somewhere like Environment.SpecialFolders.
You could also use the AppData folder on the user's computer, which is typically used for exactly what you are trying to achieve:
string fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "textfile.txt");
using (System.IO.StreamWriter file = new System.IO.StreamWriter(fileName))
{
//if the file doesn't exist, create it
if (!File.Exists(fileName))
File.Create(fileName);
for (int i = 0; i < res2.Count(); i++)
{
label3.Text = "Updating ... ";
label3.Visible = true;
label3.Refresh();
file.WriteLine("asdasD");
}
}
As you can see, I removed the file.Close() since it isn't necessary if you are using the using block. You can do this if you are using a member which implements the IDisposable interface, which StreamWriter does.
This should take care of everything for you. You won't have to create any files or worry about where they are.
I am able to write and then read a file using your code in a console application. Can you run this code (console application) and tell me if you have any exception ?
static void Main(string[] args)
{
string fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "textfile.txt");
using (System.IO.StreamWriter file = new System.IO.StreamWriter(fileName))
{
//if the file doesn't exist, create it
if (!File.Exists(fileName))
File.Create(fileName);
for (int i = 0; i < 2; i++)
{
file.WriteLine("asdas2");
}
}
using(System.IO.StreamReader fr = new StreamReader(fileName))
{
Console.WriteLine(fr.ReadToEnd());
}
}
Note, if you are trying to append to the existing file (write at the end of it and keep existing content), you need to use System.IO.StreamWriter(fileName, true).
I want to upload an image file and then extract its basic information (author, dimensions, date created, modified, etc) and display it to the user. How can I do it.
A solution or reference to this problem in asp.net c# code would be helpful. But javascript or php would be ok as well.
Check this Link. You will get more Clearance about GetDetailsOf() and its File Properties based on the Win-OS version wise.
If you want to use C# code use below code to get Metadata's:
List<string> arrHeaders = new List<string>();
Shell shell = new ShellClass();
Folder rFolder = shell.NameSpace(_rootPath);
FolderItem rFiles = rFolder.ParseName(filename);
for (int i = 0; i < short.MaxValue; i++)
{
string value = rFolder.GetDetailsOf(rFiles, i).Trim();
arrHeaders.Add(value);
}
C# solution could be found here:
Link1
Link2
Bitmap image = new Bitmap(fileName);
PropertyItem[] propItems = image.PropertyItems;
foreach (PropertyItem item in propItems)
{
Console.WriteLine("iD: 0x" + item.Id.ToString("x"));
}
MSDN Reference
C# Tutorial Reference
try this...
private string doUpload()
{
// Initialize variables
string sSavePath;
sSavePath = "images/";
// Check file size (mustn’t be 0)
HttpPostedFile myFile = FileUpload1.PostedFile;
int nFileLen = myFile.ContentLength;
if (nFileLen == 0)
{
//**************
//lblOutput.Text = "No file was uploaded.";
return null;
}
// Check file extension (must be JPG)
if (System.IO.Path.GetExtension(myFile.FileName).ToLower() != ".jpg")
{
//**************
//lblOutput.Text = "The file must have an extension of JPG";
return null;
}
// Read file into a data stream
byte[] myData = new Byte[nFileLen];
myFile.InputStream.Read(myData, 0, nFileLen);
// Make sure a duplicate file doesn’t exist. If it does, keep on appending an
// incremental numeric until it is unique
string sFilename = System.IO.Path.GetFileName(myFile.FileName);
int file_append = 0;
while (System.IO.File.Exists(Server.MapPath(sSavePath + sFilename)))
{
file_append++;
sFilename = System.IO.Path.GetFileNameWithoutExtension(myFile.FileName)
+ file_append.ToString() + ".jpg";
}
// Save the stream to disk
System.IO.FileStream newFile
= new System.IO.FileStream(Server.MapPath(sSavePath + sFilename),
System.IO.FileMode.Create);
newFile.Write(myData, 0, myData.Length);
newFile.Close();
return sFilename;
}
For example i have this:
"Was? Wo war ich? Ach ja.<pa>">
I need to create a new text file that will contain only:
Was? Wo war ich? Ach ja.
And i have a big file like 43mb and i need to scan all over the file and get only the places that start with " and end with <pa>" and to get the string between this tags.
I did this code so far:
private void retrivingTestText()
{
w = new StreamWriter(retrivedTextFile);
string startTag = "\"";
string endTag = "<pa>";
int startTagWidth = startTag.Length;
int endTagWidth = endTag.Length;
string text = "\"Was? Wo war ich? Ach ja.<pa>\">";
int begin = text.IndexOf(startTag);
int end = text.IndexOf(endTag, begin + 1);
string result = text.Substring(begin+1, end-1);
w.WriteLine(result);
w.Close();
}
But now i need to make it on a big file 43mb xml file.
So in the constructor i already did StreamReader r;
And string f;
Then i did :
r = new StreamReader(#"D:\New folder (22)\000004aa.xml")
f = r.ReadToEnd();
Now i need to use it with the code above to extract all the strings in the big file between the startTag and endTag and not only specific text.
Second thing i need to make another function so after i make changes it will know to add back all the extractes text strings to the right places where it was before between the startTag and the endTag
Thanks.
You can go for following approach to extract the data.
string word = "\"Was? Wo war ich? Ach ja<pa>\"Jain\"Romil<pa>\"";
string[] stringSeparators = new string[] { "<pa>\"" };
string ans=String.Empty;
string[] text = word.Split(stringSeparators, StringSplitOptions.None);
foreach (string s in text)
{
if (s.IndexOf("\"") >= 0)
{
ans += s.Substring(s.IndexOf("\"")+1);
}
}
return ans;
There is a similar post on how to remove HTML tags using regular expressions. Here is the link.
And another one that you can tweak, here.