I am using this code to import text file to my ListBox
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.Filter = "Text Files|*.txt";
openFileDialog1.Title = "Select a Text file";
openFileDialog1.FileName = "";
DialogResult result = openFileDialog1.ShowDialog();
if (result == DialogResult.OK)
{
string file = openFileDialog1.FileName;
string[] text = System.IO.File.ReadAllLines(file);
foreach (string line in text)
{
listBox2.Items.Add(line);
}
listBox2.Items.Add("");
}
It works fine for small text files, with 10 lines or so, but when I try to import bigger list, (4-5 megabytes) the program isn't responding and it's crashing.
Any help?
Use the BufferedStream class in C# to improve performance.
http://msdn.microsoft.com/en-us/library/system.io.bufferedstream.aspx
By using this:
string[] text = System.IO.File.ReadAllLines(file);
listBox1.Items.AddRange(text);
instead of this:
string[] text = System.IO.File.ReadAllLines(file);
foreach (string line in text)
{
listBox2.Items.Add(line);
}
you will speed up the execution at least 10-15 times because you are not invalidating listBox on every Item insert.
I have measured with few thousand lines.
The bottleneck could also be ReadAllLines if your text has too many lines. Even though I can't figure out why you would be inserting so many lines, will user be able to find the line he/she needs?
EDIT OK then I suggest you to use BackgroundWorker, here is the code:
First you initialize BackGroundWorker:
BackgroundWorker bgw;
public Form1()
{
InitializeComponent();
bgw = new BackgroundWorker();
bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
}
Then you call it in your method:
private void button1_Click(object sender, EventArgs e)
{
if (!bgw.IsBusy)
{
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.Filter = "Text Files|*.txt";
openFileDialog1.Title = "Select a Text file";
openFileDialog1.FileName = "";
DialogResult result = openFileDialog1.ShowDialog();
if (result == DialogResult.OK)
{
string file = openFileDialog1.FileName;
listView1.BeginUpdate();
bgw.RunWorkerAsync(file);
}
}
else
MessageBox.Show("File reading at the moment, try later!");
}
void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
listView1.EndUpdate();
}
void bgw_DoWork(object sender, DoWorkEventArgs e)
{
string fileName = (string)e.Argument;
TextReader t = new StreamReader(fileName);
string line = string.Empty;
while ((line = t.ReadLine()) != null)
{
string nLine = line;
this.Invoke((MethodInvoker)delegate { listBox1.Items.Add(nLine); });
}
}
It will add each line when it reads it, you will have responsive UI, and lines won't affect the listBox before it finishes loading.
It maybe simply not completing its job, and you should have to wait for more. Try with this solution:
http://www.bytechaser.com/en/articles/f3a3niqyb7/display-large-lists-in-listview-control-quickly.aspx
could use a stream to store the data:
class Test
{
public static void Main()
{
string path = #"c:\temp\MyTest.txt";
//Create the file.
using (FileStream fs = File.Create(path))
{
AddText(fs, "This is some text");
AddText(fs, "This is some more text,");
AddText(fs, "\r\nand this is on a new line");
AddText(fs, "\r\n\r\nThe following is a subset of characters:\r\n");
for (int i=1;i < 120;i++)
{
AddText(fs, Convert.ToChar(i).ToString());
}
}
//Open the stream and read it back.
using (FileStream fs = File.OpenRead(path))
{
byte[] b = new byte[1024];
UTF8Encoding temp = new UTF8Encoding(true);
while (fs.Read(b,0,b.Length) > 0)
{
Console.WriteLine(temp.GetString(b));
}
}
}
private static void AddText(FileStream fs, string value)
{
byte[] info = new UTF8Encoding(true).GetBytes(value);
fs.Write(info, 0, info.Length);
}
}
then you event handler
privateasyncvoid Button_Click(object sender, RoutedEventArgs e)
{
UnicodeEncoding uniencoding = new UnicodeEncoding();
string filename = #"c:\Users\exampleuser\Documents\userinputlog.txt";
byte[] result = uniencoding.GetBytes(UserInput.Text);
using (FileStream SourceStream = File.Open(filename, FileMode.OpenOrCreate))
{
SourceStream.Seek(0, SeekOrigin.End);
await SourceStream.WriteAsync(result, 0, result.Length);
}
}
Your application becomes unresponsive because it's waiting for the ReadAllLines method to complete and blocks the UI thread. You may want to read files on a separate thread to avoid blocking the UI. I cannot guarantee that the code below will work without errors but it should give you an idea on how to tackle the problem.
First of all, you'll need a method to append an item to the ListBox:
private void AddListBoxItem(string item)
{
if(!InvokeRequired)
{
listBox2.Items.Add(item);
}
else
{
var callback = new Action<string>(AddListBoxItem);
Invoke(callback, new object[]{item});
}
}
The method above checks if it is executed on UI thread and if yes, it simply adds an item to the listBox2.Items collection; if not, it creates a delegate from itself and invokes that delegate on UI thread.
Next, you'll need to move the code that reads the file to another thread and call AddListBoxItem method. For the sake of readability, let's put that into a separate method:
private void AddFileContentsToList(string fileName)
{
using(var reader = new System.IO.StreamReader(fileName))
{
while(!reader.EndOfStream)
{
var line = reader.ReadLine();
AddListBoxItem(line);
}
}
}
And now we will call the method on a separate thread:
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.Filter = "Text Files|*.txt";
openFileDialog1.Title = "Select a Text file";
openFileDialog1.FileName = "";
DialogResult result = openFileDialog1.ShowDialog();
if (result == DialogResult.OK)
{
var thread = new Thread(AddFileContentsToList);
thread.Start();
}
Hope this helps!
Related
I'm been wondering is there a way to save a file in specific's folder in C#?
The only method that I know is 'SaveFileDialog' but the problems is I want to save files
in folder without showing saveFilesDialog's Box.
saveFilesDialog's Box : is a box that prompts you to Click 'YES' or 'CANCEL'.
Code samples
-In form1
public Form1()
{
InitializeComponent();
}
private string Path =#"D:\Files"; //locaction i wanna stores all the files in
private int i = 0;
private button1_Click(object sender,EventArgs e)
{
i++;
SaveDialogFile save = new SaveDialogFile();
if(Save.
if (save.ShowDialog() != DialogResult.OK)return; //Prompt's Dialog will show
save.Filter = "File Text(*.txt)|*.txt";
save.InitialDirectory = Path;
save.FileName = "txt"+i.ToString();
//Goal : i want 'save.FileName' store in 'Path' without Click 'OK' or Show Prompt Dialog's box
}
Expect Result
[1]: https://i.stack.imgur.com/9JqWO.png
Anyone can help me? I kinda stuck rn :)
This is my full code it's hard to read but you'll get the point
public partial class convertMp3ToWav : Form
{
public convertMp3ToWav()
{
InitializeComponent();
}
BackgroundWorker bw;
string withoutEx;
List<string> song_lists = new List<string>();
private void button1_Click(object sender, EventArgs e)
{
bw = new BackgroundWorker();
bw.DoWork += (obj, ae) => newThread();
bw.RunWorkerAsync();
}
void newThread()
{
Thread th = new Thread
((ThreadStart)(() =>
{
file();
}));
th.SetApartmentState(ApartmentState.STA);
th.Start();
th.Join();
}
void file()
{
string path = #"D:\musics\wav";
Directory.CreateDirectory(path);
FolderBrowserDialog f = new FolderBrowserDialog();
f.ShowDialog();
string[] lists = Directory.GetFiles(f.SelectedPath, "*.*", SearchOption.AllDirectories);
foreach (string list in lists)
{
if (Path.GetExtension(list) == ".mp3")
{
string fn = Path.GetFullPath(list);
withoutEx = Path.GetFileNameWithoutExtension(fn);
song_lists.Add(fn);
Console.WriteLine(withoutEx);
SaveFileDialog save = new SaveFileDialog();
save.Filter = "Wav FIle (*.wav)|*.wav;";
//save.FileName = song_lists[0];
save.FileName = withoutEx;
save.InitialDirectory = path;
if (save.ShowDialog() == DialogResult.OK)
{
using (Mp3FileReader mp3 = new Mp3FileReader(fn))
{
using (WaveStream pcm = WaveFormatConversionStream.CreatePcmStream(mp3))
{
WaveFileWriter.CreateWaveFile(save.FileName, pcm);
}
}
}
}
}
}
}
this code's work pretty well!! but i need to click 'OK' everytime!!
so is there anyway to save file without click 'OK' everytime!!
Conceptually the only thing SaveFileDialog is doing, if you merely click OK when it shows, is changing the file extension*. Use Path.ChangeExtension instead
var pathToSaveWavTo = Path.ChangeExtension(pathToMp3, "wav");
The wav will be saved alongside the mp3. If you want to save it elsewhere, use Path.Combine to build a new path e.g.
pathToSaveWavTo = Path.Combine(#"c:\temp", Path.GetFileName(pathToSaveWavTo));
*I say this because giving it a filter of *.WAV and a filename xxx without the mp3 extension will cause it to give you a filename of xxx.wav when you only click OK, thus xxx.mp3 -> xxx.wav
I met one problem when I tried to copy file.
Error description
I worked with DataGridView and PictureBox.
Deguber of VS 2015 stopped me at
FileStream fs = File.Open(file, FileMode.Open);
in function CopyFile. I cant understand what's wrong i did.
This is some code (C#, .NET 4.5.1) from main form:
static string CopyFile(string file, string to)
{
FileInfo fileInfo = new FileInfo(file);
byte tmp = 0;
string temp = to + "\\" + fileInfo.Name;
FileStream newFile = File.Open(temp, FileMode.Create);
try
{
FileStream fs = File.Open(file, FileMode.Open);
for (int i = 0; i < fileInfo.Length; i++)
{
tmp = (byte)fs.ReadByte();
newFile.WriteByte(tmp);
}
fs.Close();
}
catch (FileNotFoundException ex)
{
MessageBox.Show("Не вдалося найти файл.");
}
newFile.Close();
return temp;
}
private void WriteNewUserToFile(User item, string pathToFile)
{
StreamWriter sw = new StreamWriter(File.Open(#pathToFile, FileMode.Append, FileAccess.Write));
sw.WriteLine(string.Format("{0}, {1}, {2}, {3}, {4}, {5}",
item.Id,
item.Image,
item.FirstName,
item.LastName,
item.Email,
item.Phone));
sw.Close();
}
private void btnAddUser_Click(object sender, EventArgs e)
{
AddUserForm dlg = new AddUserForm();
if (dlg.ShowDialog() == DialogResult.OK)
{
User item = dlg.NewUser;
item.Image = CopyFile(item.Image, "images");
WriteNewUserToFile(item, "data/users.dat");
users.Add(item);
//this.AddNewDataGridRow(item);
}
}
And some code of AddNewUserForm:
public User NewUser
{
get { return newUser; }
set { newUser = value; }
}
private void btnImage_Click(object sender, EventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
if (dlg.ShowDialog() == DialogResult.OK)
{
txtImage.Text = dlg.FileName;
try
{
picboxImage.Image = Image.FromFile(txtImage.Text);
}
catch
{
picboxImage.Image = Image.FromFile(#"images\NoImg.bmp");
}
}
}
private void btnApply_Click(object sender, EventArgs e)
{
NewUser = new User
{
Id = Convert.ToInt32(txtId.Text),
LastName = txtLastName.Text,
FirstName = txtFirstName.Text,
Email = txtEmail.Text,
Phone = txtPhone.Text,
Image = txtImage.Text
};
this.DialogResult = DialogResult.OK;
}
If somebody need all project/code, click here (download VS project).
When you set the Image for the PictureBox using the following code, the call keeps the file handle open. So when you try to open the file again you encounter the exception.
picboxImage.Image = Image.FromFile(txtImage.Text);
According to this accepted answer, when the file handle is closed is unpredictable, in some cases, the handle won't be closed even if you explicitly close the Image.
So you may use the technique in that answer like this, to ensure the file handle is closed properly.
picboxImage.Image = Image.FromStream(new MemoryStream(File.ReadAllBytes(txtImage.Text)));
I have the following code to get Text file as input from the user.I would like to change the code to read the input text file and store each line in array.I am using c# console application.
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog op = new OpenFileDialog();
op.Filter = "CBL files (*.CBL)|*.cbl";
if (op.ShowDialog() == DialogResult.OK)
{
textBox1.Text = op.FileName;
string path = op.FileName;
StringBuilder sb = new StringBuilder();
using (StreamReader sr = new StreamReader(path))
{
while (sr.Peek() >= 0)
{
sb.AppendLine(sr.ReadToEnd());
}
richTextBox1.Text = sb.ToString();
}
}
}
Please help as I am new to coding.
To answer your specific question, you can do the following:
string[] lines = sb.ToString().Split(Environment.NewLine.ToCharArray());
However, this is a lot of overkill for what it is you are actually trying to do. There is a prebuilt method for reading a file into a string array:
string[] lines = File.ReadAllLines(op.FileName);
My issue is that I keep seeing a recurring theme with trying to allow my Notepad clone to save a file. Whenever I try to save a file, regardless of the location on the hard disk, the UnauthorizedAccess Exception continues to be thrown. Below is my sample code for what I've done, and I have tried researching this since last night to no avail. Any help would be greatly appreciated.
//located at base class level
private const string fileFilter = "Text Files|*.txt|All Files|*.*";
private string currentPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
private void MenuFileSaveAs_Click(object sender, RoutedEventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.DefaultExt = "*.txt";
sfd.Filter = fileFilter;
sfd.AddExtension = true;
sfd.InitialDirectory = currentPath;
sfd.RestoreDirectory = true;
sfd.OverwritePrompt = true;
sfd.ShowDialog();
try
{
System.IO.File.WriteAllText(currentPath,TxtBox.Text,Encoding.UTF8);
}
catch (ArgumentException)
{
// Do nothing
}
catch(UnauthorizedAccessException)
{
MessageBox.Show("Access Denied");
}
}
Change the following lines.
...
if (sfd.ShowDialog() != true)
return;
try
{
using (var stream = sfd.OpenFile())
using (var writer = new StreamWriter(stream, Encoding.UTF8))
{
writer.Write(TxtBox.Text);
}
}
...
I hope it helps you.
You need to get the correct path context and file object from the dialog box once the user has hit 'ok'. Namely verify the user actually hit ok and then use the OpenFile property to see what their file selection is:
if (sfd.ShowDialog.HasValue && sfd.ShowDialog)
{
if (sfd.OpenFile() != null)
{
// convert your text to byte and .write()
sfd.OpenFile.Close();
}
}
I've got this code at the start of the form that reads a file that already exists and sets value of 4 textBoxes accordingly to what it's written inside. How do I proceed if the file hasn't yet been created? Any help would be very appreciated.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
FileStream file = new FileStream("cenaEnergentov.txt", FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(file);
sr.ReadLine();
var textLines = File.ReadAllLines("cenaEnergentov.txt");
foreach (var line in textLines)
{
string[] dataArray = line.Split(';');
textBox1.Text = (dataArray[0]);
textBox2.Text = (dataArray[1]);
textBox3.Text = (dataArray[2]);
textBox4.Text = (dataArray[3]);
}
}
If the uper is a false I'd like to proceed with normal script down below that starts with:
public void trackBar1_Scroll(object sender, EventArgs e)
{
......
Use a simple if statement
// I edit this line according to your comment
if(File.Exists(String.Concat("cenaEnergentov".ToUpper(), ".txt"))
{
// do your job
}
else
{
// call appropriate method
trackBar1_Scroll(this,EventArgs.Empty); // for example
}
Try this before you open the file:
var filename = "filename.txt";
if (!File.Exists(filename))
{
File.Create(filename);
}
This won't account for the fact that you're assigning values without checking to see if they exist first. Implementing that is relatively trivial as well.
It also appears that the FileStream and StreamReader are redundant. Just use File.ReadAllLines instead.
The previous solutions will work OK... however they don't really answer the big question:
How do I know when to continue?
The best way would be to use a FileSystemWatcher:
var watcher = new FileSystemWatcher(path, ".txt");
watcher.Created += (sender, e) =>
{
if (e.ChangeType == WatcherChangeTypes.Created)
initForm();
};
Where initForm() is:
void initForm()
{
if(File.Exists(path))
{
// Update form
}
else
{
var watcher = new FileSystemWatcher(path, ".txt");
watcher.Created += (sender, e) =>
{
if (e.ChangeType == WatcherChangeTypes.Created)
initForm();
};
}
}
try this
if(File.Exists("yourFile.txt"))
{
//do what you do
}
else
{
// call appropriate method
}