I am making a WPF program, and right now I want to be able to open and merge files. I have a button to open a file and I have a button to merge the file, and when I don't implement the "onTextChanged" method both buttons work properly and the files are formatted properly. But if I implement the onTextChanged method and use the merge file button, the previous 'file' gets extra lines in its output.
Open Button Code:
private void Button_Click_1(object sender, RoutedEventArgs e)
{
//Open windows explorer to find file
OpenFileDialog ofd = new OpenFileDialog();
ofd.CheckFileExists = true;
if (ofd.ShowDialog() ?? false)
{
//clears the buffer to open new file
buffer.Clear();
//string to hold line from file
string text;
// Read the file and add it line by line to buffer.
System.IO.StreamReader file =
new System.IO.StreamReader(ofd.FileName);
while ((text = file.ReadLine()) != null)
{
buffer.Add(text);
}
//close the open file
file.Close();
//write each element of buffer as a line in a temporary file
File.WriteAllLines("temp", buffer);
//open that temporary file
myEdit.Load("temp");
}
}
Merge Button Code:
private void merge_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.CheckFileExists = true;
if (ofd.ShowDialog() ?? false)
{
string text;
// Read the file and display it line by line.
System.IO.StreamReader file =
new System.IO.StreamReader(ofd.FileName);
while ((text = file.ReadLine()) != null)
{
buffer.Add(text); // myEdit.AppendText(text);
}
file.Close();
File.WriteAllLines("temp", buffer);
myEdit.Load("temp");
}
}
And when I execute this code, it adds lines in between the last 'file's output:
private void myEdit_TextChanged(object sender, EventArgs e)
{
tCheck.Stop();
tCheck.Start();
}
private void TimerEventProcessor(Object myObject, EventArgs myEventArgs)
{
tCheck.Stop();
Application.Current.Dispatcher.Invoke(new Action(() =>
{
buffer.Clear();
StringBuilder sb = new StringBuilder();
// pulls text from textbox
string bigS = myEdit.Text;
// getText();
for (int i = 0; i < (bigS.Length - 1); i++)
{
if (bigS[i] != '\r' && bigS[i + 1] != '\n')
{
sb.Append(bigS[i]);
}
else
{
buffer.Add(sb.ToString());
sb.Clear();
}
}
}));
}
If you are wondering why I don't use the Split method of a string, it is because I need to open 50+ MB text files and I get an out of memory exception upon using it. I really just want to keep formatting the same when I merge a file.
Wow this is a one line fix.
Original Line of Code:
buffer.Add(sb.ToString());
Changed (Correct) Line of Code:
buffer.Add(sb.ToString().Trim());
The changed worked, however if someone has any idea where these extra lines are coming from that would be helpful.
Related
I need to read a text file containing time stamps and temperatures. The thing is, I need to only show the temperatures in a listBox, spliting the string before displaying it.
So far I've managed to show the text file in the list, but im struggling with removing the timestamps.
My code:
public partial class Form1 : Form
{
OpenFileDialog openFile = new OpenFileDialog();
string line = "";
private void button1_Click(object sender, EventArgs e)
{
if (openFile.ShowDialog() == DialogResult.OK)
{
StreamReader sr = new StreamReader(openFile.FileName);
while(line != null)
{
line = sr.ReadLine();
if(line != null)
{
string[] newLine = line.Split(' ');
listBox1.Items.Add(newLine);
}
}
sr.Close();
}
}
Now the listBox only shows String[] array.
Oh, and also I need to include this in my code:
const int numOfTemp = 50;
double dailyTemp[numOfTemps];
The textfile is in this format:
11:11:11 -10,50
You should take [1] item of the the array after Split:
using System.Linq;
...
private void button1_Click(object sender, EventArgs e)
{
if (openFile.ShowDialog() != DialogResult.OK)
return;
var temps = File
.ReadLines(openFile.FileName)
.Select(line => line.Split(' ')[1]); // we need temperature only
try {
listBox1.BeginUpdate();
// In case you want to clear previous items
// listBox1.Items.Clear();
foreach (string temp in temps)
listBox1.Items.Add(temp);
}
finally {
listBox1.EndUpdate();
}
}
i need to write app to remove specific text line in very large XML file (about 3,5 GB).
I wrote this code:
string directoryPath;
OpenFileDialog ofd = new OpenFileDialog();
private void button1_Click(object sender, EventArgs e)
{
ofd.Filter = "XML|*.xml";
if (ofd.ShowDialog() == DialogResult.OK)
{
directoryPath = Path.GetDirectoryName(ofd.FileName);
textBox2.Text = directoryPath;
textBox1.Text = ofd.SafeFileName;
}
}
private void Replace()
{
StreamReader readerFile = new StreamReader(ofd.FileName, System.Text.Encoding.UTF8);
while (!readerFile.EndOfStream)
{
string stringReplaced;
string replaceResult = textBox2.Text + "\\" + "replace_results";
Directory.CreateDirectory(replaceResult);
StreamWriter writerFile = new StreamWriter(replaceResult + "\\" + textBox1.Text, true);
StringBuilder sb = new StringBuilder();
char[] buff = new char[10 * 1024 * 1024];
int xx = readerFile.ReadBlock(buff, 0, buff.Length);
sb.Append(buff);
stringReplaced = sb.ToString();
stringReplaced = stringReplaced.Replace("line to remove", string.Empty);
writerFile.WriteLine(stringReplaced);
writerFile.Close();
writerFile.Dispose();
stringReplaced = null;
sb = null;
}
readerFile.Close();
readerFile.Dispose();
}
private void button2_Click(object sender, EventArgs e)
{
if (!backgroundWorker1.IsBusy)
{
backgroundWorker1.RunWorkerAsync();
toolStripStatusLabel1.Text = "Replacing in progress...";
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
try
{
Replace();
toolStripStatusLabel1.Text = "Replacing complete!";
}
catch
{
toolStripStatusLabel1.Text = "Error! Replacing aborted!";
}
}
}
it works, but not as well because new file (after remove lines) is bigger than original file and at the end of new file are added some junk (lots of dots), screenshot:
https://images81.fotosik.pl/615/873833aa0e23b36f.jpg
How i can fix my code to make new file the same as old file, only without specific lines?
For a start why keep opening and closing the output file? Keep it open.
Secondly reading blocks – which could lead to "line to remove" being split across blocks – and writing lines is an odd mix.
But I expect your issue is three fold:
You do not set the encoding of the output file.
When you read the buffer (10MB) you may get fewer characters read – the return from ReadBlock. But you always write the complete block. Limit the write to match the amount read (as updated but the replace).
ReadBlock will include end of lines, but WriteLine will add them: either work on blocks or on lines. Mixing will only create problems (and avoid the second issue above).
This leads to code something like:
using (var rdr = OpenReadFile(...))
using (var wtr = OpenWriteFile(...)) {
string line;
while ((line = rdr.ReadLine()) != null) {
line = line.Replace(x, y);
str.WriteLine(line);
}
}
NB Processing XML as text could lead to corrupting the XML (there is no such thing as "invalid XML": either the document is valid XML or it isn't XML, just something that looks a bit like it might be XML). Therefore any such approach needs to be handled with caution. The "proper" answer is to process as XML with the streaming APIs (XmlReader and XmlWriter) to avoid parsing the whole document as one.
I trying do this by XmlTextReader but i have system.xml.xmlexception during read my file, screenshot: https://images82.fotosik.pl/622/d98b35587b0befa4.jpg
Code:
XmlTextReader xmlReader = new XmlTextReader(ofd.FileName);
XmlDocument doc = new XmlDocument();
doc.Load(xmlReader);
What I'm trying to do is read a blank file with no extension. From there, open the file and read it at a certain offset. Here's what I've done for that:
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Title = "Open 234cec File";
if (ofd.ShowDialog() == DialogResult.OK)
{
StreamReader sr = new StreamReader(File.OpenRead(ofd.FileName));
BinaryReader br = new BinaryReader(File.OpenRead(ofd.FileName));
string Texture1 = null;
for (int i = 0x2D670DE; i <= 0x2D6712F; i++)
{
br.BaseStream.Position = i;
Texture1 += br.ReadChar().ToString();
}
br.Close();
textBox1.Text = Texture1;
}
else
{
MessageBox.Show("Error");
}
}
The program works just fine and displays text in a textbox from what it read.
However, I want to be able to write back in the file, from what's in the textbox it read, with a Save button.
i.e. from what I modify in the textbox, then have it save back to my file (at the specified address) WITHOUT changing the file size (like replacing what's there).
The file I'm reading is a kinda big file like 120MB and it doesn't just contain text, it also contains other hex/code and such.
My problem is, I'm clueless as to what line I should do for my Save button after I modify what it read in the Textbox. Any help?
Not sure how to implement this, i am not using SaveFileDialog which i have seen uses OverWritePrompt = true cant seem to get that to work for me.
I am using WPF.
The structure:-
I have a textBox called filePathBox - This contains a file path used from opening an: OpenFileDialog
private void fileBrowser_Click(object sender, RoutedEventArgs e)
{
//Firstly creating the OpenFileDialog
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
//Setting the filter for the file extension of the files as well as the default extension
dlg.DefaultExt = ".txt";
dlg.Filter = "All Files|*.*";
//Display the dialog box by calling the ShowDialog method
Nullable<bool> result = dlg.ShowDialog();
//Grab the file you selected and display it in filePathBox
if (result == true)
{
//Open The document
string filename = dlg.FileName;
filePathBox.Text = filename;
}
}
You can then click a button and the .txt file displays in a textBox called textResult
private void helpfulNotes_Click(object sender, RoutedEventArgs e)
{
if (File.Exists(filePathBox.Text) && System.IO.Path.GetExtension(filePathBox.Text).ToLower() == ".txt")
{
textResult.Text = File.ReadAllText(filePathBox.Text);
}
if (string.IsNullOrWhiteSpace(filePathBox.Text))
{
MessageBox.Show("Please choose a file by clicking on the folder Icon :(");
}
}
Once you have made changes to that text in 'textResult' i have a button to save the text back to the file path that was originally loaded using the OpenFileDialog
private void saveText_Click(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(textResult.Text))
{
saveText.IsEnabled = false;
MessageBox.Show("No Text to save!");
}
else
{
saveText.IsEnabled = true;
string test = textResult.Text;
System.IO.File.WriteAllText(filePathBox.Text, test);
}
//fileSaveIcon.Visibility = Visibility.Visible;
//fileChangedIcon.Visibility = Visibility.Hidden;
}
At the moment it all saves fine, only it doesn't prompt the user saying are you sure you want to overwrite the file.
At the moment i could
load a file for the purpose of this named TestNote.txt into the
filePathBox
Type some text in textResult before even clicking to display the
file
Click save and it would just overwrite TestNote.txt with the text i
just entered without even warning me
Hopefully i have explained this adequately and provided all the code you need
Just add a messagebox to show your alert message before writing to the text file.
private void saveText_Click(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(textResult.Text))
{
saveText.IsEnabled = false;
MessageBox.Show("No Text to save!");
}
else
{
if(MessageBox.Show("are you sure you want to overwrite the file.", "Alert", MessageBoxButtons.YesNo)==DialogResult.Yes)
{
saveText.IsEnabled = true;
string test = textResult.Text;
System.IO.File.WriteAllText(filePathBox.Text, test);
}
}
//fileSaveIcon.Visibility = Visibility.Visible;
//fileChangedIcon.Visibility = Visibility.Hidden;
}
Well, OverWritePrompt is a SaveFileDialog property, which you're not using: you're always using File.WriteAllText(), which always overwrites the target file.
You want to provide a Save function that saves an earlier opened file without prompt, a Save As function that prompts the user for a new filename and also call Save As when saving a new file.
This is implemented like this, pseudo:
private string _currentlyOpenedFile;
public void FileOpen_Click(...)
{
var openFileDialog = new ...OpenFileDialog();
if (openFileDialog.ShowDialog())
{
// Save the filename when opening a file.
_currentlyOpenedFile = openFileDialog.FileName;
}
}
public void FileNew_Click(...)
{
// Clear the filename when closing a file or making a new file.
_currentlyOpenedFile = null;
}
public void FileSave_Click(...)
{
if (_currentlyOpenedFile == null)
{
// New file, treat as SaveAs
FileSaveAs_Click();
return;
}
}
public void FileSaveAs_Click(...)
{
var saveFileDialog = new ...SaveFileDialog();
if (openFileDialog.ShowDialog())
{
// Write the file.
File.WriteAllText(text, openFileDialog.FileName);
// Save the filename after writing the file.
_currentlyOpenedFile = openFileDialog.FileName;
}
}
Here you'll be leveraging the SaveFileDialog's functionality which prompts the user whether they want to overwrite an already existing file.
I have a listbox that displays the names of the files that are opened either with a dragDrop functionality or with an OpenFileDialog, the file paths are stored in the List named playlist, and the listbox only displays the names without paths and extensions. When my form closes, the playlist content is saved to a .txt file. When I open again my application, the content in the text file is stored again in the listbox and the playlist. But when I add new files after re-opening the form, I don't know why it leaves a blank line between the last files and the recently added ones.
This is the code I use to WRITE the content of playlist(List) in the txt file:
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
if(listBox1.Items.Count > 0)
{
StreamWriter str = new StreamWriter(Application.StartupPath + "/Text.txt");
foreach (String s in playlist)
{
str.WriteLine(s);
}
str.Close();
}
This is the code used to READ the same txt file:
private void Form1_Load(object sender, EventArgs e) //Form Load!!!
{
FileInfo info = new FileInfo(Application.StartupPath + "/Text.txt");
if(info.Exists)
{
if (info.Length > 0)
{
System.IO.StreamReader reader = new System.IO.StreamReader(Application.StartupPath + "/Text.txt"); //StreamREADER
try
{
do
{
string currentRead = reader.ReadLine();
playlist.Add(currentRead);
listBox1.Items.Add(System.IO.Path.GetFileNameWithoutExtension(currentRead));
} while (true);
}
catch (Exception)
{
reader.Close();
listBox1.SelectedIndex = 0;
}
}
else
{
File.Delete(Application.StartupPath + "/Text.txt");
}
}
else
{
return;
}
}
The code used to add files to listbox and playlist:
OpenFileDialog ofd = new OpenFileDialog();
ofd.Title = "Select File(s)";
ofd.Filter = "Audio Files (*.mp3, *.wav, *.wma)|*.mp3|*.wav|*.wma";
ofd.InitialDirectory = "C:/";
ofd.RestoreDirectory = false;
ofd.Multiselect = true;
ofd.ShowDialog();
foreach (string s in ofd.FileNames)
{
listBox1.Items.Add(Path.GetFileNameWithoutExtension(s));
playlist.Add(s);
}
listBox1.SelectedIndex = 0;
This is what I get when I add new files after re-opening my form:
Thanks in advance, I hope StackOverflow community can help me!
First of all: debug your code and you'll find the problem yourself :)
Issue is the use of the WriteLine method. The last line you write should use the Write method instead so that you don't have an empty line at the end. Alternatively and easier to implement is to only add non-empty lines to your playlist such like this:
// ...
do
{
string currentRead = reader.ReadLine();
if (!string.IsNullOrWhiteSpace(currentRead)) // ignore empty lines
{
playlist.Add(currentRead);
listBox1.Items.Add(System.IO.Path.GetFileNameWithoutExtension(currentRead));
}
} while (true);
As a side comment: while (true) and using exception handling is a bad approach to end a loop.