writing to a specific point in an array file

G

Guest

Hi,
I'm trying to store all of my data into one file (there're about 140 things
to keep track of). I have no problem reading a specific string from the
array file, but I wasn't sure how to replace just one item. I know I can get
the entire array, then save the whole thing (with a for loop and if
statements so that the changed data will be saved), but it seems like a lot
of unnecessary reading and writing. Is there a way to directly save
myArray[whichever number to save] to the correct line in a file?

What I have so far is:
(this one retrieves the entire array that I read from)
public string[] FileToArray(string filename)
{
ArrayList a = new ArrayList();
StreamReader sr = new StreamReader(@"C:\array.txt");
string str;
for (int i = 0; i<139; i++)
{
str = sr.ReadLine();
a.Add(str);
}
sr.Close();
string[] data = new string[a.Count];
a.CopyTo(data);

return data;
}
and then call it with
string[] data = FileToArray(@"C:\array.txt");

And to save the changed info (the 4th index) I use:
string[] data = FileToArray(@"C:\array.txt");
string puppy = "lando";
StreamWriter sw = File.CreateText(@"C:\array.txt");
for (int i = 0; i < 139; i++)
{
if (i != 4){sw.WriteLine(data);}
else {sw.WriteLine(puppy);}
}
sw.Close();

Thanks for any help!
Melanie
 
G

Guest

Hi Melanieab,
there is a way to directly write to a location in the file, I will explain
this below, but I think an easier way to store your data and update the data
would be in an XML file rather than a text file and trying to manipulate
certain parts of it. The XML library provided in .Net is easy to use and is
a really excellent way of storing and retrieving data. You can skip the top
part of the reply if you want to get straight to the XML way at the end of
the reply, I would recommend this way over the way you requested :)

The way to update just the desired row in the file rather than reading
through each line one at a time would be to use Random Access on the file
i.e. to ability to acess any point in the file without having to do a serial
read through the file to reach that position.

What we can basically do is tell the FileStream object to go to a particular
position in your file, to do this we NEED to make the numbers of characters
on a row FIXED so that we can do the following math:

long lngStartingPoint = MaxNumberOfCharactersInARow + 2 * intRowNumber;

so if you say that you will store 5 characters per row, then we need to add
another 2 characters because of the \r\n (newline characters) that gets
written to the end of each line, then:

Start of row0 = (5 + 2) * 0 = 0
Start of row1 = (5 + 2) * 1 = 7
Start of row2 = (5 + 2) * 2 = 14
etc.

<IMPORTANT>
It is important our row size is fixed otherwise we cannot calculate the
start of each line. This means if you choose 5 chars per line then if your
string is "hi" you would need to pad it out with 3 empty spaces to make it 5
chars long "hi "
</IMPORTANT>

Once we know the starting point we need to delete the old data, this is
basically writing an empty string over the current row. Then finally we write
the new data to the file on the same position, so a code example would be:

//define how long a row is i.e. 20 - don't forget to add 2 for your \r\n
int intMaxNoCharsInRow = 20 + 2;

string strNewValue = "this is my new text";

//open the file and move to the correct file location
FileStream fs = new FileStream("c:\\myfile.txt", FileMode.Open);

//move to the desired row in the file, lets say we want to modify the
//10th row i.e. this will be index 9 because it is zero based (you could
modify
the algorithm to not be zero based if you want)

int intDesiredRow = 9;
fs.Seek(intMaxNoCharsInRow * intDesiredRow, SeekOrigin.Begin);

//delete the existing row contents - in other words write a blank string
//over the top of the whole row, not including the \r\n
string strBlankRow = "".PadLeft(intMaxNoCharsInRow-2, ' ');

//need to get a byte array for writing to the file
byte[] arrbytBlank = new byte[strBlankRow.Length];
System.Text.Encoding.ASCII.GetBytes(strBlank, 0, strBlank.Length,
arrbytBlank, 0);
fs.Write(arrbytBlank, 0, arrbytBlank.Length);

//Now move back to the beginning of the line to write the new data
fs.Seek(intMaxNoCharsInRow * intDesiredRow, SeekOrigin.Begin);

//write the new text
byte[] arrbytNewValue = new byte[strNewValue.Length];
System.Text.Encoding.ASCII.GetBytes(strNewValue, 0, strNewValue.Length,
arrbytNewValue,0);
fs.Write(arrbytNewValue, 0, arrbytNewValue.Length);

fs.Close();


========= XML METHOD =============
Probably a lot easier way to do this is just to put your data inside an XML
file, then you will be able to access any node you want by an index i.e.

if you have an xml file (called testxml.xml for example) like:

<myarray>
<arrayitem>the value of the item 1</arrayitem>
<arrayitem>the value of the item 2</arrayitem>
....
<arrayitem>the value of the item 140</arrayitem>
</myarray>

Then if I wanted to modify this file all I would have to say is:

//Load the xml file from disk
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("c:\\testxml.xml");

//get the desired node from the file (i.e. row)
int intIndex = 3; //3 will give us the 4th row as the index is 0 based
XmlNode ndDesired = xmlDoc.DocumentElement.ChildNodes[intIndex];

//store original value if required
string strOriginalValue = ndDesired.InnerText;

//update the text in the node to have the new value
string strNewValue = "my new value";
ndDesired.InnerText = strNewValue;
xmlDoc.Save("c:\\testxml.xml");


Hope this helps.
Mark.






melanieab said:
Hi,
I'm trying to store all of my data into one file (there're about 140 things
to keep track of). I have no problem reading a specific string from the
array file, but I wasn't sure how to replace just one item. I know I can get
the entire array, then save the whole thing (with a for loop and if
statements so that the changed data will be saved), but it seems like a lot
of unnecessary reading and writing. Is there a way to directly save
myArray[whichever number to save] to the correct line in a file?

What I have so far is:
(this one retrieves the entire array that I read from)
public string[] FileToArray(string filename)
{
ArrayList a = new ArrayList();
StreamReader sr = new StreamReader(@"C:\array.txt");
string str;
for (int i = 0; i<139; i++)
{
str = sr.ReadLine();
a.Add(str);
}
sr.Close();
string[] data = new string[a.Count];
a.CopyTo(data);

return data;
}
and then call it with
string[] data = FileToArray(@"C:\array.txt");

And to save the changed info (the 4th index) I use:
string[] data = FileToArray(@"C:\array.txt");
string puppy = "lando";
StreamWriter sw = File.CreateText(@"C:\array.txt");
for (int i = 0; i < 139; i++)
{
if (i != 4){sw.WriteLine(data);}
else {sw.WriteLine(puppy);}
}
sw.Close();

Thanks for any help!
Melanie
 
G

Guest

Hi again,
Thanks so much! I'll definitely look into the xml.
Cheers,
Mel


Mark R. Dawson said:
Hi Melanieab,
there is a way to directly write to a location in the file, I will explain
this below, but I think an easier way to store your data and update the data
would be in an XML file rather than a text file and trying to manipulate
certain parts of it. The XML library provided in .Net is easy to use and is
a really excellent way of storing and retrieving data. You can skip the top
part of the reply if you want to get straight to the XML way at the end of
the reply, I would recommend this way over the way you requested :)

The way to update just the desired row in the file rather than reading
through each line one at a time would be to use Random Access on the file
i.e. to ability to acess any point in the file without having to do a serial
read through the file to reach that position.

What we can basically do is tell the FileStream object to go to a particular
position in your file, to do this we NEED to make the numbers of characters
on a row FIXED so that we can do the following math:

long lngStartingPoint = MaxNumberOfCharactersInARow + 2 * intRowNumber;

so if you say that you will store 5 characters per row, then we need to add
another 2 characters because of the \r\n (newline characters) that gets
written to the end of each line, then:

Start of row0 = (5 + 2) * 0 = 0
Start of row1 = (5 + 2) * 1 = 7
Start of row2 = (5 + 2) * 2 = 14
etc.

<IMPORTANT>
It is important our row size is fixed otherwise we cannot calculate the
start of each line. This means if you choose 5 chars per line then if your
string is "hi" you would need to pad it out with 3 empty spaces to make it 5
chars long "hi "
</IMPORTANT>

Once we know the starting point we need to delete the old data, this is
basically writing an empty string over the current row. Then finally we write
the new data to the file on the same position, so a code example would be:

//define how long a row is i.e. 20 - don't forget to add 2 for your \r\n
int intMaxNoCharsInRow = 20 + 2;

string strNewValue = "this is my new text";

//open the file and move to the correct file location
FileStream fs = new FileStream("c:\\myfile.txt", FileMode.Open);

//move to the desired row in the file, lets say we want to modify the
//10th row i.e. this will be index 9 because it is zero based (you could
modify
the algorithm to not be zero based if you want)

int intDesiredRow = 9;
fs.Seek(intMaxNoCharsInRow * intDesiredRow, SeekOrigin.Begin);

//delete the existing row contents - in other words write a blank string
//over the top of the whole row, not including the \r\n
string strBlankRow = "".PadLeft(intMaxNoCharsInRow-2, ' ');

//need to get a byte array for writing to the file
byte[] arrbytBlank = new byte[strBlankRow.Length];
System.Text.Encoding.ASCII.GetBytes(strBlank, 0, strBlank.Length,
arrbytBlank, 0);
fs.Write(arrbytBlank, 0, arrbytBlank.Length);

//Now move back to the beginning of the line to write the new data
fs.Seek(intMaxNoCharsInRow * intDesiredRow, SeekOrigin.Begin);

//write the new text
byte[] arrbytNewValue = new byte[strNewValue.Length];
System.Text.Encoding.ASCII.GetBytes(strNewValue, 0, strNewValue.Length,
arrbytNewValue,0);
fs.Write(arrbytNewValue, 0, arrbytNewValue.Length);

fs.Close();


========= XML METHOD =============
Probably a lot easier way to do this is just to put your data inside an XML
file, then you will be able to access any node you want by an index i.e.

if you have an xml file (called testxml.xml for example) like:

<myarray>
<arrayitem>the value of the item 1</arrayitem>
<arrayitem>the value of the item 2</arrayitem>
....
<arrayitem>the value of the item 140</arrayitem>
</myarray>

Then if I wanted to modify this file all I would have to say is:

//Load the xml file from disk
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("c:\\testxml.xml");

//get the desired node from the file (i.e. row)
int intIndex = 3; //3 will give us the 4th row as the index is 0 based
XmlNode ndDesired = xmlDoc.DocumentElement.ChildNodes[intIndex];

//store original value if required
string strOriginalValue = ndDesired.InnerText;

//update the text in the node to have the new value
string strNewValue = "my new value";
ndDesired.InnerText = strNewValue;
xmlDoc.Save("c:\\testxml.xml");


Hope this helps.
Mark.






melanieab said:
Hi,
I'm trying to store all of my data into one file (there're about 140 things
to keep track of). I have no problem reading a specific string from the
array file, but I wasn't sure how to replace just one item. I know I can get
the entire array, then save the whole thing (with a for loop and if
statements so that the changed data will be saved), but it seems like a lot
of unnecessary reading and writing. Is there a way to directly save
myArray[whichever number to save] to the correct line in a file?

What I have so far is:
(this one retrieves the entire array that I read from)
public string[] FileToArray(string filename)
{
ArrayList a = new ArrayList();
StreamReader sr = new StreamReader(@"C:\array.txt");
string str;
for (int i = 0; i<139; i++)
{
str = sr.ReadLine();
a.Add(str);
}
sr.Close();
string[] data = new string[a.Count];
a.CopyTo(data);

return data;
}
and then call it with
string[] data = FileToArray(@"C:\array.txt");

And to save the changed info (the 4th index) I use:
string[] data = FileToArray(@"C:\array.txt");
string puppy = "lando";
StreamWriter sw = File.CreateText(@"C:\array.txt");
for (int i = 0; i < 139; i++)
{
if (i != 4){sw.WriteLine(data);}
else {sw.WriteLine(puppy);}
}
sw.Close();

Thanks for any help!
Melanie
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top