c# File.WriteAllText overwriting new text on old Text - c#

While inserting new text into Json file its overwriting new text (insted of writing in new line).
Here is my code
public static void WriteToJson()
{
string filepath = #"../../SchemaList.json";
// string filepath = #"C:\HoX_code\learning\Readjson\Readjson\SchemaList.json";
List<SchemaInfo> _oscheme = new List<SchemaInfo>();
_oscheme.Add(new SchemaInfo()
{
AuthenticateCmdlets= "AuthenticateCmdlets1",
GetPowerState= "GetPowerState1",
PowerOff= "PowerOff",
PowerOn= "PowerOn",
});
string json = JsonConvert.SerializeObject(_oscheme.ToArray(), Formatting.Indented);
using (StreamWriter sw = new StreamWriter(#"C:\HoX_code\learning\Readjson\Readjson\SchemaList.json"))
{
sw.Write(json);
}
/// File.WriteAllText(#"../../SchemaList.json", json);
}
Here i use File.WriteAllText & StreamWriter Both are working same

This is intended behaivour. Checking the documentation for File.WriteAllText it says
Creates a new file, write the contents to the file, and then closes the file. If the target file already exists, it is overwritten.
(Emphasis mine)
You're going to want to use File.AppendAllText, it's documentation states
Appends the specified string to the file, creating the file if it does not already exist.
If you want to use streams, then the StreamWriter constructor has a parameter to specify whether or not to append or overwrite text in a file here (Credits go to #vernou, I totally forgot this constructor existed)
But do note that this will result in invalid JSON, as JSON may only have 1 base object and this will result in multiple. If you actually want to append to the serialized JSON object, the I recommend you check out How to Append a json file without disturbing the formatting

Related

Can write to csv file but not append

string pathDesktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string filePath = pathDesktop + "\\mycsvfile.csv";
string delimter = ",";
string a = "Enoelpro---[037,033,0,018,030,012,004,021,009,038,035,053,044,050,074,F,018,010,070,000]<Vulpix>[-][037,034,0,022,020,029,002,008,024,036,046,049,041,057,077,F,018,005,070,000]<Vulpix>[-] cual es mejor??";
List<string[]> test = conv(a,"testrainer");
int length = test.Count;
using (TextWriter writer = File.CreateText(filePath))
{
for (int index = 0; index < length; index++)
{
writer.WriteLine(string.Join(delimter, test[index]));
}
}
So, at the momement, this works fine, except it doesn't keep the old data in the csv file. How can I modify this so instead of deleting the data, it simply appends to the data?
Can you please try with StreamWriter class?
If the file exists, it can be either overwritten or appended to. If the file does not exist, this constructor creates a new file.
Instead using
TextWriter writer = File.CreateText(filePath) try to use
TextWriter writer = new StreamWriter(filePath, true);
If you pass true in constructor it should append text to file.
File.CreateText Method (String)
This method is equivalent to the StreamWriter(String, Boolean)
constructor overload with the append parameter set to false. If the
file specified by path does not exist, it is created. If the file does
exist, its contents are overwritten. Additional threads are permitted
to read the file while it is open.
StreamWriter Constructor (String, Boolean)
Here second parameter, true to append data to the file; false to overwrite the file.
If you check the documentation for each method it cleary say the answers for your questions and also there is a suggetion in case of you need to append the file. Use StreamWriter constructor with path and append parameter (true)

Xml document gets written twice rather than overwriting through an in-memory stream

I'm trying to open an archive Xml file (inside a zip file but not extracting it to a physical directory) in an in-memory stream then making changes to it and saving it. But archive xml file doesn't get overwritten rather it gets two copies of Xml data. One copy is the original copy of Xml data and the other one is changed/modified/edited copy of Xml data in the same archive file.
Here is my code, please help me overwrite the existing Xml data with the changes made rather than having 2 copies of Xml data in the same archive xml file.
static void Main(string[] args)
{
string rootFolder = #"C:\Temp\MvcApplication5\MvcApplication5\Package1";
string archiveName = "MvcApplication5.zip";
string folderFullPath = Path.GetFullPath(rootFolder);
string archivePath = Path.Combine(folderFullPath, archiveName);
string fileName = "archive.xml";
using (ZipArchive zip = ZipFile.Open(archivePath, ZipArchiveMode.Update))
{
var archiveFile = zip.GetEntry(fileName);
if (archiveFile == null)
{
throw new ArgumentException(fileName, "not found in Zip");
}
if (archiveFile != null)
{
using (Stream stream = archiveFile.Open())
{
XDocument doc = XDocument.Load(stream);
IEnumerable<XElement> xElemAgent = doc.Descendants("application");
foreach(var node in xElemAgent)
{
if(node.Attribute("applicationPool").Value!=null)
{
node.Attribute("applicationPool").Value = "MyPool";
}
}
doc.Save(stream);
}
Console.WriteLine("Document saved");
}
}
}
You are first reading the XML data from the stream and then writing to the same stream, which is pointing to the end of the file. To illustrate, let's say the old file contains ABCD and we want to replace this with 123.
The current approach would result in ABCD123, since the stream is pointing to the last char in ABCD.
If you reset the stream to position 0 (stream.Seek(0) before writing the changed file, the file would contain 123D, because it wouldn't reduce the file length.
The solution is to delete your old ZipArchiveEntry and create a new one.
I came across this same issue just now, and I fixed it by adding this first line:
stream.SetLength(0);
xmlDoc.Save(stream);
edit: I see you came across the same solution as you mentioned in the comments of the previous answer. You can add an answer to your own question. It would have helped someone like me :]

c# compare 2 files - create and update functions

It is my first time to write code to function file operations. I need to compare old file with a new file. If the old file name is equal to a new file name, it needs to be overwritten (update). If not equal, creating a new file name. How to do this in a simple and best way?
public void FileCreateOrOverwritten(string file)
{
try
{
if (File.Exists(file))
{
if (file == newFile)
{
//how to replace old file with a new one with new data (xml document)
//need to use filestream
}
else
{
//how to create a new file with new data (xml document)
}
}
.
.
.
}
To (over)write a file,
using (var writer = File.CreateText(file))
{
for (...)
{
writer.WriteLine(...);
}
}
You don't then need to decide if you have an old one to over-write or a new one to create.
From the docs
"This method is equivalent to the StreamWriter(String, Boolean)
constructor overload with the append parameter set to false. If the
file specified by path does not exist, it is created. If the file does
exist, its contents are overwritten"
If you are new to this, note the using

Search and replace contents of text file based on mappings in CSV file in C#

I am new to programming and am working on a C# project that will search and replace certain words in a text file with new values. I have some code that works, but the OLD and NEW values are hardcoded right now. I would like to use an external CSV file as a configuration file so the user can add or update the OLD to NEW mappings at a later time. This is my current code with the OLD and NEW values hardcoded:
try
{
StreamReader file = new StreamReader(inputfullfilepath);
TextWriter writer = new StreamWriter(outputfile);
while ((line = file.ReadLine()) != null)
{
line = line.Replace("OLD1", "NEW1");
line = line.Replace("OLD2", "NEW2");
// etc....
writer.WriteLine(line);
}
file.Close();
File.Move(inputfullfilepath, inputfullfilepath + ".old");
writer.Close();
File.Move(outputfile, outputfilepath + #"\" + inputfilename);
MessageBox.Show("File Scrub Complete", "Success");
}
catch
{
MessageBox.Show("Error: Be sure data paths are valid.", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
The code takes each line of the text file, tries to do a search/replace for all OLD to NEW mappings, then goes to the next line in the text file. The problem I am trying to wrap my head around is being able to make this list of OLD to NEW mappings dynamic based on a CSV (or XML if that would be easier?) configuration file so the user can add new search/replace keywords.
I tried to use the C# Application Settings in Visual Studio (which creates an XML configuration file) but I had a really hard time understanding how to make that work. What's the best way to do this so the values don't have to be hardcoded?
A csv file will work just fine.
I'll create a new Object which i'll call ReplaceObject
public ReplaceObject()
{
public string original;
public string updated;
//ideally you'd use getters and setters, but I'll keep it simple
}
Now we read from the csv
List<ReplaceObject> replaceList = new List<ReplaceObject>
while (reader.peek != -1)
{
string line = reader.readln();
var splitLine = line.split(',');
ReplaceObject rObject = new ReplaceObject();
rObject.original = splitLine[0];
rObject.updated = splitLine[1];
replaceList.add(rObject);
}
Now we go through the list.. and replace
string entireFile = //read all of it
foreach (ReplaceObject o in replaceList)
{
entireFile.Replace(o.original,o.updated);
}
//write it at the end
(Note that my code is missing some checks, but you should get the idea. Also you might want to use a StringBuilder)
My suggestion would be that you use the Settings.cs instead of CSV
It is very easy to use them and involves very less code
e.g. Properties.Settings.Default.Old1;
Here is a walkthrough http://msdn.microsoft.com/en-us/library/aa730869(v=vs.80).aspx
See this example showing how you can use it http://www.codeproject.com/Articles/17659/How-To-Use-the-Settings-Class-in-C

why wont XML read from string? (but will from .txt of same data)

this is the code in question:
using (var file = MemoryMappedFile.OpenExisting("AIDA64_SensorValues"))
{
using (var readerz = file.CreateViewAccessor(0, 0))
{
var bytes = new byte[567];
var encoding = Encoding.ASCII;
readerz.ReadArray<byte>(0, bytes, 0, bytes.Length);
File.WriteAllText("C:\\myFile.txt", encoding.GetString(bytes));
var readerSettings = new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Fragment };
using (var reader = XmlReader.Create("C:\\myFile.txt", readerSettings))
{
This is what myfile.txt looks like:
<sys><id>SCPUCLK</id><label>CPU Clock</label><value>1598</value></sys><sys><id>SCPUFSB</id><label>CPU FSB</label><value>266</value></sys><sys><id>SMEMSPEED</id><label>Memory Speed</label><value>DDR2-667</value></sys><sys><id>SFREEMEM</id><label>Free Memory</label><value>415</value></sys><sys><id>SGPU1CLK</id><label>GPU Clock</label><value>562</value></sys><sys><id>SFREELVMEM</id><label>Free Local Video Memory</label><value>229</value></sys><temp><id>TCPU</id><label>CPU</label><value>42</value></temp><temp><id>TGPU1</id><label>GPU</label><value>58</value></temp>
if i write the data to a txt file on the hard drive with:
File.WriteAllText("C:\\myFile.txt", encoding.GetString(bytes));
then read that same text file with the fragment XmlReader:
XmlReader.Create("C:\\myFile.txt");
it reads it just fine, the program runs and completes like it supposed to, but then if i directly read with the fragment XmlReader like:
XmlReader.Create(encoding.GetString(bytes));
I get exception when run " illegal characters in path" on the XmlReader.Create line.
ive tried writing it to a separate string first and reading that with xmlreader, and it wouldn't help to try to print it to CMD to see what it looks like because CMD wouldnt show the invalid characters im dealing with right?
but oh well i did Console.WriteLine(encoding.GetString(bytes)); and it precisely matched the txt file.
so somehow writing it to the text file is removing some "illegal characters"? what do you guys think?
XmlReader.Create(encoding.GetString(bytes));
XmlReader.Create() interprets your string as the URI where it should read a file from. Instead encapsulate your bytes in a StringReader:
StringReader sr = new StringReader(encoding.GetString(bytes));
XmlReader.Create(sr);
Here:
XmlReader.Create(encoding.GetString(bytes));
you are simply invoking the following method which takes a string representing a filename. However you are passing the actual XML string to it which obviously is an invalid filename.
If you want to load the reader from a buffer you could use a stream:
byte[] bytes = ... represents the XML bytes
using (var stream = new MemoryStream(bytes))
using (var reader = XmlReader.Create(stream))
{
...
}
The method XmlReader.Create() with a single string as argument needs a URI passed and not the XML document as string, please refer to the MSDN. It tries to open a file named "<..." which is an invalid URI. You can pass a Stream instead.
You are passing the xml content in the place where it is expecting a path, as evidenced by the error - illegal characters in path
Use an appropriate overload, and pass a stream - http://msdn.microsoft.com/en-us/library/system.xml.xmlreader.create.aspx

Categories